本文介紹Keras一些常見的驗(yàn)證和調(diào)參技巧,快速地驗(yàn)證模型和調(diào)節(jié)超參。
小技巧:
- CSV數(shù)據(jù)文件加載
- Dense初始化警告
驗(yàn)證與調(diào)參:
- 模型驗(yàn)證(Validation)
- K重交叉驗(yàn)證(K-fold Cross-Validation)
- 網(wǎng)格搜索驗(yàn)證(Grid Search Cross-Validation)
歡迎Follow我的GitHub:https://github.com/SpikeKing

CSV數(shù)據(jù)文件加載
使用NumPy的 loadtxt() 方法加載CSV數(shù)據(jù)文件
- delimiter:數(shù)據(jù)單元的分割符;
- skiprows:略過首行標(biāo)題;
dataset = np.loadtxt(raw_path, delimiter=',', skiprows=1)
Dense初始化警告
Dense初始化參數(shù)的警告:
UserWarning: Update your `Dense` call to the Keras 2 API
`Dense(units=12, activation="relu", kernel_initializer="uniform")`
output = Dense(units=12, init='uniform', activation='relu')(main_input)
將init參數(shù)替換為kernel_initializer參數(shù)即可。
模型驗(yàn)證
在 fit() 中自動(dòng)劃分驗(yàn)證集:
通過設(shè)置參數(shù)validation_split的值(0~1)確定驗(yàn)證集的比例。
實(shí)現(xiàn):
history = self.model.fit(
self.data[0], self.data[1],
epochs=self.config.num_epochs,
verbose=1,
batch_size=self.config.batch_size,
validation_split=0.33,
)
在 fit() 中手動(dòng)劃分驗(yàn)證集:
train_test_split來(lái)源sklearn.model_selection:
-
test_size:驗(yàn)證集的比例; -
random_state:隨機(jī)數(shù)的種子;
通過參數(shù)validation_data添加驗(yàn)證數(shù)據(jù),格式是 數(shù)據(jù)+標(biāo)簽 的元組。
實(shí)現(xiàn):
X_train, X_test, y_train, y_test = \
train_test_split(self.data[0], self.data[1], test_size=0.33, random_state=47)
history = self.model.fit(
X_train, y_train,
validation_data=(X_test, y_test),
epochs=self.config.num_epochs,
batch_size=self.config.batch_size,
verbose=1,
)
交叉驗(yàn)證
K重交叉驗(yàn)證(K-fold Cross-Validation)是常見的模型評(píng)估統(tǒng)計(jì)。
人工模式
交叉驗(yàn)證函數(shù) StratifiedKFold() 來(lái)源于sklearn.model_selection:
-
n_splits:交叉的重?cái)?shù),即N重交叉驗(yàn)證; -
shuffle:數(shù)據(jù)和標(biāo)簽是否隨機(jī)洗牌; -
random_state:隨機(jī)數(shù)種子; -
skf.split(X, y):劃分?jǐn)?shù)據(jù)和標(biāo)簽的索引。
cvscores用于統(tǒng)計(jì)K重交叉驗(yàn)證的結(jié)果,計(jì)算均值和方差。
實(shí)現(xiàn):
X = self.data[0] # 數(shù)據(jù)
y = self.data[1] # 標(biāo)簽
skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=47)
cvscores = [] # 交叉驗(yàn)證結(jié)果
for train_index, test_index in skf.split(X, y): # 索引值
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
history = self.model.fit(
X_train, y_train,
epochs=self.config.num_epochs,
batch_size=self.config.batch_size,
verbose=0,
)
self.loss.extend(history.history['loss'])
self.acc.extend(history.history['acc'])
# scores的第一維是loss,第二維是acc
scores = self.model.evaluate(X_test, y_test)
print('[INFO] %s: %.2f%%' % (self.model.metrics_names[1], scores[1] * 100))
cvscores.append(scores[1] * 100)
cvscores = np.asarray(cvscores)
print('[INFO] %.2f%% (+/- %.2f%%)' % (np.mean(cvscores), np.std(cvscores)))
輸出:
[INFO] acc: 79.22%
[INFO] acc: 70.13%
[INFO] acc: 75.32%
[INFO] acc: 75.32%
[INFO] acc: 80.52%
[INFO] acc: 81.82%
[INFO] acc: 75.32%
[INFO] acc: 85.71%
[INFO] acc: 75.00%
[INFO] acc: 76.32%
[INFO] 77.47% (+/- 4.18%)
Wrapper模式
通過 cross_val_score() 函數(shù)集成模型和交叉驗(yàn)證邏輯。
- 將模型封裝成wrapper,注意使用內(nèi)置函數(shù),而非調(diào)用,沒有括號(hào)
()。 -
epochs即輪次,batch_size即批次數(shù); - StratifiedKFold是K重交叉驗(yàn)證的邏輯;
cross_val_score的輸入是模型wrapper、數(shù)據(jù)X、標(biāo)簽Y、交叉驗(yàn)證cv;輸出是每次驗(yàn)證的結(jié)果,再計(jì)算均值和方差。
實(shí)現(xiàn):
X = self.data[0] # 數(shù)據(jù)
Y = self.data[1] # 標(biāo)簽
model_wrapper = KerasClassifier(
build_fn=create_model,
epochs=self.config.num_epochs,
batch_size=self.config.batch_size,
verbose=0
) # keras wrapper
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=47)
results = cross_val_score(model_wrapper, X, Y, cv=kfold)
print('[INFO] %.2f%% (+/- %.2f%%)' % (np.mean(results) * 100.0, np.std(results) * 100.0))
輸出:
[INFO] 74.74% (+/- 4.37%)
網(wǎng)格搜索驗(yàn)證
網(wǎng)格搜索驗(yàn)證(Grid Search Cross-Validation)用于選擇模型的最優(yōu)超參值。
交叉驗(yàn)證函數(shù) GridSearchCV() 來(lái)源于sklearn.model_selection:
- 設(shè)置超參列表,如optimizers、
init_modes、epochs、batches; - 創(chuàng)建參數(shù)字典,key值是模型的參數(shù),或者wrapper的參數(shù);
- estimator是模型,
param_grid是網(wǎng)格參數(shù)字典,n_jobs是進(jìn)程數(shù); - 輸出最優(yōu)結(jié)果和其他排列組合結(jié)果。
實(shí)現(xiàn):
X = self.data[0] # 數(shù)據(jù)
Y = self.data[1] # 標(biāo)簽
model_wrapper = KerasClassifier(
build_fn=create_model,
verbose=0
) # 模型
optimizers = ['rmsprop', 'adam'] # 優(yōu)化器
init_modes = ['glorot_uniform', 'normal', 'uniform'] # 初始化模式
epochs = np.array([50, 100, 150]) # Epoch數(shù)
batches = np.array([5, 10, 20]) # 批次數(shù)
# 網(wǎng)格字典optimizer和init_mode是模型的參數(shù),epochs和batch_size是wrapper的參數(shù)
param_grid = dict(optimizer=optimizers, epochs=epochs, batch_size=batches, init_mode=init_modes)
grid = GridSearchCV(estimator=model_wrapper, param_grid=param_grid, n_jobs=4)
grid_result = grid.fit(X, Y)
print('[INFO] Best: %f using %s' % (grid_result.best_score_, grid_result.best_params_))
for params, mean_score, scores in grid_result.grid_scores_:
print('[INFO] %f (%f) with %r' % (scores.mean(), scores.std(), params))
輸出:
[INFO] Best: 0.721354 using {'epochs': 100, 'init_mode': 'uniform', 'optimizer': 'adam', 'batch_size': 20}
[INFO] 0.697917 (0.025976) with {'epochs': 50, 'init_mode': 'normal', 'optimizer': 'rmsprop', 'batch_size': 10}
[INFO] 0.700521 (0.006639) with {'epochs': 50, 'init_mode': 'normal', 'optimizer': 'adam', 'batch_size': 10}
[INFO] 0.697917 (0.018414) with {'epochs': 50, 'init_mode': 'uniform', 'optimizer': 'rmsprop', 'batch_size': 10}
[INFO] 0.701823 (0.030314) with {'epochs': 50, 'init_mode': 'uniform', 'optimizer': 'adam', 'batch_size': 10}
[INFO] 0.632813 (0.059069) with {'epochs': 100, 'init_mode': 'normal', 'optimizer': 'rmsprop', 'batch_size': 10}
...
歡迎Follow我的GitHub:https://github.com/SpikeKing
By C. L. Wang
OK, that's all! Enjoy it!