Tensorflow之keras
keras
-
keras是基于python的高级神经网路API.keras必须有后端才可以运行,后端可以切换。它以特别方便快速试验,帮助用户以最少的时间验证自己的想法,帮助用户以最少的时间验证自己的想法。
-
Tf-keras和keras联系
它们都基于同一套API,keras程序可以通过改导入方式轻松转为tf.keras程序 反之不能成立,因为tf.keras有其他特性,而keras不能满足 它们有相同的JOSN和HDF5模型序列化格式和语义
-
tf-keras和keras区别
1.tf.keras全面支持动态图模式 2.只用keras.Sequential和keras.Model时没影响。自定义Model内部运算逻辑的时候有影响 3.TF.keras支持基于tf.data模型训练,支持TPU训练,支持tf.distribution中分布式策略。Tf.keras可以与tensorflow中estimator集成,tf.keras可以保存SavedModel
1.分类问题+回归问题
-
分类问题其实是预测当前所属类别,通过模型输出的是它的概率分布,而回归问题预测的是值,模型输出的是一个实际值。
-
回归问题,预测预测值与真实值之间差距。
-
目标函数
为什么需要目标函数? 这是机器学习特性所决定的,大部分机器学习都是逐步调整参数得到最优解,从而逼近目标值。而目标函数可以帮助衡量模型好坏程度。 比如一个分类问题:它能衡量目标类别与当前预测的差距。通过One-hot编码,把一个正整数变为向量表达(生成一个长度不小于正整数向量,只有正整数的位置处于1,其余处于0)。
-
分类问题常用方式:
-
平方差损失
平方差损失距离: 预测值: [0.2, 0.7, 0.1] 真实值: [0, 0, 1] 损失函数值: [(0-0)^2 + (0.7-0)^2 + (0.1-1)^2]*0.5 = 0.65
-
交叉熵损失
-
2.Tf.kears分类模型示例
-
我们采用tensorflow内置图片数据集进行示例:fashion_mnist
- 导包:
# tf.keras 分类模型 import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline import numpy as np 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__) """ 2.1.0 sys.version_info(major=3, minor=7, micro=5, releaselevel='final', serial=0) matplotlib 3.3.3 numpy 1.19.5 pandas 1.2.1 sklearn 0.24.0 tensorflow 2.1.0 tensorflow_core.keras 2.2.4-tf """
- 数据导入
# 导入内置图片数据集 fashion_mnist = keras.datasets.fashion_mnist # 训练集 测试集 (x_train_all,y_train_all),(x_test,y_test) = fashion_mnist.load_data() # 拆分前5000张作为验证集,剩下作为训练集 x_valid, x_train = x_train_all[:5000], x_train_all[5000:] y_valid, y_train = y_train_all[:5000], y_train_all[5000:] # 打印大小 print(x_valid.shape, y_valid.shape) print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape) """ (5000, 28, 28) (5000,) (55000, 28, 28) (55000,) (10000, 28, 28) (10000,) """
- 展示一张图片
def show_single_image(img_arr): """ 展示查看一张图片 """ plt.imshow(img_arr,cmap="binary") show_single_image(x_train[0])
- 展示多个图片集合
def show_imgs(n_rows, n_cols,x_data,y_data,class_names): """ 展示图片集 class_names 索引 """ # assert len(x_data) == len(y_data) # 验证行和列的乘积不能大于样本数 assert n_rows * n_cols < len(x_data) # 定义图大小 plt.figure(figsize=(n_cols * 1.4, n_rows * 1.6)) # 对每行每列放图片 for row in range(n_rows): for col in range(n_cols): index = n_cols * row + col # 绘制子图 plt.subplot(n_rows, n_cols, index+1) # 展示数据 interpolation缩放图片 plt.imshow(x_data[index], cmap="binary",interpolation="nearest") # 关闭坐标系 plt.axis("off") # 配置title plt.title(class_names[y_data[index]]) plt.show() class_names = ["T-shirt","Trouser","Pullover","Dress","Coat","Sandal","Shirt","Sneaker","Bag", "Ankle boot"] # 显示3行5列 show_imgs(3, 5,x_train,y_train,class_names)
- 使用tf.keras.models.Sequential 进行分类
# 使用tf.keras.models.Sequential 进行分类 # 写法1: # Sequential对象 model = keras.models.Sequential() # 往对象添加层次: # 添加输入层,并将其展开 : 我输入的是28*28矩阵,用Flatten进行展平,成为一个一维向量 model.add(keras.layers.Flatten(input_shape=[28,28])) # 添加全连接层 单元数:300(它是用层次发掘神经网络,上一层神经单元和下一层神经单元一一进行连接) activation表示激活函数 model.add(keras.layers.Dense(300, activation="relu")) # 再添加全连接层 单元数:100 model.add(keras.layers.Dense(100, activation="relu")) model.add(keras.layers.Dense(10, activation="softmax")) # relu: y = max(0,x) # softmax: 将向量变成概率分布输出 # x=[x1,x2,x3] # y = [e^x1/sum , e^x2/sum, e^x3/sum], sum = e^x1 + e^x2 + e^x3 # 写法2: # model = keras.models.Sequential([ # keras.layers.Flatten(input_shape=[28,28]), # keras.layers.Dense(300, activation="relu"), # keras.layers.Dense(100, activation="relu"), # keras.layers.Dense(10, activation="softmax") # ]) # 因为y是一个index值,我们需要将y 经过one_hot 变成一个向量 # 如果y是一个向量用categorical_crossentropy即可 # optimizer 为求解优化器方法: 这里使用adam # metrics : 把损失函数,优化方法加入 keras.optimizers.SGD(lr = 0.1) model.compile(loss="sparse_categorical_crossentropy",optimizer="adam", metrics=["accuracy"])
- 查看模型层数
# 查看模型层数 model.layers """ [<tensorflow.python.keras.layers.core.Flatten at 0x7fa359641750>, <tensorflow.python.keras.layers.core.Dense at 0x7fa359641950>, <tensorflow.python.keras.layers.core.Dense at 0x7fa359645490>, <tensorflow.python.keras.layers.core.Dense at 0x7fa359645050>] """
- 查看模型概况
# 查看模型概况 model.summary() """ Model: "sequential_7" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= flatten_7 (Flatten) (None, 784) 0 _________________________________________________________________ dense_21 (Dense) (None, 300) 235500 _________________________________________________________________ dense_22 (Dense) (None, 100) 30100 _________________________________________________________________ dense_23 (Dense) (None, 10) 1010 ================================================================= Total params: 266,610 Trainable params: 266,610 Non-trainable params: 0 _________________________________________________________________ """
- 开始训练
# 整个层数解析: # 第一层:是样本数 乘以 784 矩阵 # 第二层:进入全连接层 将其变成样本数 * 300 矩阵 (变换过程: 【样本数 乘以 784 】 * W(权重, W为[784,300]矩阵) + b(偏执, b为300长的向量)) # 第三层,第四层也是如上方式实现 # 训练模型 # epochs:将训练集运行10次 # validation_data:对训练集进行验证 history = model.fit(x_train,y_train, epochs=10,validation_data=(x_valid,y_valid)) """ Train on 55000 samples, validate on 5000 samples Epoch 1/10 55000/55000 [==============================] - 5s 95us/sample - loss: 2.0006 - accuracy: 0.7321 - val_loss: 0.6174 - val_accuracy: 0.8032 Epoch 2/10 55000/55000 [==============================] - 4s 81us/sample - loss: 0.5339 - accuracy: 0.8135 - val_loss: 0.4758 - val_accuracy: 0.8424 Epoch 3/10 55000/55000 [==============================] - 5s 99us/sample - loss: 0.4774 - accuracy: 0.8339 - val_loss: 0.4359 - val_accuracy: 0.8538 Epoch 4/10 55000/55000 [==============================] - 5s 91us/sample - loss: 0.4468 - accuracy: 0.8447 - val_loss: 0.4878 - val_accuracy: 0.8392 Epoch 5/10 55000/55000 [==============================] - 5s 95us/sample - loss: 0.4269 - accuracy: 0.8511 - val_loss: 0.4067 - val_accuracy: 0.8642 Epoch 6/10 55000/55000 [==============================] - 5s 93us/sample - loss: 0.4076 - accuracy: 0.8551 - val_loss: 0.3962 - val_accuracy: 0.8728 Epoch 7/10 55000/55000 [==============================] - 5s 97us/sample - loss: 0.4024 - accuracy: 0.8594 - val_loss: 0.3951 - val_accuracy: 0.8690 Epoch 8/10 55000/55000 [==============================] - 5s 98us/sample - loss: 0.3881 - accuracy: 0.8627 - val_loss: 0.4112 - val_accuracy: 0.8626 Epoch 9/10 55000/55000 [==============================] - 5s 95us/sample - loss: 0.3734 - accuracy: 0.8691 - val_loss: 0.4331 - val_accuracy: 0.8550 Epoch 10/10 55000/55000 [==============================] - 5s 95us/sample - loss: 0.3594 - accuracy: 0.8727 - val_loss: 0.3709 - val_accuracy: 0.8800 history.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() plot_learning_curves(history)
3.分类模型归一化
- 训练后数据的准确率达到81%-87%之间,而在图像分类有个很有效的方式用于提高准确率,那就是归一化
- 这里使用sklearn进行归一化,采用x = (x - avg) /std方式进行归一化(avg是均值,std是方差)
- 代码:
- 导入图片数据集
# 这里使用sklearn进行归一化
# 导入内置图片数据集
fashion_mnist = keras.datasets.fashion_mnist
# 训练集 测试集
(x_train_all,y_train_all),(x_test,y_test) = fashion_mnist.load_data()
# 拆分前5000张作为验证集,剩下作为训练集
x_valid, x_train = x_train_all[:5000], x_train_all[5000:]
y_valid, y_train = y_train_all[:5000], y_train_all[5000:]
print(x_valid.shape, y_valid.shape)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
"""
(5000, 28, 28) (5000,)
(55000, 28, 28) (55000,)
(10000, 28, 28) (10000,)
"""
- 打印训练集最大值
print(np.max(x_train), np.min(x_train))
# 255 0
- 归一化:训练集,验证集,测试集
# 归一化
#
# x = (x - avg) /std
# avg是均值
# std是方差
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# 训练集做归一化
# 归一化只能进行二维矩阵归一化,因为x_train是三维矩阵,首先将它转为二维矩阵,然后归一化,然后再转回三维矩阵
x_train_scaled = scaler.fit_transform(x_train.astype(np.float32).reshape(-1,1)).reshape(-1,28,28)
# 验证集做归一化
x_valid_scaled = scaler.transform(x_valid.astype(np.float32).reshape(-1,1)).reshape(-1,28,28)
# 测试集做归一化
x_test_scaled = scaler.transform(x_test.astype(np.float32).reshape(-1,1)).reshape(-1,28,28)
- 此时再打印训练集最大值
print(np.max(x_train_scaled), np.min(x_train_scaled))
# 2.0231433 -0.8105136
- 使用tf.keras.models.Sequential 进行分类(同上)
- 训练模型,这里训练集和验证集为归一化的数据集
history = model.fit(x_train_scaled,y_train, epochs=10,validation_data=(x_valid_scaled,y_valid))
"""
Train on 55000 samples, validate on 5000 samples
Epoch 1/10
55000/55000 [==============================] - 5s 95us/sample - loss: 0.4586 - accuracy: 0.8323 - val_loss: 0.3790 - val_accuracy: 0.8560
Epoch 2/10
55000/55000 [==============================] - 6s 104us/sample - loss: 0.3526 - accuracy: 0.8701 - val_loss: 0.3577 - val_accuracy: 0.8718
Epoch 3/10
55000/55000 [==============================] - 5s 95us/sample - loss: 0.3154 - accuracy: 0.8826 - val_loss: 0.3366 - val_accuracy: 0.8758
Epoch 4/10
55000/55000 [==============================] - 5s 93us/sample - loss: 0.2916 - accuracy: 0.8909 - val_loss: 0.3162 - val_accuracy: 0.8854
Epoch 5/10
55000/55000 [==============================] - 5s 91us/sample - loss: 0.2722 - accuracy: 0.8972 - val_loss: 0.3546 - val_accuracy: 0.8720
Epoch 6/10
55000/55000 [==============================] - 5s 92us/sample - loss: 0.2593 - accuracy: 0.9024 - val_loss: 0.3358 - val_accuracy: 0.8800
Epoch 7/10
55000/55000 [==============================] - 5s 90us/sample - loss: 0.2395 - accuracy: 0.9095 - val_loss: 0.3286 - val_accuracy: 0.8894
Epoch 8/10
55000/55000 [==============================] - 5s 91us/sample - loss: 0.2318 - accuracy: 0.9122 - val_loss: 0.3225 - val_accuracy: 0.8900
Epoch 9/10
55000/55000 [==============================] - 5s 88us/sample - loss: 0.2172 - accuracy: 0.9185 - val_loss: 0.3302 - val_accuracy: 0.8930
Epoch 10/10
55000/55000 [==============================] - 5s 89us/sample - loss: 0.2101 - accuracy: 0.9202 - val_loss: 0.3380 - val_accuracy: 0.8942
"""
- 查看训练结果图
-
由上面可以知道归一化的训练后结果准确率:达到最高92%
-
验证准确率
model.evaluate(x_test_scaled, y_test) """ 10000/10000 [==============================] - 0s 37us/sample - loss: 0.3633 - accuracy: 0.8853 [0.3633375147640705, 0.8853] """ loss 0.3633375147640705 准确度:0.8853
4.回调函数
-
当你在训练模型时候,你中间可以做一些事情,常用回调函数:
EarlyStopping 当模型训练时候当你的loss在不断下降时候,我们可以提前停掉 ModelCheckpoint 将在每个epoch后保存模型到filepath TensorBoard 模型训练过程中可以显示训练结果状态
-
只需在model.fit调用回调函数
# Tensorboard logdir = "./callbacks" # 创建目录 if not os.path.exists(logdir): os.mkdir(logdir) # 定义输出文件 output_model_file = os.path.join(logdir, "fashion_mnist_model.h5") callbacks = [ keras.callbacks.TensorBoard(logdir), # save_best_only保存最好模型 keras.callbacks.ModelCheckpoint(output_model_file, save_best_only=True), # patience 当下一次训练比上一次训练小的时候,连续发生多少次,就要停掉 # min_delta 阈值, 当前次训练比上一次训练要低于这个值会停掉 keras.callbacks.EarlyStopping( patience=5,min_delta=1e-3) ] history = model.fit(x_train_scaled,y_train, epochs=10,validation_data=(x_valid_scaled,y_valid),callbacks=callbacks)
-
命令行中callbacks目录下执行tensorboard --logdir=callbacks --host=0.0.0.0获取详细信息
- 可以调整Smoothing调整平滑度
- GRAPHS查看训练模型
5.回归模型
??
6.神经网络如何进行训练
- 采用训练方式为梯度下降方式,首先进行求导,找到每个变量变化方向,然后更新参数。上面我们的分类模型为一个三层,伴随层次越来越深。就成深度神经网络。
7.激活函数
-
在我们构建模型层次时候,使用激活函数,激活函数有如下
它们将非线性特性引入到我们的网络中。其主要目的是将模型中一个节点的输入信号转换成一个输出信号。该输出信号现在被用作堆叠中下一个层的输入。
8.归一化和批归一化
-
其实它就是将输入输出数据进行规整,使它的均值为0,方差为1。常用归一化种类
Min-max归一化: x*=(x-min)/(max-min) Z-score归一化: x*=(x-μ)/σ
-
批归一化
将每层激活值都做归一化
-
为什么归一化有效,如下图:
图一没有做归一化处理导致theta1与theta2值是不一样的。这样由于theta1与theta2值是不一样,等高线看起来像是一个椭圆,(等高线解释:等高线表示在这条等高线的值都是一样的),但是目标函数值是一样的。因为它是椭圆,在计算法向量时候没有指向圆心,导致训练轨迹非常曲折。 经过归一化如图二,当然训练速度也会更快
11.Dropout
-
Dropout是一种在深度学习环境中应用的正规化手段。它是这样运作的:在一次循环中我们先随机选择神经层中的一些单元并将其临时隐藏,然后再进行该次循环中神经网络的训练和优化过程。在下一次循环中,我们又将隐藏另外一些神经元,如此直至训练结束。Dropout
-
Droupout作用
作用可以防止过拟合: (什么是过拟合:训练集上表现很好,测试集上不好)---造成这样原因可能模型参数比较多,容量太大,使得模型记住样本(测试集的样本和训练集样本是不一样),不能泛华
12.Keras实现深度神经网络
-
还是以上面为例只不过我们添加学习网络时,增加20层
# 使用tf.keras.models.Sequential 进行分类 # Sequential对象 model = keras.models.Sequential() # 往对象添加层次: # 添加输入层,并将其展开 : 我输入的是28*28矩阵,用Flatten进行展平,成为一个一维向量 model.add(keras.layers.Flatten(input_shape=[28,28])) # 添加20层学习网络 for _ in range(20): model.add(keras.layers.Dense(100, activation="relu")) model.add(keras.layers.Dense(10,activation="softmax"))
-
此时打印训练结果图
由上图我们发现,相对于之前学习曲线图在初期时候(x轴0到3之间),目标函数趋势是不怎么发生变化的。而把目标函数迭代到x轴为4时,目标函数才变化的陡峭,导致原因是: 1. 由于是深度学习,参数比较多,训练不充分。 2. 梯度消失:一般发生在深度学习网络里,导致发生原因为链式法则,(链式法则用于复合函数求导f(g(x)), 函数g(x)输出是f函数输入)。对于低层次神经网络,它的复合函数嵌套较多,梯度一层一层传导下去,到低层次因符合函数嵌套较多,就有可能导致梯度消失,导致训练结果比较平滑,梯度消失
-
批归一化实现
- 在keras实现批归一化较为简单,只需要在添加训练模型时候添加 如下代码
model.add(keras.layers.BatchNormalization())
- 批归一化添加也可以放在激活函数之前
model.add(keras.layers.Dense(100))# 添加学习层次 model.add(keras.layers.BatchNormalization())# 批归一化 model.add(keras.layers.Activation('relu'))# 添加激活后面
- 训练结果
我们可以看到进行批归一化训练的模型,没有了上述问题。我们通过批归一化缓解梯度消失,通过归一化是数据更加规整,这样计算更加准确
-
激活函数更改带来效果
- selu 自带归一化的激活函数
model.add(keras.layers.Dense(100, activation="selu"))
- 训练效果 训练时间优于BatchNormalization
-
dropout添加
- 一般我们添加dropout都是在最后几层添加
# rate为添加单元比例 # 添加AlphaDropout model.add(keras.layers.AlphaDropout(rate=0.5)) # 添加普通Dropout方式 model.add(keras.layers.Dropout(rate=0.5))
AlphaDropout 比 Dropout更加强大,AlphaDropout优势:均值和方差不变,归一化的性质也不变。
-
Dropout使用,根据自己训练场景定,如果没有出现过拟合现象可以不用使用Dropout
13. wide和Deep模型
-
用于分类和回归的模型,并应用到了 Google Play 的应用推荐中。wide and deep 模型的核心思想是结合线性模型的记忆能力(memorization)和 DNN 模型的泛化能力(generalization),在训练过程中同时优化 2 个模型的参数,从而达到整体模型的预测能力最优。
-
稀疏特征:
-
什么是稀疏特征:
比如我们100维度的向量(x1,x2,....x100),我们通过x1,x2,x3来表示即可,其他参数约束为0,那么他就是一种稀疏表示思想。
-
它是一个离散值特征,使用One-hot表示。而稀疏特征可以进行叉乘,叉乘可以有效刻画样本,通过稀疏特征做叉乘取出共现信息,实现模型记忆效果。
有一个词表: [你,他, 计算机] 经过one-hot ===> 他=[0,0,1,...] 计算机=[1,0,1,...] 进行叉乘 : (他,计算机)
-
优缺点:
优点: 降低表示复杂度,更直白的原因其实就是减少系数参数,通过稀疏表示,可以充分发挥数据所含有的信息,去掉冗余的数据信息,达到最大化利用数据,广泛用于工业界 缺点: 需要人工设计 可能过拟合,所有特征都叉乘,相当于记住每一个样本
-
-
密集特征
-
用向量表达特征
有一个词表: [你,他, 计算机] 经过one-hot ===> 他=[0,0,1,...] 计算机=[1,0,1,...] 他 用一个向量来表示 [0.2,0.5,0.3,...(n维向量)]
-
Word2vec工具就是词语转化成向量。
-
优缺点
优点: 带有语义信息,不同向量之间有相关性 兼容没有出现过的特征组合 更少的人工去设计 缺点: 过度泛化,导致推荐不怎么相关的产品
-
-
wide 和deep模型结构
图像左侧为wide模型
右侧为wide&deep模型
wide模型
它所有输入都连接输出上,输入就是系数特征(one-hot表达)
wide&deep
左半部分是一个wide模型
右半部分是deep模型,他是多层的模型。首先输入是稀疏特征,deep把说有输入数据作为一个密集的向量表达,然后进行多层的全连接网络,最后连接到输出。
14.wide 和deep模型实现
14.1函数API实现wide&deep模型
- 导包
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
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__)
- 加载数据 使用sklearn fetch_californiz_hoursing
# 导入fetch_california_housing类
from sklearn.datasets import fetch_california_housing
# 实例化对象
housing = fetch_california_housing()
# 打印相关信息
print(housing.DESCR)
print(housing.data.shape)
# 输出:(20640, 8)
print(housing.target.shape)
# 输出:(20640,)
- 数据预处理(划分训练集,测试集)
from sklearn.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,test_size = 0.2)
# 拆分训练集,验证集
x_train,x_valid,y_train,y_valid = train_test_split(
x_train_all , y_train_all , random_state=11)
"""
train_test_split类里面传入housing.data-(20640, 8),
housing.targget-(20640,)
随机种子-random.state
(train_test_split 默认划分比例是3:1
也可以通过test_size,改变比例,
默认test_size = 0.25)
"""
- 打印划分结果
print(x_train.shape,y_train.shape)
print(x_valid.shape,y_valid.shape)
print(x_test.shape,y_test.shape)
- 数据标准化
#导入StandardScaler类
from sklearn.preprocessing import StandardScaler
# 实例化
scaler = StandardScaler()
# 调用scaler。fit 或者scaler.transform方法
x_train_scaled = scaler.fit_transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)
- 创建模型 使用函数式API功能实现
# 使用函数式API功能实现
# 定义输入层 将数据读取
input = keras.layers.Input(shape=x_train.shape[1:])
# 使用2层神经网络实现deep model 有点类似复合函数 fx(x) = h(g(x))
hidden1 = keras.layers.Dense(30, activation='relu')(input)# 第一层
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)# 第二层
# wide输入和神经网络层输出合并
concat = keras.layers.concatenate([input, hidden2])
# 最后输出
output = keras.layers.Dense(1)(concat)
# 定义model 函数式需要定义model
model = keras.models.Model(inputs=[input],outputs=[output])
model.compile(loss="mean_squared_error",optimizer="adam", metrics=["accuracy"])
- 训练模型
callbacks = [
keras.callbacks.EarlyStopping( patience=5,min_delta=1e-3)
]
history = model.fit(x_train_scaled,y_train, epochs=100,validation_data=(x_valid_scaled,y_valid), callbacks=callbacks)
- 查看训练结果图
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)
14.2子类API实现wide & deep模型
# 子类API
class WideDeepModel(keras.models.Model):
def __init__(self):
super(WideDeepModel, self).__init__()
# 定义模型层次
self.hidden1_layer = keras.layers.Dense(30, activation="relu")# 全连接层1
self.hidden2_layer = keras.layers.Dense(30, activation="relu")# 全连接层2
self.output_layer = keras.layers.Dense(1)# 输出层 ,长度为1
def call(self, input):
"""完成模型正向计算"""
hideen1 = self.hidden1_layer(input)
hideen2 = self.hidden2_layer(hideen1)
concat = keras.layers.concatenate([input, hideen2])
output = self.output_layer(concat)
return output
# 构建model
# 方式1:
# model = WideDeepModel()
# 方式2:
model = keras.models.Sequential([
WideDeepModel(),
])
model.build(input_shape=(None, 8))
model.compile(loss="mean_squared_error",optimizer="adam")
15.wide &deep模型多输入和多输出
- 上面实现wide&deep模型的wide,deep部分输入都是用一样输入,其实真实情况下,wide&deep模型的输入和输出式不一样的
15.1多输入
- 选择wide和deep输入:
# 多输入
# 函数式实现方法
input_wide = keras.layers.Input(shape=[5])# wide输入:选前5个当wide模型输入
input_deep = keras.layers.Input(shape=[6])# deep输入:选后6个 当deep模型输入
hidden1 = keras.layers.Dense(30, activation='relu')(input_deep)
hidden2 = keras.layers.Dense(30, activation='relu')(input_wide)
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.compile(loss="mean_squared_error",optimizer="adam")
- 训练输入数据拆分
callbacks = [
keras.callbacks.EarlyStopping( patience=5,min_delta=1e-3)
]
# 训练数据拆分
# wide训练数据取前5个
x_train_scaled_wide = x_train_scaled[:,:5]
# deep训练数据取后5个
x_train_scaled_deep = x_train_scaled[:,2:]
# 测试数据拆分
x_test_scaled_deep = x_test_scaled[:,2:]
x_test_scaled_wide = x_test_scaled[:,:5]
# 验证数据拆分
x_valid_scaled_deep = x_valid_scaled[:,2:]
x_valid_scaled_wide = x_valid_scaled[:,:5]
history = model.fit([x_train_scaled_wide, x_train_scaled_deep],y_train, epochs=100,validation_data=([x_valid_scaled_wide, x_valid_scaled_deep],y_valid), callbacks=callbacks)
15.2多输出
- 多输出一般用于多任务学习问题。比如我们预测当年房价和明年房价,这样就有2个任务。
# 上例中再定义个输出
# 输出hidden2
output2 = keras.layers.Dense(1)(hidden2)
# 实例模型加入输出
model = keras.models.Model(inputs=[input_wide,input_deep],outputs=[output, output2])
# 训练模型: y_train,y_valid 添加输出训练数据和验证数据
history = model.fit([x_train_scaled_wide, x_train_scaled_deep],[y_train, y_train], epochs=100,validation_data=([x_valid_scaled_wide, x_valid_scaled_deep],[y_valid,y_valid]), callbacks=callbacks)
# 验证增加 y_test验证数据集
model.evaluate([x_test_scaled_wide,x_test_scaled_deep], [y_test,y_test])
16.超参数搜索
- 神经网络有很多训练过程中不变参数,比如
网络结构参数:有几层,每层宽度,每层激活函数
训练参数:batch_size,学习率,学习率衰减算法等
-
而这些参数是不变的,如果手工去实验耗费人力。
-
搜索策略:
-
网格搜索
把各种传参数离散化成几个值,吧这几个值一一组合起来,然后一个个去试。
-
随机搜索
相比网格搜索,网格搜索是将传参数离散化几个固定值,比如值为[0.2,0.4,0.6,0.8] 而最优解是一个0.2-0.4之间的值,这样无法得到最优解。随机搜索是随机的生成参数组合,就能确保最优解是有可能被搜索到的,但随机的组合会比网格搜索更多
-
遗传算法搜索
遗传算法是对自然界的模拟 1.首先初始化候选参数集合 -> 训练-> 得到模型指标作为生存概率 2.然后根据生存的概率做随机选择 -> 交叉(类似于DNA组合) -> 变异(参数进行微小调整) -> 产生下一代集合 3.重新回到1.
-
启发式搜索
使用循环神经网络来生成参数,使用强化学习来进行反馈,使用模型来训练生成参数。
-
17.超参数搜索实现
- 使用regression数据集
17.1手动实现超参数搜索
# 定义 learning_rate
# W = W + grad + learning_rate
learning_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)# sgd adam
callbacks = [
keras.callbacks.EarlyStopping( patience=5,min_delta=1e-3)
]
# 训练模型
history = model.fit(
x_train_scaled, y_train,
validation_data=(x_valid_scaled, y_valid),
epochs = 10,
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_rates, histories): print("Learning rate:", lr) plot_learning_curves(history)
-
上述手动实现超参数搜索存在着以下问题
1.当前我们只有一个参数,只用一层for循环,如果我们参数有20层,那就会有20层for循环 2.使用for循环导致只能等上一个模型训练完毕才能开始下一个模型训练,没有一个并行化处理
17.2sklearn实现超参数搜索
-
使用RandomizedSearchCV实现超参数搜索,整体步骤是首先将tf.model转化为sklearn的model,定义参数集合,实现超参数搜索
-
常规导报
import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline import numpy as np 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__)
-
导入数据集
# 导入fetch_california_housing类 from sklearn.datasets import fetch_california_housing # 实例化对象 housing = fetch_california_housing() # 打印相关信息 print(housing.DESCR) print(housing.data.shape) # 输出:(20640, 8) print(housing.target.shape)
-
拆分训练集,测试集
from sklearn.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,test_size = 0.2) # 拆分训练集,验证集 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)
-
数据标准化
#导入StandardScaler类 from sklearn.preprocessing import StandardScaler # 实例化 scaler = StandardScaler() # 调用scaler。fit 或者scaler.transform方法 x_train_scaled = scaler.fit_transform(x_train) x_valid_scaled = scaler.transform(x_valid) x_test_scaled = scaler.transform(x_test)
-
将tf.model转化为sklearn的model
callbacks = [ keras.callbacks.EarlyStopping( patience=5,min_delta=1e-3) ] # 将tf.model转化为sklearn的model def build_model(hidden_layers=1,layer_size=30,learning_rate=3e-3): """ hidden_layers中间层的层数 layer_size 默认30 learning_rate 学习率 """ # 实例化一个训练model model = keras.models.Sequential() # 添加全连接层 model.add(keras.layers.Dense(layer_size, activation='relu', input_shape=x_train.shape[1:])) # 添加hidden_layers 个全连接层 for _ in range(hidden_layers): model.add(keras.layers.Dense(layer_size, activation='relu')) # 添加输出层 model.add(keras.layers.Dense(1)) # 定义优化器 optimizer = keras.optimizers.SGD(learning_rate) # mse为mean_squared_error简称 model.compile(loss="mse",optimizer=optimizer)# sgd adam return model # sklearn_model = keras.wrappers.scikit_learn.KerasRegressor(build_model) history = sklearn_model.fit(x_train_scaled, y_train, epochs=10, validation_data=(x_valid_scaled,y_valid),callbacks=callbacks)
-
定义搜索空间
param_distribution = { "hidden_layers": [1,2,3,4,5], "layer_size":np.arange(1,100),# 为1-100连续取值 "learning_rate": reciprocal(1e-4,1e-2)# 为一个分布取值 }
scipy 的reciprocal
from scipy.stats import reciprocal reciprocal.rvs(1e-4,1e-2,size=10)# 生成10的-4次方到10的-2次方 的 10个数 """ array([0.00407106, 0.00033841, 0.00018518, 0.00246045, 0.00991374, 0.00079176, 0.00011086, 0.00023637, 0.00359715, 0.00372375]) """
-
RandomizedSearchCV超参数搜搜
from sklearn.model_selection import RandomizedSearchCV # 初始化对象 # n_iter 从param_distribution 生成多少个集合 # n_jobs 并行处理数量 # cv 默认为3 使用了cross_validation: 训练集分成n份,n-1训练,最后一份验证 random_search_cv = RandomizedSearchCV(sklearn_model,param_distribution,cv=3, n_iter=10,n_jobs=1) # 进行训练 random_search_cv.fit(x_train_scaled,y_train,epochs=100,validation_data=(x_valid_scaled,y_valid), callbacks=callbacks)
-
查看结果
# 查看最好参数 print(random_search_cv.best_params_) # 查看最好峰值 print(random_search_cv.best_score_) # 最好model print(random_search_cv.best_estimator_)
-
拿取最好model进行验证
# 拿取最好model进行验证 model = random_search_cv.best_estimator_.model model.evaluate(x_test_scaled, y_test)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库