Могу ли я отправить обратный вызов KerasClassifier?

Я хочу, чтобы классификатор работал быстрее и останавливался раньше, если терпение достигает установленного мной числа. В следующем коде он выполняет 10 итераций подгонки модели.

import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.wrappers.scikit_learn import KerasClassifier
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.constraints import maxnorm
from keras.optimizers import SGD
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load dataset
dataframe = pandas.read_csv("sonar.csv", header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:60].astype(float)
Y = dataset[:,60]
# encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)

calls=[EarlyStopping(monitor='acc', patience=10), ModelCheckpoint('C:/Users/Nick/Data Science/model', monitor='acc', save_best_only=True, mode='auto', period=1)]

def create_baseline(): 
    # create model
    model = Sequential()
    model.add(Dropout(0.2, input_shape=(33,)))
    model.add(Dense(33, init='normal', activation='relu', W_constraint=maxnorm(3)))
    model.add(Dense(16, init='normal', activation='relu', W_constraint=maxnorm(3)))
    model.add(Dense(122, init='normal', activation='softmax'))
    # Compile model
    sgd = SGD(lr=0.1, momentum=0.8, decay=0.0, nesterov=False)
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
    return model

numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=calls)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

здесь ошибка-

RuntimeError: Cannot clone object <keras.wrappers.scikit_learn.KerasClassifier object at 0x000000001D691438>, as the constructor does not seem to set parameter callbacks

Я изменил cross_val_score в следующем-

numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=calls)))
pipeline = Pipeline(estimators)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params={'callbacks':calls})
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

и теперь я получаю эту ошибку-

ValueError: need more than 1 value to unpack

этот код взят отсюда. Код, безусловно, самый точный, который я использовал до сих пор. Проблема что нет model.fit() в любом месте в коде. Это также занимает вечность, чтобы соответствовать. The fit() операция происходит в results = cross_val_score(...) и нет параметров, чтобы бросить обратный вызов там.

как мне это сделать? Кроме того, как запустить модель, обученную тестовому набору?

мне нужно сохранить обученную модель для последующего использования...

3 ответов


чтение отсюда, который является исходным кодом KerasClassifier, вы можете передать ему аргументы fit, и они должны быть использованы. У меня нет вашего набора данных, поэтому я не могу его проверить, но вы можете сказать мне, работает ли это, а если нет, я попытаюсь адаптировать решение. Измените эту строку :

estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=300, batch_size=16, verbose=0, callbacks=[...your_callbacks...])))

небольшое объяснение того, что происходит : KerasClassifier принимает все возможные аргументы для fit, predict, score и использует их соответственно при каждой вызывается метод. Они создали функцию, которая фильтрует аргументы, которые должны идти к каждой из вышеперечисленных функций, которые могут быть вызваны в конвейере. Я думаю, есть несколько fit и predict звонки внутри StratifiedKFold шаг, чтобы тренироваться на разных шпагатах каждый раз.

причина, по которой требуется вечность, чтобы соответствовать, и он подходит 10 раз, потому что один подходит делает 300 эпох, как вы просили. Поэтому KFold повторяет этот шаг за разных складок :

  • звонки fit со всеми параметрами, заданными KerasClassifier (300 эпох и размер партии = 16). Это обучение на 9/10 ваших данных и использование 1/10 в качестве проверки.

EDIT:

Ok, поэтому я потратил время, чтобы загрузить набор данных и попробовать ваш код... Прежде всего, вам нужно исправить "несколько" вещей в вашей сети:

  • ваш вход имеет 60 функций. Вы четко показываете это в своих данных prep:

    X = dataset[:,:60].astype(float)
    

    так зачем вам это:

    model.add(Dropout(0.2, input_shape=(33,)))
    

    пожалуйста, измените на :

    model.add(Dropout(0.2, input_shape=(60,)))
    
  • о ваших целях / ярлыках. Вы изменили цель с исходного кода (binary_crossentropy) к categorical_crossentropy. Но вы не изменили свой массив Y. Поэтому либо сделайте это при подготовке данных:

    from keras.utils.np_utils import to_categorical
    encoded_Y = to_categorical(encoder.transform(Y))
    

    или измените свою цель на binary_crossentropy.

  • теперь размер выхода сети : 122 на последний плотный слой? ваш набор данных, очевидно, имеет 2 категории, так почему вы пытаетесь вывести 122 класса? он не будет соответствовать цели. Пожалуйста, измените свой последний слой на:

    model.add(Dense(2, init='normal', activation='softmax'))
    

    если вы используете categorical_crossentropy или

    model.add(Dense(1, init='normal', activation='sigmoid'))
    

    если вы вернетесь в binary_crossentropy.

Итак, теперь, что ваша сеть будет компилироваться, я мог начать troubleshout.

вот ваше решение

так что теперь я мог бы получить реальное сообщение об ошибке. Оказывается, когда кормишь fit_params=whatever на cross_val_score() функция, вы подаете эти параметры в трубопровод. Чтобы узнать, в какую часть конвейера вы хотите отправить эти параметры, вы должны указать его следующим образом:

fit_params={'mlp__callbacks':calls}

ваша ошибка заключалась в том, что процесс не мог распаковать 'callbacks'.split('__', 1) в 2 значения. На самом деле он искал название шага трубопровода, чтобы применить это.

он должен работать сейчас :)

results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params={'mlp__callbacks':calls})

но, вы должны знать, что здесь происходит... перекрестная проверка фактически вызывает create_baseline() функция для воссоздания модели с нуля 10 раз тренирует ее 10 раз на разных частях набора данных. Так что это не делает эпохи, как вы говорили, это делает 300 эпох 10 раз. Что также происходит в результате использования этого инструмента: поскольку модели всегда отличаются, это означает fit() метод приложен 10 раз на различных моделях, поэтому обратные вызовы также применяются 10 раз и файлы, сохраненные ModelCheckpoint() получить переопределен, и вы окажетесь только с лучшей моделью последнего запуска.

это присуще инструментам, которые вы используете, я не вижу никакого способа обойти это. Это происходит как следствие использования различных общих инструментов, которые не особенно считались используемыми вместе со всеми возможными конфигурациями.


попробуй:

estimators.append(('mlp', 
                   KerasClassifier(build_fn=create_model2,
                                   nb_epoch=300,
                                   batch_size=16,
                                   verbose=0,
                                   callbacks=[list_of_callbacks])))

здесь list_of_callbacks список вызовов, которые вы хотите применить. Вы можете найти детали здесь. Там упоминается, что параметры подаются в KerasClassifier могут быть законными параметрами установки.

также стоит упомянуть, что если вы используете несколько запусков с графическими процессорами, может возникнуть проблема из-за нескольких сообщений об утечках памяти, особенно при использовании theano. Я также заметил, что запуск нескольких fits следовательно может показать результаты которые кажутся не независимыми при использовании sklearn API-интерфейс.

Edit:

попробуйте также:

results = cross_val_score(pipeline, X, encoded_Y, cv=kfold, fit_params = {'mlp__callbacks': calls})

вместо того, чтобы помещать список обратных вызовов в экземпляр оболочки.


вот что я сделал

results = cross_val_score(estimator, X, Y, cv=kfold,
                      fit_params = {'callbacks': [checkpointer,plateau]})

и до сих пор работал