def train_and_evaluate(model, model_name, training_epochs, the_data):
    print('model.metrics_names: {}'.format(model.metrics_names))
    total_steps = (training_epochs * the_data.get_training_mini_batches_per_epoch())
    training_index = pd.RangeIndex(start=0, stop=total_steps, name='Training Step')
    training_metrics_df = pd.DataFrame(data=np.zeros((total_steps, len(model.metrics_names))), columns=model.metrics_names, index=training_index)
    dev_index = pd.RangeIndex(start=0, stop=training_epochs, name='Epoch')
    dev_columns = pd.MultiIndex.from_product(iterables=(the_data.get_dev_set_names(), model.metrics_names), names=('dev set', 'metric'))
    dev_metrics_df = pd.DataFrame(data=np.zeros((training_epochs, (len(the_data.get_dev_set_names()) * len(model.metrics_names)))), columns=dev_columns, index=dev_index)
    print(dev_metrics_df.head())
    steps_per_epoch = the_data.get_training_mini_batches_per_epoch()
    n = 0
    t0 = time.time()
    t00 = time.time()
    for (train_X, train_y, step, epoch) in the_data.get_training_data_generator()(yield_state=True):
        if (epoch > training_epochs):
            print('completed {} training epochs in {:5.2f}s'.format(training_epochs, (time.time() - t0)))
            break
        else:
            print('training on batch {} ({})'.format(step, steps_per_epoch))
            training_metrics = model.train_on_batch(train_X, train_y)
            training_metrics_df.loc[(n, model.metrics_names)] = training_metrics
            n += 1
        if (step == steps_per_epoch):
            print('completed training epoch {} in {:5.2f}s'.format(epoch, (time.time() - t00)))
            print('{} steps per epoch'.format(steps_per_epoch))
            print('{:5.2f}s per step'.format(((time.time() - t00) / steps_per_epoch)))
            print(training_metrics_df.loc[(n - 2):n])
            t00 = time.time()
            print('evaluate the model on the dev set(s)')
            evaluate_dev_sets(epoch=epoch, model=model, the_data=the_data, dev_metrics_df=dev_metrics_df)
            plot_training_and_dev_metrics(training_metrics_df, dev_metrics_df, model_name=model_name, steps_per_epoch=steps_per_epoch, epoch_count=training_epochs, output_fp=(model_name + '.pdf'))
    return (training_metrics_df, dev_metrics_df)
def train_and_evaluate(model, model_name, training_epochs, the_data):
    print('model.metrics_names: {}'.format(model.metrics_names))
    total_steps = (training_epochs * the_data.get_training_mini_batches_per_epoch())
    training_index = pd.RangeIndex(start=0, stop=total_steps, name='Training Step')
    training_metrics_df = pd.DataFrame(data=np.zeros((total_steps, len(model.metrics_names))), columns=model.metrics_names, index=training_index)
    dev_index = pd.RangeIndex(start=0, stop=training_epochs, name='Epoch')
    dev_columns = pd.MultiIndex.from_product(iterables=(the_data.get_dev_set_names(), model.metrics_names), names=('dev set', 'metric'))
    dev_metrics_df = pd.DataFrame(data=np.zeros((training_epochs, (len(the_data.get_dev_set_names()) * len(model.metrics_names)))), columns=dev_columns, index=dev_index)
    print(dev_metrics_df.head())
    steps_per_epoch = the_data.get_training_mini_batches_per_epoch()
    n = 0
    t0 = time.time()
    t00 = time.time()
    for (train_X, train_y, step, epoch) in the_data.get_training_data_generator()(yield_state=True):
        if (epoch > training_epochs):
            print('completed {} training epochs in {:5.2f}s'.format(training_epochs, (time.time() - t0)))
            break
        else:
            print('training on batch {} ({})'.format(step, steps_per_epoch))
            training_metrics = model.train_on_batch(train_X, train_y)
            training_metrics_df.loc[(n, model.metrics_names)] = training_metrics
            n += 1
        if (step == steps_per_epoch):
            print('completed training epoch {} in {:5.2f}s'.format(epoch, (time.time() - t00)))
            print('{} steps per epoch'.format(steps_per_epoch))
            print('{:5.2f}s per step'.format(((time.time() - t00) / steps_per_epoch)))
            print(training_metrics_df.loc[(n - 2):n])
            t00 = time.time()
            print('evaluate the model on the dev set(s)')
            evaluate_dev_sets(epoch=epoch, model=model, the_data=the_data, dev_metrics_df=dev_metrics_df)
            plot_training_and_dev_metrics(training_metrics_df, dev_metrics_df, model_name=model_name, steps_per_epoch=steps_per_epoch, epoch_count=training_epochs, output_fp=(model_name + '.pdf'))
    return (training_metrics_df, dev_metrics_df)