//  [python]
def train(self, train_points, eval_point, epoch_num, ob_step=5, save_path=None, load_path=None):
        if load_path is None:
            self.graph = self.build_graph()

        else:
            self.graph = tf.Graph()

        with self.graph.as_default():
            with tf.Session() as sess:
                if load_path is None:
                    saver = tf.train.Saver()
                    tf.global_variables_initializer().run()
                else:
                    saver = tf.train.import_meta_graph(load_path + '.meta')
                    saver.restore(sess, load_path)

                    self.fm_cols_vals = self.graph.get_operation_by_name("ModelInput/features").outputs[0]
                    self.labels = self.graph.get_tensor_by_name("ModelInput/labels:0")
                    self.training = self.graph.get_tensor_by_name("ModelInput/training_flag:0")

                    self.update = self.graph.get_operation_by_name("Optimizer/GradientDescent")
                    self.loss = self.graph.get_operation_by_name("Loss/Mean").outputs[0]
                    self.output_prob = self.graph.get_operation_by_name("ModelOutput/truediv").outputs[0]

                print("Start Training")
                step = 0
                cnt = 0
                metric_train_loss = 0
                train_pred = []
                train_labels = []
                for ep in range(epoch_num):
                    print("-------------- epoch %d: ----------------" % ep)
                    random.shuffle(train_points)
                    for batch_id, (ft, labels) in DataInput(train_points, self.batch_size, self.fm_cols, self.label_name):

                        feed_vals = {}
                        feed_vals[self.fm_cols_vals] = ft
                        feed_vals[self.labels] = np.expand_dims(np.array(labels), axis=1)
                        feed_vals[self.training] = True

                        _, l, predictions = sess.run(
                            [self.update, self.loss, self.output_prob],
                            feed_dict=feed_vals
                        )
                        metric_train_loss += l * len(labels)
                        cnt += len(labels)
                        train_pred.append(predictions)
                        train_labels.append(labels)

                        if step > 0 and step % ob_step ==0:
                            accuracy = self.accuracy(np.concatenate(train_pred, axis=0),
                                                     np.expand_dims(np.array(list(chain(*train_labels))), axis = 1))

                            print('Minibatch loss at step %d: %f' % (step, metric_train_loss/cnt))
                            print('Minibatch accuracy %.1f %%\n' % (100 * accuracy))

                            train_pred = []
                            train_labels = []
                            metric_train_loss = 0
                            cnt = 0

                        if step == self.epoch_size - 1:
                            step = 0
                            eval_cnt = 0
                            eval_loss = 0
                            eval_pred = []
                            eval_labels = []
                            for batch_id, (ft, labels) in DataInput(eval_point, self.batch_size, self.fm_cols, self.label_name):
                                feed_vals = {}
                                feed_vals[self.fm_cols_vals] = ft
                                feed_vals[self.labels] = np.expand_dims(np.array(labels), axis=1)
                                feed_vals[self.training] = False
                                l, predictions = sess.run([self.loss, self.output_prob], feed_dict=feed_vals)
                                eval_loss += l * len(labels)
                                cnt += len(labels)
                                eval_pred.append(predictions)
                                eval_labels.append(labels)

                            accuracy = self.accuracy(np.concatenate(eval_pred, axis=0),
                                                     np.expand_dims(np.array(list(chain(*eval_labels))), axis=1))

                            print('DEV_SET loss at step %d: %f' % (step, eval_loss/cnt))
                            print('DEV_SET accuracy: %.1f%%\n' % (100%accuracy))

                        else:
                            step += 1

                if save_path is not None:
                    saver.save(sess, save_path)