'Train the model.'

def Train(self):

    assert (self.t_op is not None), 't_op    is    None.'
    assert (self.e_op is not None), 'e_op    is    None.'
    self.SetUpTrainer()
    step = self.t_op.current_step
    stop = self.TrainStopCondition(step)
    stats = []
    collect_predictions = False
    try:
        p = self.output_datalayer[0].proto.performance_stats
        if (p.compute_MAP or p.compute_prec50):
            collect_predictions = True
    except Exception as e:
        pass
    select_model_using_error = self.net.hyperparams.select_model_using_error
    select_model_using_acc = self.net.hyperparams.select_model_using_acc
    select_model_using_map = self.net.hyperparams.select_model_using_map
    select_best = (select_model_using_error or select_model_using_acc or select_model_using_map)
    if select_best:
        best_valid_error = float('Inf')
        test_error = float('Inf')
        best_net = self.DeepCopy()
    dump_best = False
    while (not stop):
        sys.stdout.write(('\rTrain    Step:    %d' % step))
        sys.stdout.flush()
        self.GetTrainBatch()
        losses = self.TrainOneBatch(step)
        if stats:
            for (acc, loss) in zip(stats, losses):
                Accumulate(acc, loss)
        else:
            stats = losses
        step += 1
        if self.ShowNow(step):
            self.Show()
        if self.EvalNow(step):
            sys.stdout.write(('\rStep    %d    ' % step))
            for stat in stats:
                sys.stdout.write(GetPerformanceStats(stat, prefix='T'))
            self.net.train_stats.extend(stats)
            stats = []
            self.Evaluate(validation=True, collect_predictions=collect_predictions)
            self.Evaluate(validation=False, collect_predictions=collect_predictions)
            if select_best:
                valid_stat = self.net.validation_stats[(-1)]
                if (len(self.net.test_stats) > 1):
                    test_stat = self.net.test_stats[(-1)]
                else:
                    test_stat = valid_stat
                if select_model_using_error:
                    valid_error = (valid_stat.error / valid_stat.count)
                    _test_error = (test_stat.error / test_stat.count)
                elif select_model_using_acc:
                    valid_error = (1 - (float(valid_stat.correct_preds) / valid_stat.count))
                    _test_error = (1 - (float(test_stat.correct_preds) / test_stat.count))
                elif select_model_using_map:
                    valid_error = (1 - valid_stat.MAP)
                    _test_error = (1 - test_stat.MAP)
                if (valid_error < best_valid_error):
                    best_valid_error = valid_error
                    test_error = _test_error
                    dump_best = True
                    self.CopyModelToCPU()
                    self.t_op.current_step = step
                    self.net.best_valid_stat.CopyFrom(valid_stat)
                    self.net.train_stat_es.CopyFrom(self.net.train_stats[(-1)])
                    self.net.test_stat_es.CopyFrom(test_stat)
                    best_net = self.DeepCopy()
                    best_t_op = CopyOperation(self.t_op)
            sys.stdout.write('\n')
        if self.SaveNow(step):
            self.t_op.current_step = step
            self.CopyModelToCPU()
            util.WriteCheckpointFile(self.net, self.t_op)
            if dump_best:
                dump_best = False
                if select_model_using_error:
                    print ('Best    valid    error    :    %.4f    Test    error    %.4f' % (best_valid_error, test_error))
                elif select_model_using_acc:
                    print ('Best    valid    acc    :    %.4f    Test    acc    %.4f' % ((1 - best_valid_error), (1 - test_error)))
                elif select_model_using_map:
                    print ('Best    valid    MAP    :    %.4f    Test    MAP    %.4f' % ((1 - best_valid_error), (1 - test_error)))
                util.WriteCheckpointFile(best_net, best_t_op, best=True)
        stop = self.TrainStopCondition(step)
