//  [python]
def train(self, data, model=None, starting_epoch=0, clip_grad=True, epochs=1001, input_keep_prob=0.5, output_keep_prob=0.5, learning_rate=0.001 , eval_epoch=20,val_epoch=10, save_epoch=1):

        self.data = data

        if clip_grad:
            jazz_optimizer = self.clip_optimizer(learning_rate,self.jazz_loss)
            classical_optimizer = self.clip_optimizer(learning_rate,self.classical_loss)
        else:
            jazz_optimizer = tf.train.AdamOptimizer(learning_rate).minimize(self.jazz_loss)
            classical_optimizer = tf.train.AdamOptimizer(learning_rate).minimize(self.classical_loss)



        self.sess = tf.Session()

        self.c_in_list, self.c_out_list,self.c_input_lens, self.c_files = self.eval_set('classical')
        self.j_in_list, self.j_out_list,self.j_input_lens, self.j_files = self.eval_set('jazz')

        if model:
            self.load(model)
        else:
            self.sess.run(tf.global_variables_initializer())

        self.summary_op = tf.summary.merge_all()

        self.train_writer = tf.summary.FileWriter(os.path.join(self.dirs['logs_path'], 'train'), graph=self.sess.graph_def)
        self.test_writer = tf.summary.FileWriter(os.path.join(self.dirs['logs_path'], 'test'), graph=self.sess.graph_def)

        classical_batcher = BatchGenerator(self.data["classical"]["X"], self.data["classical"]["Y"], self.batch_count, self.input_size, self.output_size, mini=self.mini)
        jazz_batcher = BatchGenerator(self.data["jazz"]["X"], self.data["jazz"]["Y"], self.batch_count, self.input_size, self.output_size, mini=self.mini)

        self.v_classical_batcher = self.validate("classical")
        self.v_classical_batcher = self.v_classical_batcher.batch()

        self.v_jazz_batcher = self.validate("jazz")
        self.v_jazz_batcher = self.v_jazz_batcher.batch()


        classical_generator = classical_batcher.batch()
        jazz_generator = jazz_batcher.batch()

        print("[*] Initiating training...")

        for epoch in xrange(starting_epoch, epochs):

            classical_epoch_avg = 0
            jazz_epoch_avg = 0

            print("[*] Epoch %d" % epoch)
            for batch in range(classical_batcher.batch_count):
                batch_X, batch_Y, batch_len = classical_generator.next()
                batch_len = [batch_len] * len(batch_X)
                epoch_error, classical_summary, _  =  self.sess.run([self.classical_loss,
                                                         self.summary_op,
                                                         classical_optimizer,
                                                         ], feed_dict={ self.inputs: batch_X,
                                                                                  self.true_classical_outputs: batch_Y,
                                                                                  self.true_jazz_outputs: batch_Y,
                                                                                  self.seq_len: batch_len,
                                                                                  self.input_keep_prob: input_keep_prob,
                                                                                  self.output_keep_prob: output_keep_prob})
                classical_epoch_avg += epoch_error
                print("\tBatch %d/%d, Training MSE for Classical batch: %.9f" % (batch+1, classical_batcher.batch_count, epoch_error))
                self.train_writer.add_summary(classical_summary, epoch*classical_batcher.batch_count + epoch)

            for batch in range(jazz_batcher.batch_count):
                batch_X, batch_Y, batch_len = jazz_generator.next()
                batch_len = [batch_len] * len(batch_X)
                epoch_error, jazz_summary, _  =  self.sess.run([self.jazz_loss,
                                                         self.summary_op,
                                                         jazz_optimizer,
                                                         ], feed_dict={ self.inputs: batch_X,
                                                                                  self.true_jazz_outputs: batch_Y,
                                                                                  self.true_classical_outputs: batch_Y,
                                                                                  self.seq_len: batch_len,
                                                                                  self.input_keep_prob: input_keep_prob,
                                                                                  self.output_keep_prob: output_keep_prob})
                jazz_epoch_avg += epoch_error
                print("\tBatch %d/%d, Training MSE for Jazz batch: %.9f" % (batch+1, jazz_batcher.batch_count, epoch_error))

                self.train_writer.add_summary(jazz_summary, epoch*jazz_batcher.batch_count + epoch)
                # self.validation(epoch)

            print("[*] Average Training MSE for Classical epoch %d: %.9f" % (epoch, classical_epoch_avg/classical_batcher.batch_count))
            print("[*] Average Training MSE for Jazz epoch %d: %.9f" % (epoch, jazz_epoch_avg/jazz_batcher.batch_count))

            if epoch % val_epoch == 0 :
                print("[*] Validating model...")
                self.validation(epoch)

            if epoch % save_epoch == 0 :
                self.save(epoch)

            if epoch % eval_epoch == 0 :
                print("[*] Evaluating model...")
                self.evaluate(epoch)

        print("[*] Training complete.")