博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Keras(六)keras模型封装转化为sklearn模型、使用超参数搜索
阅读量:4201 次
发布时间:2019-05-26

本文共 10776 字,大约阅读时间需要 35 分钟。

本文将介绍:

  • 超参数搜索简介
  • 手动实现超参数搜索
  • sklearn封装keras模型
  • sklearn实现超参数搜索
  • 实现问题答疑

一,超参数搜索

1,什么是超参数
  • 神经网络有很多训练过程中不变的参数
    • 网络结构参数:层数,每层宽度,每层激活函数等
    • 训练参数:batch_size,学习率,学习率衰减算法等
2,搜索策略
  • 网格搜索
  • 随机搜索
  • 遗传算法搜索
  • 启发式搜索
1)网格搜索
  • 定义n维网格
  • 每个网格对应一组超参数
  • 一组一组尝试参数
    在这里插入图片描述
2)随机搜索
  • 参数的生成方式为随机
  • 可探索的空间更大
    在这里插入图片描述
3)遗传算法搜索
  • 对自然界的模拟
  • A.初始化候选参数集合->训练->得到模型指标作为生存概率
  • B.选择->交叉->变异->产生下一代集合
  • C.重新到A
4)启发式搜索
  • 研究热点-AutoML
  • 使用循环神经网络来生成参数
  • 使用强化学习来进行反馈,使用模型来训练生成参数

二,手动实现超参数搜索

此方法只为了实验,并不推荐使用

#!/usr/bin/env python3# -*- coding: utf-8 -*-import matplotlib as mplimport matplotlib.pyplot as pltimport numpy as npimport sklearnimport pandas as pdimport osimport sysimport timeimport tensorflow as tffrom tensorflow import keras# 1,打印使用的python库的版本信息print(tf.__version__)print(sys.version_info)for module in mpl, np, pd, sklearn, tf, keras:    print(module.__name__, module.__version__)# 2,下载并使用sklearn中的“fetch_california_housing”数据集from sklearn.datasets import fetch_california_housinghousing = fetch_california_housing()print(housing.DESCR)print(housing.data.shape)print(housing.target.shape)# 3,拆分数据集中的数据为 训练数据、验证数据、测试数据from sklearn.model_selection import train_test_splitx_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,在将数据带入到模型之前,先进行预处理-训练、验证、测试数据标准化from sklearn.preprocessing import StandardScalerscaler = StandardScaler()x_train_scaled = scaler.fit_transform(x_train)x_valid_scaled = scaler.transform(x_valid)x_test_scaled = scaler.transform(x_test)# 5,构建wide_deep回归模型、模型层级图、编译模型(添加损失函数、优化器)、添加回调函数# learning_rate: [1e-4, 3e-4, 1e-3, 3e-3, 1e-2, 3e-2]# W = W + grad * learning_ratelearning_rates = [1e-4, 3e-4, 1e-3, 3e-3, 1e-2, 3e-2]histories = []for lr in learning_rates:    model = keras.models.Sequential([        keras.layers.Dense(30, activation='relu',                           input_shape=x_train.shape[1:]),        keras.layers.Dense(1),    ])    optimizer = keras.optimizers.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.append(history)    # 6,得到训练曲线图def plot_learning_curves(history):    pd.DataFrame(history.history).plot(figsize=(8, 5))    plt.grid(True)    plt.gca().set_ylim(0, 1)    plt.show()for lr, history in zip(learning_rates, histories):    print("Learning rate: ", lr)    plot_learning_curves(history)

三,sklearn封装keras模型

1,使用keras内置接口将keras模型转化为sklearn模型

在这里插入图片描述

def build_model(hidden_layers = 1,layer_size = 30,learning_rate = 3e-3):    model = keras.models.Sequential()    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))    optimizer = keras.optimizers.SGD(learning_rate)    model.compile(loss = 'mse', optimizer = optimizer)    return modelsklearn_model = keras.wrappers.scikit_learn.KerasRegressor(build_fn = build_model)callbacks = [keras.callbacks.EarlyStopping(patience=5, min_delta=1e-2)]
2,总结代码
#!/usr/bin/env python3# -*- coding: utf-8 -*-import matplotlib as mplimport matplotlib.pyplot as pltimport numpy as npimport sklearnimport pandas as pdimport osimport sysimport timeimport tensorflow as tffrom tensorflow import keras# 1,打印使用的python库的版本信息print(tf.__version__)print(sys.version_info)for module in mpl, np, pd, sklearn, tf, keras:    print(module.__name__, module.__version__)    # 2,下载并使用sklearn中的“fetch_california_housing”数据集from sklearn.datasets import fetch_california_housinghousing = fetch_california_housing()print(housing.DESCR)print(housing.data.shape)print(housing.target.shape)# 3,拆分数据集中的数据为 训练数据、验证数据、测试数据from sklearn.model_selection import train_test_splitx_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,在将数据带入到模型之前,先进行预处理-训练、验证、测试数据标准化from sklearn.preprocessing import StandardScalerscaler = StandardScaler()x_train_scaled = scaler.fit_transform(x_train)x_valid_scaled = scaler.transform(x_valid)x_test_scaled = scaler.transform(x_test)# 5,构建模型、模型层级图、编译模型(添加损失函数、优化器)、添加回调函数# RandomizedSearchCV# -1-. 转化为sklearn的model# -2-. 定义参数集合# -3-. 搜索参数def build_model(hidden_layers = 1,layer_size = 30,learning_rate = 3e-3):    model = keras.models.Sequential()    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))    optimizer = keras.optimizers.SGD(learning_rate)    model.compile(loss = 'mse', optimizer = optimizer)    return modelsklearn_model = keras.wrappers.scikit_learn.KerasRegressor(build_fn = build_model)callbacks = [keras.callbacks.EarlyStopping(patience=5, min_delta=1e-2)]# 6,训练构建的模型history = sklearn_model.fit(x_train_scaled, y_train,                            epochs = 10,                            validation_data = (x_valid_scaled, y_valid),                            callbacks = callbacks)# 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)

四,sklearn实现超参数搜索

#!/usr/bin/env python3# -*- coding: utf-8 -*-import matplotlib as mplimport matplotlib.pyplot as pltimport numpy as npimport sklearnimport pandas as pdimport osimport sysimport timeimport tensorflow as tffrom tensorflow import keras# 1,打印使用的python库的版本信息print(tf.__version__)print(sys.version_info)for module in mpl, np, pd, sklearn, tf, keras:    print(module.__name__, module.__version__)    # 2,下载并使用sklearn中的“fetch_california_housing”数据集from sklearn.datasets import fetch_california_housinghousing = fetch_california_housing()print(housing.DESCR)print(housing.data.shape)print(housing.target.shape)# 3,拆分数据集中的数据为 训练数据、验证数据、测试数据from sklearn.model_selection import train_test_splitx_train_all, x_test, y_train_all, y_test = train_test_split(housing.data, housing.target, random_state = 7,test_size=0.3)x_train, x_valid, y_train, y_valid = train_test_split(x_train_all, y_train_all, random_state = 11,test_size=0.3)print(x_train.shape, y_train.shape)print(x_valid.shape, y_valid.shape)print(x_test.shape, y_test.shape)# 4,在将数据带入到模型之前,先进行预处理-训练、验证、测试数据标准化from sklearn.preprocessing import StandardScalerscaler = StandardScaler()x_train_scaled = scaler.fit_transform(x_train)x_valid_scaled = scaler.transform(x_valid)x_test_scaled = scaler.transform(x_test)# 5,构建模型、模型层级图、编译模型(添加损失函数、优化器)、添加回调函数# RandomizedSearchCV# 1. 转化为sklearn的model# 2. 定义参数集合# 3. 搜索参数def build_model(hidden_layers = 1,layer_size = 30,learning_rate = 3e-2):    model = keras.models.Sequential()    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))    optimizer = keras.optimizers.SGD(learning_rate)    model.compile(loss = 'mse', optimizer = optimizer)    return modelsklearn_model = keras.wrappers.scikit_learn.KerasRegressor(build_fn = build_model)callbacks = [keras.callbacks.EarlyStopping(patience=5, min_delta=1e-2)]# 6,训练构建的模型# history = sklearn_model.fit(x_train_scaled, y_train,#                             epochs = 10,#                             validation_data = (x_valid_scaled, y_valid),#                             callbacks = callbacks)# # 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)# 8,使用sk-learn实现网格搜索,交叉验证from scipy.stats import reciprocalreciprocal.rvs(1e-4,1e-2,size=10)from scipy.stats import reciprocal# f(x) = 1/(x*log(b/a)) a <= x <= bparam_distribution = {
"hidden_layers":[ 3, 4], "layer_size": np.arange(3, 7), "learning_rate": reciprocal(1e-4, 1e-3), # "layer_size": [1,2,3,4,5,6,7,8,9,10], # "learning_rate": [1e-4, 5e-5, 1e-3, 5e-3, 1e-2],}from sklearn.model_selection import RandomizedSearchCVrandom_search_cv = RandomizedSearchCV(sklearn_model, # 调用的模型 param_distribution,# 参数字典 n_iter = 10, # 输出多少参数集合 cv = 4, # 指定几折交叉验证 n_jobs = 1)# 多少核的并行计算random_search_cv.fit(x_train_scaled, y_train, epochs = 5, validation_data = (x_valid_scaled, y_valid), callbacks = callbacks)# cross_validation: 训练集分成n份,n-1训练,最后一份验证.# 9,打印最佳print(random_search_cv.best_params_) # 最佳参数print(random_search_cv.best_score_) # 最佳得分(为-loss)print(random_search_cv.best_estimator_) # 最佳估计器返回的模型model = random_search_cv.best_estimator_.model# print(model.evaluate(x_test_scaled, y_test))print(model.evaluate(x_test_scaled, y_test,verbose = 0))

另外分享一篇文章:

注意:

  • RandomizedSearchCV 中的参数 “n_iter ”是指定输出多少参数集合
  • RandomizedSearchCV 中的参数 “cv”是指定多少折交叉验证,n-1个测试集,1个验证集
  • 在网格/随机搜索训练中,在每次训练中,训练集为 ( 训练集测试数据 * (cv数 - 1/ cv数)),验证集为(训练集测试数据 * (1/ cv数))
  • 当训练好得到最佳的参数集合后,将所有的训练数据和最佳参数带入模型训练,然后使用x_valid_std去进行验证,总的程序训练的次数也就等于n_iter * cv +1
  • 在tf2.2中,会存每组打印出的测试数据值偏小,使用tf2.1中会恢复正常。

五,实现存在的问题

1,关于RandomizedSearchCV方法中的n_jobs参数不能取非1的值

普通的scikit模型把n_jobs设为大于1的值可以成功,但对于tensorflow的模型来说,把n_jobs设为大于1的数的时候会遇到一个job不能被序列化的问题。此问题暂时还无解。

2,在cross_validation中已经分离出了验证数据,是否还有必要传入validation_data ?

cross_validation用于寻找参数,在找好之后,最后一次会在全部的训练集上训练,在validation_data上验证。

3,在cross_validation每组参数的多次训练中,使用的是最低loss的参数还是最后的参数?

最后将使用每组参数中最后一个epoch的参数验证。

4,当param_distribution 中使用np.arange或reciprocal会报错

可能是新版本tensorflow中的KerasRegressor的问题,新版本的参数在做deep copy的时候出现了问题,导致在拷贝复杂的numpy对象的时候出错。因为deep copy这个操作对用户不可见,所以结论是,退回到sklearn 0.21.3版本,或者在param_distribution中使用普通列表。

5,tensorflow是否可以进行超参数搜索呢?

tensorflow中目前没有这样的库实现,需要自己自行实现。AutoML还是很多其他的复杂算法,不仅仅是超参数搜索,还包括模型结构搜索。这些算法都需要一一实现,目前还没有可用的比较完整的算法库。

6,best_score_为什么是负值?

因为在实现中,搜索的时候会调用KerasRegressor的score函数,而这个函数的实现是返回-loss,而mse(均方误差)是正数,所以score就成了负数。之所以用负数,是因为搜索的过程中希望score越高越好,而mse是越低越好,所以为了统一,就返回负数。

7,为什么RandomizedSearchCV在fit的过程中,在验证穿进去的x_valid_std和y_valid的时候会出现很多的"======"?

可能是版本的原因,有一版(我记得是2.0.0)上会有很多等号,可以用verbose = 0来设置不输出进度。我更新到2.1.0没有发现类似问题。

转载地址:http://gpili.baihongyu.com/

你可能感兴趣的文章
IT行业--简历模板及就业秘籍
查看>>
JNI简介及实例
查看>>
DOM4J使用教程
查看>>
JAVA实现文件树
查看>>
Drools 规则引擎
查看>>
OLTP和OLAP区别
查看>>
JMeter最常用的三种类型的压力测试
查看>>
Hibernate HQL 语法大全(上)
查看>>
深入Java事务的原理与应用
查看>>
CSS单位和CSS默认值大全
查看>>
交大我来了--周末再见了
查看>>
网页中flash wmode属性
查看>>
挑战自我,勇攀高峰
查看>>
神奇的HTML5画图应用
查看>>
flex 滚动条问题
查看>>
软件开发管理中的博奕论
查看>>
计算机认证考试种类
查看>>
SQL in和exists 比较
查看>>
社会性网络服务(SNS)研究
查看>>
鼠标DarkField技术
查看>>