Keras: использование данных проверки с помощью fit_generator - PullRequest
0 голосов
/ 17 февраля 2019

Когда я использую fit_generator в Keras, я получаю набор проверки, разделенный на мини-партии, и каждая мини-партия оценивается как прогресс обучения.Я хочу, чтобы данные проверки использовались ровно один раз в конце каждой эпохи.То есть мой код в настоящее время:

def model_fit_generator(self):
    #This does the actual training of the model

    earlystop = EarlyStopping(monitor='val_acc', patience=5, verbose=2, mode='auto')

    self.__model.fit_generator(generator=self.train_generator, 
            validation_data=self.valid_generator, 
            steps_per_epoch=self.s_per_e, 
            epochs=self.epochs,
            validation_steps = self.v_per_e, 
            shuffle=False, 
            verbose=2,
            callbacks=[earlystop])
    model_filename = '_'.join([str(x) for x in now_list]) + '_model.h5'
    self.__model.save(model_filename)

def model_evaluate(self):
    self.model_fit_generator()
    evaluation = self.__model.evaluate_generator(self.valid_generator, self.v_per_e, verbose=0)
    return evaluation

Как мне изменить это, чтобы у меня были данные проверки, использованные один раз, в конце каждой эпохи, чтобы решить, полезна ли ранняя остановка?

РЕДАКТИРОВАТЬ: В ответ на комментарий, вот полный MWE, показывающий, что данные проверки используются одновременно с данными обучения.Обратите внимание, что этот код выдаст ошибку, но он также напечатает номера партий, чтобы показать, что используются оба набора проверки и обучения.Для запуска этого кода вам понадобятся 10 CSV-файлов данных, которые я могу предоставить, но я бы предпочел просто дать вам вывод сразу после этого кода.

from __future__ import division
from __future__ import print_function

from pandas import concat
from pandas import DataFrame
import sys, keras, GPy, GPyOpt
import numpy as np
import pandas as pd
from keras import backend as K
from keras.models import Model
from keras.metrics import binary_crossentropy
from keras.layers import Dense, Input, LSTM, Lambda
from keras.optimizers import Adam
from keras.callbacks import EarlyStopping

class my_model():

    def __init__(self, n_lags=2, hid_dim_1=5, epochs=2, batch_size=1):
        self.n_lags = n_lags
        self.hid_dim_1 = hid_dim_1
        self.epochs = epochs
        self.batch_size = batch_size
        self.train_generator, self.s_per_e, self.valid_generator, self.v_per_e, self.n_vars = self.read_data()
        self.__model = self.model()

    def read_data(self):

        n_vars = 2
        num_sample_minibatches = 6
        num_valid_minibatches = 4
        sample_IDs = range(1, self.batch_size+num_sample_minibatches)
        valid_IDs = range(num_sample_minibatches+1, max(sample_IDs)+num_valid_minibatches+1)
        params = {'batch_size': self.batch_size, 'n_lags': self.n_lags, 'n_vars': n_vars}
        train_generator = DataGenerator(sample_IDs, **params)
        valid_generator = DataGenerator(valid_IDs, **params)
        s_per_e = int(len(sample_IDs) - self.batch_size + 1) #e.g. if you have 1,2,3,4,5,6 then you can create 4 sequences of length 3 (batch_size)
        v_per_e = int(len(valid_IDs) - self.batch_size + 1)

        return train_generator, s_per_e, valid_generator, v_per_e, n_vars

    def model(self):
        #https://github.com/twairball/keras_lstm_vae/blob/master/lstm_vae/vae.py
        a_input = Input(shape=(self.n_lags, self.n_vars,), name='a_input')
        cond_on_this = Input(shape=(self.n_vars,), name="cond_on_this")
        b_lstm = LSTM(self.hid_dim_1)(a_input)
        outputs = Dense(self.hid_dim_1, activation='sigmoid')(b_lstm)
        my_model1 = Model([a_input, cond_on_this], outputs)
        my_model1.compile(optimizer=Adam(lr=0.001), loss=binary_crossentropy)
        return my_model1

    def my_model_fit_generator(self):
        earlystop = EarlyStopping(monitor='val_acc', patience=5, verbose=2, mode='auto')
        self.__model.fit_generator(generator=self.train_generator,
            validation_data=self.valid_generator,
            steps_per_epoch=self.s_per_e,
            epochs=self.epochs,
            validation_steps = self.v_per_e,
            shuffle=False,
            verbose=2,
            callbacks=[earlystop])

    def my_model_evaluate(self):
        self.my_model_fit_generator()
        evaluation = self.__model.evaluate_generator(self.valid_generator, self.v_per_e, verbose=0)
        return evaluation

class DataGenerator(keras.utils.Sequence):

    'Generates data for Keras'
    def __init__(self, list_IDs, batch_size, n_lags, n_vars, shuffle=False):
        'Initialization'
        self.list_IDs = list_IDs
        self.batch_size = batch_size
        self.n_lags = n_lags
        self.n_vars = n_vars
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        'Denotes the number of batches per epoch'
        batches_per_epoch = int(np.floor(len(self.list_IDs) - self.batch_size + 1))
        return batches_per_epoch

    def __getitem__(self, index):
        'Generate one batch of data'
        #Here's my evidence that the validation minibatches are being used during training!
        print('batch number: ', index+1, 'of: ', int(np.floor(len(self.list_IDs) - self.batch_size + 1)))
        indexes = self.indexes[index:(index+self.batch_size)]

        # Find list of IDs
        list_IDs_temp = [self.list_IDs[k] for k in indexes]

        # Generate data
        data, cond_on_this = self.__data_generation(list_IDs_temp)

        return [np.asarray(data), np.asarray(cond_on_this)], np.asarray(cond_on_this)

    def on_epoch_end(self):
        'Updates indexes after each epoch'
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    #From MachineLearningMastery
    def series_to_supervised(self, data, n_out=1, dropnan=True):
        n_vars = 1 if type(data) is list else data.shape[1]
        df = DataFrame(data)
        cols, names = list(), list()

        #input sequence t-n, ..., t-1
        for i in range(self.n_lags, 0, -1): #for i in 3 to 0 not including 0
            cols.append(df.shift(i))
            names += [('var%d(t-%d)' % (j+1, i)) for j in range (self.n_vars)]

        #forecast sequence t, t+1, ..., t+n
        for i in range(0, n_out):
            cols.append(df.shift(-i))
            if i==0:
                names += [('var%d(t)' % (j+1)) for j in range(self.n_vars)]
            else:
                names += [('var%d(t+%d)' % (j+1, i)) for j in range(self.n_vars)]

        agg = concat(cols, axis=1)
        agg.columns = names
        if dropnan:
            agg.dropna(inplace=True)
        return agg

    def __data_generation(self, list_IDs_temp):
        'Generates data containing batch_size samples'
        data_np_array = np.empty((self.batch_size, self.n_vars), dtype=float)

        for i, ID in enumerate(list_IDs_temp):
            #Read in a data file corresponding to this ID; put it into the numpy array.
            data_file = './pollution_' + str(i) + '.csv'
            df_data = pd.read_csv(data_file, sep=",", header=0)
            df_data.columns = ['date','pollution','dew','temp','press','wnd_dir','wnd_spd','snow','rain']
            df_data_vals = df_data[['pollution', 'temp']] #this is shape (24, 2)
            data_np_array[i,] = np.asarray(df_data_vals)

        data_s2s = np.asarray(self.series_to_supervised(data_np_array))

        data_data = data_s2s[:, :int(self.n_vars*self.n_lags)]
        data_cond = data_s2s[:, int(self.n_vars*self.n_lags):]
        data_data = data_data.reshape((data_data.shape[0], self.n_lags, self.n_vars))

        return data_data, data_cond

def run_my_model(n_lags=2, hid_dim_1=5, epochs=2, batch_size=1):

    _my_model = my_model(n_lags=n_lags, hid_dim_1=hid_dim_1, epochs=epochs, batch_size=batch_size)
    mymodel_evaluation = _my_model.my_model_evaluate()
    return mymodel_evaluation

#Bounds for hyperparameters
bounds = [{'name': 'hid_dim_1', 'type': 'discrete', 'domain': (5, 10)}]

#Bayesian Optimization
def f(x):
    evaluation = run_my_model(hid_dim_1 = int(x[:,0]), epochs = 2, batch_size = 1)
    print("binary crossentropy:\t{0}".format(evaluation[0]))
    print(evaluation)
    return evaluation

#Optimizer instance
opt_mymodel = GPyOpt.methods.BayesianOptimization(f=f, domain=bounds, initial_design_numdata=1)

#Run optimizer
opt_mymodel.run_optimization(max_iter=2)
opt_mymodel.x_opt

Соответствующий вывод:

Using TensorFlow backend.
Epoch 1/2
batch number:  1 of:  4
batch number:  1 of:  6
batch number:  2 of:  4
batch number:  2 of:  6
batch number:  3 of:  4
batch number:  3 of:  6
batch number:  4batch number:  4 of:   4
of:  6
batch number:  5 of:  6
batch number:  6 of:  6
Traceback (most recent call last):
  ...Error after this...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...