深度学习基础知识-[未完]-神经网络超参数调优

参考书籍:《Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 2nd Edition (Aurelien Geron [Géron, Aurélien])》

代码运行环境:win10 + python 3.9.12 + tensorflow 2.12.0 + cpu

使用RandomizedSearchCV

可以通过先做一次随机的搜索,然后再缩小范围继续搜索。但是这样比较耗时。

from scikeras.wrappers import KerasRegressor

# 模型构建
def build_model(n_hidden=1, n_neurons=30, learning_rate=3e-3, input_shape=[8]):
    model = keras.models.Sequential()
    model.add(keras.layers.InputLayer(input_shape=input_shape))
    for layer in range(n_hidden):
        model.add(keras.layers.Dense(n_neurons, activation="relu"))
    model.add(keras.layers.Dense(1))
    optimizer = keras.optimizers.SGD(lr=learning_rate)
    model.compile(loss="mse", optimizer=optimizer)
    return model

# 下面这句会提示KerasRegressor过时
#keras_reg = keras.wrappers.scikit_learn.KerasRegressor(build_model)
keras_reg = KerasRegressor(build_fn=build_model, n_hidden=1, n_neurons=30, learning_rate=3e-3)

# 这是一种特殊的分布
from scipy.stats import reciprocal
from sklearn.model_selection import RandomizedSearchCV

param_distribs = {
    "n_hidden": [0, 1, 2, 3],
    "n_neurons": np.arange(1, 100),
    "learning_rate": reciprocal(3e-4, 3e-2),
}

rnd_search_cv = RandomizedSearchCV(keras_reg, param_distribs, n_iter=10, cv=3)

rnd_search_cv.fit(X_train, y_train, epochs=100,
                  validation_data=(X_valid, y_valid),
                  callbacks=[keras.callbacks.EarlyStopping(patience=10)])
                  
print(rnd_search_cv.best_params_)
print(rnd_search_cv.best_score_)
'''
{'learning_rate': 0.007527490846816864, 'n_hidden': 2, 'n_neurons': 92}
0.7710459058982116
'''

# 获取模型,随后可以保存
model = rnd_search_cv.best_estimator_.model

报错:DeprecationWarning: KerasRegressor is deprecated, use Sci-Keras(https://github.com/adriangb/scikeras) instead. 并且提示xx参数找不到

先pip安装

pip install scikeras

>>> scikeras.__version__
'0.10.0'

然后修改:(主要是要把build_model里要测试的参数写进KerasRegressor,不然会找不到参数)

keras_reg = KerasRegressor(build_fn=build_model, n_hidden=1, n_neurons=30, learning_rate=3e-3)

其他影响因素

有一些用来调超参数的库:Hyperopt, Hyperas, kopt, Talos, Kera Tuner, Scikit-Optimize(skopt), Spearmint, Hyperband, Sklearn-Deap。google cloud ai平台也提供调优服务。

隐藏层数

一些情况下,使用一个隐藏层就足以得到较好结果了,但是对于很复杂的问题,相比浅层网络,深层网络可以使用更少的神经元(指数级地少),并且效果更好。

Transfer learning:举个例子,我已经训练好一个识别图片中人脸的模型,如果我想再训练一个神经网络以识别发型,那我就可以把识别人脸的网络放在底层,重用参数,然后再加层、训练。

所以对于很多复杂问题来说,一般可以通过加层,直到overfitting,以提高准确率。对于更复杂的问题,一般先找别人训练好的、处理类似问题的网络,再训练,这样可以使用较少的训练数据,并且缩短训练时间。

隐藏层上的神经元数目

一般来说,如果每层神经元数目太少,可能学习的能力会下降。我们也不会给每个隐藏层设计单独的神经元数目,因为这样参数太多了,而且每层神经元数目一样,很多时候表现是相同甚至更好的。通常来说,增加层数比增加每层的神经元数目更能提升性能。

学习率和Optimizer

这俩比较要紧,后面会专门写一篇。

可以从小的学习率(如10^-5)开始,到比较大的(如10),每个跑几百次,然后绘制loss曲线,找比较好的那个。

Batch size等一众超参数会影响学习率。如果调整了其他超参数,应该更新学习率。

Batch size

大的batch size可以充分利用gpu,能缩短训练时间,但可能不稳定,最终模型可能不如小batch size的泛化能力强。一种策略是先用大的batch size(有人用到8192也没有generalization gap),然后用learning rate warmup,如果训练不稳定或者最终结果不好,再用小的batch size。

激活函数

隐藏层用ReLU就挺好,输出层则根据任务决定。

循环数

一般不用调,用early stopping。

你可能感兴趣的:(机器学习,深度学习,神经网络,python)