看的视频——https://www.bilibili.com/video/av79196096?p=23
单输入单输出
input即为wide模型的输入、又为deep模型的输入 输出仅有一个output
# model = keras.models.Sequential([
# keras.layers.Dense(30, activation = 'relu', input_shape = x_train.shape[1:]),
# keras.layers.Dense(1),
# ])
input = keras.layers.Input(shape=x_train.shape[1:])
#函数式API 这个层次可以像函数一样地去使用它
hidden1 = keras.layers.Dense(30, activation = 'relu')(input)
hidden2 = keras.layers.Dense(30,activation = 'relu')(hidden1)
#wide模型
#input wide模型的输入 hidden2 deep模型的输出
concat = keras.layers.concatenate([input,hidden2])
output = keras.layers.Dense(1)(concat)
#使用model把模型固定下来
model = keras.models.Model(inputs=[input],outputs=[output])
model.summary()
model.compile(loss = "mean_squared_error", optimizer = "adam")
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)
单输入单输出
#子类API实现wide_deep模型
class WideDeepModel(keras.models.Model):
def __init__(self):#初始化函数
super(WideDeepModel,self).__init__()
'''定义模型的层次'''
self.hidden1_layer = keras.layers.Dense(30,activation='relu')
self.hidden2_layer = keras.layers.Dense(30,activation='relu')
self.output_layer = keras.layers.Dense(1)
def call(self,input):
'''
重载此函数 完成模型的正向计算
'''
hidden1 = self.hidden1_layer(input)
hidden2 = self.hidden2_layer(hidden1)
concat = keras.layers.concatenate([input,hidden2])
output = self.output_layer(concat)
return output
#model = WideDeepModel()
model = keras.models.Sequential([
WideDeepModel(),
])
model.build(input_shape=(None,8))
model.summary()
model.compile(loss = "mean_squared_error", optimizer = "adam")
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)
# 函数式API实现wide_deep模型
#多输入 前5个特征为wide模型的输入 后6个特征为deep模型的输入
input_wide = keras.layers.Input(shape=[5])
input_deep = keras.layers.Input(shape=[6])
hidden1 = keras.layers.Dense(30,activation = 'relu')(input_deep)
hidden2 = keras.layers.Dense(30,activation = 'relu')(hidden1)
concat = keras.layers.concatenate([input_wide,hidden2])
output = keras.layers.Dense(1)(concat)
model = keras.models.Model(inputs = [input_wide,input_deep],outputs=[output])
model.summary()
model.compile(loss = "mean_squared_error", optimizer = "adam")
callbacks = [keras.callbacks.EarlyStopping(patience = 5, min_delta = 1e-2)]
x_train_scaled_wide = x_train_scaled[:,:5]#wide取前5个feature
x_train_scaled_deep = x_train_scaled[:,2:]#deep取后6个feature
x_valid_scaled_wide = x_valid_scaled[:,:5]
x_valid_scaled_deep = x_valid_scaled[:,2:]
x_test_scaled_wide = x_test_scaled[:,:5]
x_test_scaled_deep = x_test_scaled[:,2:]
history = model.fit([x_train_scaled_wide,x_train_scaled_deep], y_train, validation_data = ([x_valid_scaled_wide,x_valid_scaled_deep], y_valid), epochs = 100, callbacks = callbacks)
input_wide = keras.layers.Input(shape=[5])
input_deep = keras.layers.Input(shape=[6])
hidden1 = keras.layers.Dense(30,activation = 'relu')(input_deep)
hidden2 = keras.layers.Dense(30,activation = 'relu')(hidden1)
concat = keras.layers.concatenate([input_wide,hidden2])
output = keras.layers.Dense(1)(concat)
output2 = keras.layers.Dense(1)(hidden2)
model = keras.models.Model(inputs = [input_wide,input_deep],outputs=[output,output2])
model.summary()
model.compile(loss = "mean_squared_error", optimizer = "adam")
callbacks = [keras.callbacks.EarlyStopping(patience = 5, min_delta = 1e-2)]
x_train_scaled_wide = x_train_scaled[:,:5]#wide取前5个feature
x_train_scaled_deep = x_train_scaled[:,2:]#deep取后6个feature
x_valid_scaled_wide = x_valid_scaled[:,:5]
x_valid_scaled_deep = x_valid_scaled[:,2:]
x_test_scaled_wide = x_test_scaled[:,:5]
x_test_scaled_deep = x_test_scaled[:,2:]
history = model.fit([x_train_scaled_wide,x_train_scaled_deep],[y_train, y_train], validation_data = ([x_valid_scaled_wide,x_valid_scaled_deep], [y_valid,y_valid]), epochs = 100, callbacks = callbacks)
根据图像选取较好的超参数
#手动实现learning_rate的搜索[1e-4,3e-4,1e-3,3e-3,1e-2,3e-2]
#W = W + grad* learning_rate
learning_rate = [1e-4,3e-4,1e-3,3e-3,1e-2,3e-2]
# 对每个参数都需要定义模型
histories = []
for lr in learning_rate:
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)
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_rate,histories):
print("learning rate:",lr)
plot_learning_curves(history)
RandomizedSearchCV实现超参数搜索 分为三步:
1、tf.keras.model转化为sklearn的model 利用tf.keras.wrappers.scikit_learn.KerasRegressor
def build_model(hidden_layers = 1,#中间层数
layer_size =30,#中间层大小
learning_rate=1e-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 = "mean_squared_error", optimizer = optimizer)# mean_squared_error == mse
return model
sklearn_model = keras.wrappers.scikit_learn.KerasRegressor(build_model)
callbacks = [keras.callbacks.EarlyStopping(patience = 5, min_delta = 1e-2)]
history = sklearn_model.fit(x_train_scaled,y_train,
epochs = 100,
validation_data = (x_valid_scaled,y_valid),
callbacks = callbacks)
2、定义参数集合
以上完成了第一步
下面开始第二步,进行参数集合的定义
要搜索的参数为hidden_layers = 1、layer_size =30、learning_rate=1e-3
from scipy.stats import reciprocal
# f(x) = 1/(x*log(b/a)) a<=x<=b f(x)为概率 reciprocal的分布函数
param_distribution = {
"hidden_layers":[1,2,3,4],
"layer_size":np.arange(1,100),
#希望learning_rate为连续取值 定义区间即可
"learning_rate":reciprocal(1e-4,1e-2),
}
3、使用RandomizedSearchCV实现超参数搜索
from sklearn.model_selection import RandomizedSearchCV
random_search_cv = RandomizedSearchCV(sklearn_model,
param_distribution,
n_iter = 10,#从param_distribution散播出来的参数集合的数目
#cv = 3,通过此修改cross_validation的n
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的机制
#cross_validation:训练集分为n-1份 1份用于验证
#超参搜索完之后再用所有数据训练一次
最后,对得到的模型进行评估
print(random_search_cv.best_params_)#最好的参数
print(random_search_cv.best_score_)#最好的值
print(random_search_cv.best_estimator_)#最好的model
model = random_search_cv.best_estimator_.model
model.evaluate(x_test_scaled, y_test)