code: func (nn *neuralnetwork2) train(examples []example) error {
  	size := len(examples)
  	batches := size / nn.BatchSize
  
  	var start, end int
  	if nn.BatchSize > size {
  		batches = 1
  		end = size
  		G.WithBatchSize(float64(size))(nn.solver) // set it such that the solver doesn't get confused
  	} else {
  		end = nn.BatchSize
  	}
  
  	for batch := 0; batch < batches; batch++ {
  		for _, ex := range examples[start:end] {
  			nn.feats2vec(ex.features)
  			tid := lookupTransition(ex.transition, nn.transitions)
  
  			if err := G.UnsafeLet(nn.cost, G.S(tid)); err != nil {
  				return err
  			}
  
  			if err := nn.vm.RunAll(); err != nil {
  				return err
  			}
  
  			nn.vm.Reset()
  		}
  		if err := nn.solver.Step(nn.model); err != nil {
  			err = errors.Wrapf(err, "Stepping on the model failed %v", batch)
  			return err
  		}
  
  		if nn.costChan != nil {
  			nn.costChan <- nn.costVal
  		}
  
  		start = end
  		if start >= size {
  			break
  		}
  		end += nn.BatchSize
  		if end >= size {
  			end = size
  		}
  	}
  
  	return nil
  }
docs: // train does one epoch of training. The examples are batched.