Я пытался применить байесовскую оптимизацию к простому CNN для набора рукописных цифр MNIST, и у меня мало признаков того, что он работает. Я пытался выполнить k-кратную проверку, чтобы сгладить шум, но все же не похоже, что оптимизация делает какие-либо шаги в направлении достижения оптимальных параметров. В целом, каковы основные причины, по которым Байесовская оптимизация может потерпеть неудачу? А в моем конкретном случае?
Остальное - просто контекст и фрагменты кода.
Определение модели:
def define_model(learning_rate, momentum):
model = Sequential()
model.add(Conv2D(32, (3,3), activation = 'relu', kernel_initializer = 'he_uniform', input_shape=(28,28,1)))
model.add(MaxPooling2D((2,2)))
model.add(Flatten())
model.add(Dense(100, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(10, activation='softmax'))
opt = SGD(lr=learning_rate, momentum=momentum)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])
return model
Один тренировочный заезд с гиперпараметрами: batch_size = 32, скорость обучения = 1e-2, импульс = 0,9, 10 эпох. (синий = обучение, желтый = проверка).
![enter image description here](https://i.stack.imgur.com/k8hxm.png)
График прямоугольника и усов для точности в 5-кратной перекрестной проверке , с теми же гиперпараметрами, что и выше (чтобы получить представление о разбросе)
![enter image description here](https://i.stack.imgur.com/q50hx.png)
Поиск в сетке с batch_size, равным 32, и в соответствии с 10 эпохой. Я делал это на отдельных оценках, а не в 5 раз, так как спред был недостаточно большим, чтобы испортить результаты.
![enter image description here](https://i.stack.imgur.com/0dRDB.png)
Байесовская оптимизация . Как и выше, batch_size = 32 и 10 эпох. Поиск по тем же диапазонам. Но на этот раз с 5-кратной перекрестной проверкой, чтобы сгладить шум. Предполагается, что go из 100 итераций, но это еще 20 часов.
space = {'lr': hp.loguniform('lr', np.log(np.sqrt(10)*1e-4), np.log(1e-1)), 'momentum': 1 - hp.loguniform('momentum', np.log(np.sqrt(10)*1e-3), np.log(np.sqrt(10)*1e-1))}
tpe_best = fmin(fn=objective, space=space, algo=tpe.suggest, trials=Trials(), max_evals=100)
![enter image description here](https://i.stack.imgur.com/EQvJ7.png)
Испытанные скорости обучения ![enter image description here](https://i.stack.imgur.com/dYS9G.png)
Испытанные импульсы ![enter image description here](https://i.stack.imgur.com/LpDtg.png)
Это выглядело хорошо после 27–49 итераций, но затем снова сошло с ума.
РЕДАКТИРОВАТЬ
Более подробно для тех, кто спросил.
Импорт
# basic utility libraries
import numpy as np
import pandas as pd
import time
import datetime
import pickle
from matplotlib import pyplot as plt
%matplotlib notebook
# keras
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Input, BatchNormalization
from keras.optimizers import SGD
from keras.callbacks import Callback
from keras.models import load_model
# learning and optimisation helper libraries
from sklearn.model_selection import KFold
from hyperopt import fmin, tpe, Trials, hp, rand
from hyperopt.pyll.stochastic import sample
Одиночная оценка
def evaluate_model(trainX, trainY, testX, testY, max_epochs, learning_rate, momentum, batch_size, model=None, callbacks=[]):
if model == None:
model = define_model(learning_rate, momentum)
history = model.fit(trainX, trainY, epochs=max_epochs, batch_size=batch_size, validation_data=(testX, testY), verbose=0, callbacks = callbacks)
return model, history
Крест валидация
def evaluate_model_cross_validation(trainX, trainY, max_epochs, learning_rate, momentum, batch_size, n_folds=5):
scores, histories = list(), list()
# prepare cross validation
kfold = KFold(n_folds, shuffle=True, random_state=1)
# enumerate splits
for trainFold_ix, testFold_ix in kfold.split(trainX):
# select rows for train and test
trainFoldsX, trainFoldsY, testFoldX, testFoldY = trainX[trainFold_ix], trainY[trainFold_ix], trainX[testFold_ix], trainY[testFold_ix]
# fit model
model = define_model(learning_rate, momentum)
history = model.fit(trainFoldsX, trainFoldsY, epochs=max_epochs, batch_size=batch_size, validation_data=(testFoldX, testFoldY), verbose=0)
# evaluate model
_, acc = model.evaluate(testFoldX, testFoldY, verbose=0)
# stores scores
scores.append(acc)
histories.append(history)
return scores, histories
Как мне настроить байесовскую оптимизацию (или случайный поиск)
def selective_search(kind, space, max_evals, batch_size=32):
trainX, trainY, testX, testY = prep_data()
histories = list()
hyperparameter_sets = list()
scores = list()
def objective(params):
lr, momentum = params['lr'], params['momentum']
accuracies, _ = evaluate_model_cross_validation(trainX, trainY, max_epochs=10, learning_rate=lr, momentum=momentum, batch_size=batch_size, n_folds=5)
score = np.log10(1 - np.mean(accuracies))
scores.append(score)
with open('{}_scores.pickle'.format(kind), 'wb') as file:
pickle.dump(scores, file)
hyperparameter_sets.append({'learning_rate': lr, 'momentum': momentum, 'batch_size': batch_size})
with open('{}_hpsets.pickle'.format(kind), 'wb') as file:
pickle.dump(hyperparameter_sets, file)
return score
if kind == 'bayesian':
tpe_best = fmin(fn=objective, space=space, algo=tpe.suggest, trials=Trials(), max_evals=max_evals)
elif kind == 'random':
tpe_best = fmin(fn=objective, space=space, algo=rand.suggest, trials=Trials(), max_evals=max_evals)
else:
raise BaseError('First parameter "kind" must be either "bayesian" or "random"')
return histories, hyperparameter_sets, scores
Тогда как я на самом деле запускаю байесовскую оптимизацию.
space = {'lr': hp.loguniform('lr', np.log(np.sqrt(10)*1e-4), np.log(1e-1)), 'momentum': 1 - hp.loguniform('momentum', np.log(np.sqrt(10)*1e-3), np.log(np.sqrt(10)*1e-1))}
histories, hyperparameter_sets, scores = selective_search(kind='bayesian', space=space, max_evals=100, batch_size=32)