def on_train_finish(**variables):
    global plot
    if plot is not None:
        learning_utils.plot_lines(data=[train_errors, valid_errors], labels=["Training error", "Validation error"],
                                  xlabel="number of epochs",
                                  ylabel=config['loss_type'],
                                  title="training and validation error", suptitle=None, conf=config, additionals=[
                [best_train_i, variables['best_train_error']], [best_valid_i, variables['best_valid_error']]],
                                  path=plot)
    # joblib.dump(valid_errors, 'test.pkl', compress=1) todo
    if config['unit_range']:
        unit_iter_train_error.append(variables['avg_train_error'])
        unit_iter_valid_error.append(variables['avg_valid_error'])

        unit_iter_best_train_error.append(variables['best_train_error'])
        unit_iter_best_valid_error.append(variables['best_valid_error'])
def train_custom(conf, plot_path, debug, verbose, gs_params=None, callbacks=default_callbacks):
    global config, plot, train_errors, valid_errors
    plot = plot_path

    train_errors = np.zeros(conf['epochs'])
    valid_errors = np.zeros(conf['epochs'])
    all_ = list()
    for x in ['all', 'md', 'mir', 'feat_sel', 'random']:
        all = list()
        if x in ('all', 'md', 'mir'):
            training_data, training_targets, valid_data, valid_targets = getData(conf['datasets'], 0, None,
                                                                                 None, type=x)
        elif x == 'random':
            from utils import features
            import random
            conf['features'] = random.sample(np.hstack(features.values()), random.randint(1, 115))
            training_data, training_targets, valid_data, valid_targets = getData(conf['datasets'], 0, conf['features'],
                                                                                 balanced=conf['balanced'], type=x)
        else:
            training_data, training_targets, valid_data, valid_targets = getData(conf['datasets'], 0, conf['features'],
                                                                                 balanced=conf['balanced'], type=x)

        # if there is not enough data available
        conf['datasets'] = training_data.shape[0]
        if conf['units'] is None:
            conf['units'] = [int(math.ceil((training_data.shape[1] + 7) / 2))]
        conf['n_input'] = training_data.shape[1]
        config = conf
        units = [int(math.ceil((training_data.shape[1] + 7) / 2))]
        for i in range(1, 101):
            net = getNet(units, conf['learning_rate'], conf['epochs'], conf['learning_rule'],
                         conf['batch_size'], conf['weight_decay'], conf['dropout_rate'],
                         conf['loss_type'], n_stable=conf['n_stable'], debug=debug, verbose=verbose,
                         callbacks=callbacks,
                         # valid_set=(valid_data, valid_targets)
                         valid_size=conf['ratio']
                         )
            pipeline = learning_utils.getPipeline(training_data, net)
            pipeline.fit(training_data, training_targets)
            all.append(valid_errors)
        all_.append(np.array(all).mean(axis=0))
    learning_utils.plot_lines(data=all_, labels=["all", "md", "mir", "feat_sel", "random"],
                              xlabel="number of epochs",
                              ylabel=config['loss_type'],
                              title="mean training and validation error", suptitle=None,
                              path="learning/nn/plots/comb/test.png")
def train(conf, plot_path, debug, verbose, gs_params=None, callbacks=default_callbacks):
    global config, plot, train_errors, valid_errors
    plot = plot_path
    if 'neural_network__n_iter' in gs_params:
        train_errors = np.zeros(20)
        valid_errors = np.zeros(20)
    else:
        train_errors = np.zeros(conf['epochs'])
        valid_errors = np.zeros(conf['epochs'])
    training_data, training_targets, valid_data, valid_targets, ids = getData(conf['datasets'], conf['ratio'],
                                                                              conf['features'],
                                                                              balanced=conf['balanced'],
                                                                              type=conf['type'], return_ids=True)

    # if there is not enough data available
    conf['datasets'] = training_data.shape[0]
    if conf['units'] is None:
        conf['units'] = [int(math.ceil((training_data.shape[1] + 7) / 2))]
    conf['n_input'] = training_data.shape[1]
    config = conf

    if conf['unit_range'] is not None:
        del conf['units']
        for units in range(conf['unit_range'][0], conf['unit_range'][1] + 1):
            net = getNet([units], conf['learning_rate'], conf['epochs'], conf['learning_rule'],
                         conf['batch_size'], conf['weight_decay'], conf['dropout_rate'],
                         conf['loss_type'], n_stable=conf['n_stable'], debug=debug, verbose=verbose,
                         callbacks=callbacks,
                         valid_size=conf['ratio']
                         )
            pipeline = learning_utils.getPipeline(training_data, net, 'neural_network')
            pipeline.fit(training_data, training_targets)
        learning_utils.plot_lines(data=[unit_iter_train_error, unit_iter_valid_error],
                                  labels=["Training error", "Validation error"],
                                  xlabel="number of hidden units",
                                  ylabel=config['loss_type'],
                                  title="training and validation error", suptitle=None, conf=config, additionals=[
                [np.array(unit_iter_train_error).argmin() + conf['unit_range'][0],
                 np.array(unit_iter_train_error).min()],
                [np.array(unit_iter_valid_error).argmin() + conf['unit_range'][0],
                 np.array(unit_iter_valid_error).min()]],
                                  begin=conf['unit_range'][0],
                                  path="learning/nn/plots/unit_iter/{}_{}.png".format(conf['unit_range'],
                                                                                      conf['epochs']))
        learning_utils.plot_lines(data=[unit_iter_best_train_error, unit_iter_best_valid_error],
                                  labels=["Training error", "Validation error"],
                                  xlabel="number of hidden units",
                                  ylabel=config['loss_type'],
                                  title="training and validation error", suptitle=None, conf=config, additionals=[
                [np.array(unit_iter_best_train_error).argmin() + conf['unit_range'][0],
                 np.array(unit_iter_best_train_error).min()],
                [np.array(unit_iter_best_valid_error).argmin() + conf['unit_range'][0],
                 np.array(unit_iter_best_valid_error).min()]],
                                  begin=conf['unit_range'][0],
                                  path="learning/nn/plots/unit_iter/{}_{}_{}.png".format(conf['unit_range'],
                                                                                         conf['epochs'],
                                                                                         "best"))
    else:
        net = getNet(conf['units'], conf['learning_rate'], conf['epochs'], conf['learning_rule'],
                     conf['batch_size'], conf['weight_decay'], conf['dropout_rate'],
                     conf['loss_type'], n_stable=conf['n_stable'], debug=debug, verbose=verbose,
                     callbacks=callbacks,
                     # valid_set=(np.array(valid_data), valid_targets),
                     valid_size=conf['ratio']
                     )
        pipeline = learning_utils.getPipeline(training_data, net, 'neural_network')
        model = pipeline.fit(training_data, training_targets)
        model.ids = ids
        return model