2-13 超参数搜索代码实战

Margaret ·
更新时间:2024-09-21
· 885 次阅读

一、 概念

               在神经网络中有许多参数,而超参数就是神经网络训练过程中不变的参数,也就是在训练之前设置好的参数,

               而不是训练

               得到的参数。比如说,神经网络结构:层数,宽度,激活函数、训练参数:batch_size,学习率,学习率衰减算法。

               而超参数搜索就是让机器自己选择合适的超参数的值,以省下我们大量的精力。

二、 搜索策略

               超参数的搜索策略一共有以下几种

               2.1 网格搜索

               2.2 随机搜索

               2.3 遗传算法搜索

               2.4 启发式搜索

          2.1 网格搜索

                         假设我们需要对两个超参数进行搜索,那我们就设定一个二维矩阵,x 轴对应超参数 1 ,y 轴对应超参数 2,

                         机器就会将两个超参数的值两两组合,找到最合适的值和最合适的搭配。

                         我们可以总结如下:

                          定义 n 维方格

                         每个方格对应一组超参数

                         一对一对尝试

          2.2 随机搜索

                         在选定的参数范围内随机生成超参数数组,并对超参数进行组合,以达到最优解。

                        总结如下:

                        生成方式随机

                        可探索的空间更大

          2.3 遗传算法搜索

                        初始化候选超参数集合

                        训练筛选 -> 得到模型的生存概率

                        淘汰并选择一部分

                        交叉 -> 变异

                        得到下一代

                        迭代

          2.4 启发式搜索

                       启发式搜索是以前研究热点 —— AutoML 的一部分,在其的子领域神经网络结构搜索

                       原理如下:(具体原理有空的话会再写一篇博文)

                       使用循环神经网络来生成参数,生成参数后根据参数生成新的网络结构来进行训练

                       训练后,使用强化学习的思维,生成反馈机制,再来训练我们的循环神经网络

                       

三、 手工实现超参数搜索代码实战

              手工实现的话,缺点在于比较繁琐,下面展示的只是一个参数的修改,而实际上我们需要修改的远远不止一个参数

          3.1 修改模型配置与训练代码

               代码的基本框架与 wide and deep 模型代码实战 是一致的,这里只编写代码的不同之处

               需要修改的地方为,模型搭建以及模型训练部分,并且因为有多个模型训练,需要建立 histories 数组,

               以便保存多个结果,从代码上来说,就是模型层次搭建到 fit 部分

# 这里用学习率 learning rate 来做演示,取值范围为 [1e-4,3e-4,1e-3,3e-3,1e-2,3e-2] # 1e-4 = 1 * 10^(-4) # W = W + grad * learning_rate # 定义 learning_rate 集合,重复训练模型 n 次 learning_rates = [1e-4,3e-4,1e-3,3e-3,1e-2,3e-2] histories = [] for lr in learning_rates: # 实现多输入 这里使用函数式的方法 # 我们假设我们将前 5 个 feature 输入 wide 模型,后 6 个 feature 输入 deep 模型,一共 8 个 feature ,也就是说, wide and deep 有交集部分 input_wide = keras.layers.Input(shape=[5]) input_deep = keras.layers.Input(shape=[6]) # deep model 有两个隐藏层 hidden1 = keras.layers.Dense(30,activation='relu')(input_deep) hidden2 = keras.layers.Dense(30,activation='relu')(hidden1) # 合并两个模型的输出 concat = keras.layers.concatenate([input_wide,hidden2]) # 模型的输入为两个模型的输入,输出只有一个 model = keras.models.Model(inputs = [input_wide,input_deep], outputs = [output]) # 因为我们改变的是学习率,我们只需要将模型的 optimizer 修改即可 optimizer = keras.optimizer.SGD(lr) model.compile(loss="mean_squared_error",optimizer=optimizer) callbacks = [keras.callbacks.EarlyStopping( patience= 5,min_delta=1e-2)] history = model.fit(x_train_scaled,y_train, validation_data = (x_valid_scaled,y_valid), epochs = 100, callbacks = callbacks) # 最后,因 histories 不只一个,需要进行保存 histories.append(history)           3.2 图表展示代码修改

                        因为有多个模型需要展示,展示代码也需要略微修改,多添加一个循环即可

                        最好把 learning_rate  和 history 组合显示,方便对比

# 设定图表展示函数,将模型训练的接受对象 history 输入到该函数中 def plot_learning_curves(history): # 将 history 获取到的训练过程的参数变化的字典变为矩阵形状,并设定图的尺寸大小为 8 和 5 pd.DataFrame(history.history).plot(figsize=(8,5)) # 显示网格 plt.grid(True) # 设置坐标范围 ,设定 y 为 0~1 之间 plt.gca().set_ylim(0,1) # 显示这张图 plt.show() #多添加一个循环即可 for lr, history in zip(learning_rates, histories): print("Learning rate: ", lr) plot_learning_curves(history)           3.3 删除模型评测部分

                     因为模型评测是针对最后一个模型,对我们帮助不大,直接删除

                     将以下代码删除

# 输入测试集的特征与标签 model.evaluate(x_test_scaled,y_test) 四、 keras 库实现超参数搜索-随机搜索           4.1 资源库导入 import matplotlib as mpl import matplotlib.pyplot as plt import numpy import sklearn import pandas as pd import os import sys import time import tensorflow as tf from tensorflow import keras print(tf.__version__) print(sys.version_info) for module in mpl,np,pd,sklearn,tf,keras: print(module.__name__,module.__version__)                        4.2 导入数据 from sklearn.datasets import fetch_california_housing housing = fetch_california_housing() print(housing.DESCR) print(housing.data.shape) print(housing.target.shape)             4.3 数据划分 from skleran.model_selection import train_test_split x_train_all,x_test,y_train_all,y_test = train_test_split( housing.data,housing.target,random_state = 7) x_train,x_valid,y_train,y_valid=train_test_split( x_train_all,y_train_all,random_state = 11) print(x_train.shape,y_train.shape) print(x_valid.shape,y_valid.shape) print(x_test.shape,y_test.shape)              4.4 数据标准化 from skleran.preprocessing import StandarScaler scaler = StandarScaler() x_train_scaled = scaler.fit_transform(x_train) x_valid_scaled = scaler.transform(x_valid) x_test_scaled = scaler.transform(x_test)                            4.5 将模型设定为函数 API # 设定模型的默认值 # hodden_layer: 模型隐藏层默认为 1 # layer_size: 神经元的数量默认为 30 # learning_rate:3e-3 def build_model(hodden_layer = 1, layer_size = 30, learning_rate = 3e-3): # 使用 Sequential 的方式在函数内构件模型 model = keras.models.Sequential() # 设定输入层,输入的矩阵形状为 x_train.shape model.add(keras.layers.Dense(layer_size,activation = 'relu', input_shape=x_train.shape[1:])) # 设定隐藏层生成循环 for _ in range(hidden_layers -1): model.add(keras.layers.Dense(layer_size, activation = 'relu')) # 添加输出层 model.add(keras.layers.Dense(1)) # 使用 keras.optimizers.SGD API 来修改模型中的学习率 optimizer = keras.optimizer.SGD(learning_rate) # 编译模型 model.compile(loss='mse'.optimizer = optimizer) return model               4.6 进行试训练 # 引用函数,建立函数 sklearn_model = keras.wrappers.scikit_learn.KerasRegressor( build_fn = build_model) # 设定早停函数 callbacks = [keras.callbacks.EarlyStopping(patience=5,min_delta=1e-2)] # 试训练 history = sklern_model.fit(x_train_scaled,y_train, epochs = 10, validation_data = (x_valid_scaled,y_valid), callbacks = callbacks)                 4.7 可视化 def plot_learning_curves(history): pd.DataFrame(history.history).plot(figsize = (8,5)) plt.grid(True) plt.gca().set_ylim(0,1) plt.show() plot_learning_curves(history)                              4.8 设定超参数字典 # 加入分布库 reciprocal # f(x) = 1/(x*log(b/a)) a<= x <= b from scipy.stats import reciprocal param_distribution = [ "hidden_layers":[1,2,3,4], "layer_size":np.arange(1,100), "learning_rate":reciprocal(1e-4,1e-2), ]                4.9 搜索参数 from sklearn.model_selection import RandomizedSearchCV # RandomizedSearchCV 参数说明 # sklearn model: 训练模型 # param_distribution: 字典参数 # n_iter: 训练次数 # cv: 交叉验证的折数,默认为 5 # n_jobs: 运行的 CPU 数量,-1 默认为 1 random_search_cv = RandomizedSearchCV(sklearn_model, param_distribution, n_iter = 10, cv = 3, n_jobs =1) random_search_cv.fit(x_train_scaled,y_train,epochs = 100, validation_data = (x_valid_scaled,y_valid), callbacks = callbacks ) # cross_validation: 训练集分成 n 份,n-1 训练,最后一份验证 print(random_search_cv.best_params_) print(random_search_cv.best_score_) print(random_search_cv.best_estimator_)                 4.10 显示最佳的模型以及最佳的精确 model = random_search_cv.best_estimator_.model model.evalute(x_test_scaled,y_test)
作者:XMing666



实战 超参数 参数

需要 登录 后方可回复, 如果你还没有账号请 注册新账号