本节内容:
前两节使用 Tensorflow2 的原生代码大叫神经网络。本节使用 keras 搭建神经网络(八股:六步法,有 Sequential 和 class 两种)。
文章目录
- 一、搭建网络八股 sequential
- 1.1、keras 介绍
- 1.2、六步法搭建 keras 神经网络
- 1.3、函数用法
- 1.3.1、Sequential() 函数
- 1.3.2、compile() 函数
- 1.3.3、fit() 函数
- 1.3.4、model.summary()
- 1.4、鸢尾花分类代码复现
- 二、类 class 搭建神经网络
- 三、MNIST 手写数字识别数据集
- 3.1、使用 Sequential 搭建神经网络
- 3.2、使用 clas 搭建神经网络
- 四、FASHION 衣裤识别数据集及训练
一、搭建网络八股 sequential
1.1、keras 介绍
tf.keras 是 Tensorflow2 引入的高封装度框架,可以用于快速搭建神经网络模型。
keras 官方文档:https://keras.io/zh/
两种学习 API 的方法:
- 1)在 PyCharm 集成开发环境中查看框架源码:将鼠标放置在函数上按住 Ctrl 键会显示函数的基本信息,包括封装函数的类、函数入口参数,函数功能等等。
- 2)在 Tensorflow 官网中查询函数文档:通过左边的检索寻找目标函数。如:查询 model.fit() 函数,打开 tf.keras 中的 Model 类,右方目录列出了 Model 类所包含的函数,点击 fit() 函数可以看到对于函数的介绍,包括输入参数具体介绍、函数功能等等。
1.2、六步法搭建 keras 神经网络
1)import 相关模块。如 import tensorflow as tf
。
2)指定输入网络的训练集 train
和测试集 test
,如指定训练集的输入 x_train
和标签 y_train
,以及测试集的输入 x_test
和标签 y_test
。
3)逐层搭建网络结构,相当于走了一边前向传播 models.Sequential
。
model = tf.keras.models.Sequential()
# 另外一种方法:class MyModel
class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()
初始化网络结构,搭建出神经网络所需的各种网络结构块
def call(self, x):
调用网络结构块,实现前向传播
return y
model = MyModel()
4)在 compile()
中配置训练方法,选择训练时使用的优化器、损失函数和评价指标。
model.compile()
5)在 model.fit()
中执行训练过程,告知训练集和测试集的输入值和标签、每个 batch
的大小 batch_size
、数据集的迭代次数 epoch
。
model.fit()
6)打印网络结构,统计参数数目。
model.summary()
1.3、函数用法
1.3.1、Sequential() 函数
Sequential()
可以认为是一个容器,这个容器里面封装了一个神经网络结构。在 Sequential() 函数中要描述从输入层到输出层的每一层的网络结构,每一层的网络结构可以是拉直层 Flatten() 或者全连接层 Dense()。
# 描述各层网络
model = tf.keras.model.Sequential([网络结构])
网络结构举例:
- 拉直层:这一层不含计算,只是形状转换,把输入特征拉直变成一维数组,可以变换张量的尺寸。
tf.keras.layers.Flatten()
- 全连接层:又叫 Dense 层。
# 其中激活函数 activation 用字符串给出,可选用:relu、softmax、sigmoid、tanh
# kernel_regularizer 可选用:tf.keras.regularizers.l1()、tf.keras.regularizers.l2()
tf.keras.layers.Dense(神经元个数,activation = "激活函数",kernel_regularizer = 哪种正则化
)
- 卷积层:卷积神经网络
tf.keras.layers.Conv2D(filters=卷积核个数,
kernel_size=卷积核尺寸,
strides=卷积步长,
padding= "valid" or "same")
- LSTM 层:循环神经网络
tf.keras.layers.LSTM()
1.3.2、compile() 函数
用于配置神经网络的训练方法,告知训练时使用的优化器、损失函数和准确率评测标准。
model.compile(optimizer=优化器,
loss=损失函数,
metrics=["准确率"])
1)optimizer
可以是以字符串形式给出的优化器名字,比如 sgd、adagrad、adadelta、adam。也可以是函数形式,使用函数形式可以设置学习率、动量等超参数。建议入门时,先使用左边字符串形式的优化器名字,等掌握了整个框架后,可通过TensorFlow官网查询这些函数的具体用法,调节超参数。
https://tensorflow.google.cn/api_docs/python/tf/keras/optimizers/experimental/SGD
‘sgd’ or tf.keras.optimizers.SGD(lr=学习率,
decay=学习率衰减率,
momentum=动量参数)
‘adagrad’ or tf.keras.optimizers.Adagrad(lr=学习率,
decay=学习率衰减率)
‘adadelta’ or tf.keras.optimizers.Adadelta(lr=学习率,
decay=学习率衰减率)
‘adam’ or tf.keras.optimizers.Adam (lr=学习率,
beta_1=0.9,
beta_2=0.999)
2)loss
可以是字符串给出的损失函数名字,如:mse、spare_categorical_crossentropy。也可以是函数形式。
‘mse’ or tf.keras.losses.MeanSquaredError()
‘sparse_categorical_crossentropy' or tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False) # from_logits 是否是原始输出,即未经过概率分布的输出
损失函数常需要经过 softmax 函数将输出转化为概率分布的形式。from_logits 用来标注该损失函数是否需要转换为概率的形式,取 False 表示转化为概率分布,取 True 表示没有转化为概率分布,直接输出。
3)Metrics
告知网络评测指标。
# y_是标签,y是网络输出结果
‘accuracy’ :y_和y都是数值,如y_=[1] y=[1]
‘categorical_accuracy’ :y_和y都是独热码(概率分布),如y_=[0,1,0] y=[0.256,0.695,0.048]
‘sparse_categorical_accuracy’ :y_是数值,y是独热码(概率分布),如y_=[1] y=[0.256,0.695,0.048]
1.3.3、fit() 函数
fit() 函数执行训练过程。
model.fit (训练集的输入特征,
训练集的标签,
batch_size= , # 每次喂入神经网络的样本数
epochs= , # 要迭代多少次数据集
# 以下函数 validation_data 和 validation_split 二选一
validation_data=(测试集的输入特征,测试集的标签),
validation_split=从训练集划分多少比例给测试集,
validation_freq = 多少次epoch测试一次 # 每多少次 epoch 迭代使用测试集验证一次结果
)
1.3.4、model.summary()
summary()
可以打印出网络的结构和参数统计。
1.4、鸢尾花分类代码复现
# 1:首先 import 相关模块
import tensorflow as tf
from sklearn import datasets
import numpy as np
# train、test 分别交代训练集中的输入特征 x_train 和训练集的标签 y_train
# 测试集的输入特征 x_test 和测试集的标签 y_test 也可以像 x_train 和 y_train 一样直接在这里给定,也可以在 fit 中按比例从训练集中划分
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
# 以下 5 行代码实现数据集的乱序
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
# 在 sequential 中搭建网络结构:神经元个数、激活函数、正则化方法
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
])
# 在 compile 中配置训练方法:选择 SGD 优化器,学习率设置为 0.1、选择损失函数、由于神经网络末端使用了 softmax 函数,使得输出是概率分布而不是原始输出,所以 from_logits 是 false
# 由于鸢尾花数据集给的标签是 0 1 2,是数值。神经网络前向传播的输出是概率分布,所以这里选择 sparse_categorical_accuracy 作为评测指标。
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
# 在 fit 中执行训练过程:训练集输入特征、训练集标签、训练时一次喂入神经网络多少组数据 batch_size、数据集迭代循环的次数、validation_split 告知从训练集中选择 20% 的数据作为测试集、validation_freq 表示每迭代 20 次训练集要在测试集中验证一次准确率。
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
# 用 summary 打印网络结构和参数统计
model.summary()
法2:也可以像 x_train 和 y_train 一样直接给定
以上是测试集 test 的两种划分方式。
二、类 class 搭建神经网络
使用 Sequential 可以搭建出上层输出就是下层输入的顺序网络结构,但是无法写出一些带有跳连的非顺序网络结构,此时可以选择用类 class 搭建神经网络结构,可以使用 class 类搭建一个神经网络结构。
class MyModel(Model): # MyModel为声明的神经网络的名字,括号中的Model表示创建的类需要继承TensorFlow库中的Model类
# 类中需要定义两个函数
def __init__(self): # 类的构造函数,用于初始化类的参数
super(MyModel, self).__init__() # 初始化父类的参数
初始化网络结构,搭建出神经网络所需的各种网络结构块
def call(self, x): #调用__init__()函数完成初始化的网络块,实现前向传播并返回推理值
调用网络结构块,实现前向传播
return y
model = MyModel()
可以认为 init 函数准备出搭建网络所需的各种积木,call 函数调用 init 中搭建好的积木,实现前向传播。
使用 class 方式搭建 iris 网络结构:
class IrisModel(Model):
def __init__(self):
super(IrisModel, self).__init__()
# 在__init__函数中定义了要在call函数中调用的具有三个神经元的全连接网络Dense
self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2()) # d1是给这一层起的名字,每一层都用self.引导
def call(self, x):
y = self.d1(x) # 在call函数中调用self.d1实现了从输入x输出y的前向传播
return y
# 对于鸢尾花的例子,前向传播只经过一层网络,这层网络结构快已经在 __init__ 函数中定义好了,直接 self.d1 调用,输入 x 输出 y,返回 y
搭建好网络结构后,只需要使用 Model = MyModel() 构建类的对象,就可以使用该模型了。
model = IrisModel() # 实例化
完整代码如下:
import tensorflow as tf
from tensorflow.keras.layers import Dense
# 添加 model 模块
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
# 定义了 IrisModel 类
class IrisModel(Model):
def __init__(self):
super(IrisModel, self).__init__()
# 具有三个神经元的全连接网络 Dense
self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
def call(self, x):
# 在 call 函数中调用了 self.d1 实现了输入 x 到输出 y 的前向传播
y = self.d1(x)
return y
# 实例化 model
model = IrisModel()
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
model.summary()
三、MNIST 手写数字识别数据集
数据集介绍:MNIST 数据集一共有 7 万张图片,都是 28 * 28 像素点的手写数字图片。其中 6 万张用于训练,1 万张用于测试。
import tensorflow as tf
from matplotlib import pyplot as plt
# 导入数据集
mnist = tf.keras.datasets.mnist # keras 函数库提供了使用 mnist 数据集的接口
# x_train 是训练集输入特征,y_train 是训练集标签,x_test 是测试集输入特征,y_test 是测试集标签
(x_train, y_train), (x_test, y_test) = mnist.load_data() # load_data() 直接从 mnist 中读取测试集和训练集
# 送入神经网络时要把数据拉直成一维数组,把 784 个像素点的灰度值作为输入特征送入神经网络
tf.keras.layers.Flatten()
# 可视化训练集输入特征的第一个元素
# 以下两句话把训练集中的第一个样本 x_train[0] 可视化出来
plt.imshow(x_train[0], cmap='gray') # 绘制灰度图
plt.show()
以上代码生成如下:
import tensorflow as tf
from matplotlib import pyplot as plt
# 导入 MNIST 数据集
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 可视化训练集输入特征的第一个元素
plt.imshow(x_train[0], cmap='gray') # 绘制灰度图
plt.show()
# 打印出训练集中第一个样本的输入特征
print("x_train[0]:\n", x_train[0])
# 打印出训练集中第一个样本的标签
print("y_train[0]:\n", y_train[0])
# 打印出整个训练集输入特征形状
print("x_train.shape:\n", x_train.shape)
# 打印出整个训练集标签的形状
print("y_train.shape:\n", y_train.shape)
# 打印出整个测试集输入特征的形状
print("x_test.shape:\n", x_test.shape)
# 打印出整个测试集标签的形状
print("y_test.shape:\n", y_test.shape)
3.1、使用 Sequential 搭建神经网络
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 对输入网络的输入特征进行归一化,使原来 0 到 255 之间的灰度值变为 0 到 1之间的数值
# 把输入特征的数值变小更适合神经网络的吸收
x_train, x_test = x_train / 255.0, x_test / 255.0
# 用 sequential 搭建神经网络
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(), # 先把输入特征拉直为一维数组,也就是拉直为 748 个数值
tf.keras.layers.Dense(128, activation='relu'), # 定义第一层网络有 128 个神经元,用 relu 激活函数
tf.keras.layers.Dense(10, activation='softmax') # 定义第二层网络有 10 个神经元,用 softmax 函数使输出符合概率分布
])
# 用 compile 配置训练方法
model.compile(optimizer='adam', # 优化器选择 adma
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), # 损失函数选择 SparseCategoricalCrossentropy
metrics=['sparse_categorical_accuracy']) # 数据集中的标签是数值,神经网络输出 y 是概率分布,所以这里选择 sparse_categorical_accuracy
# fit 中执行训练过程,参数依次为:训练集输入特征、训练集标签、每次喂入网络 32 组数据、数据集迭代 5 次、【测试集输入特征、测试集标签】、每迭代一次训练集执行一次测试集的评测
model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
# 打印出网络结构和参数统计
model.summary()
# 我们所说的准确率是使用测试集计算出的准确率,也就是看的这里:val_sparse_categorical_accuracy: 0.9787
执行结果说明:
- 1)MNIST 数据集有 60000 张图片用来训练,batch_size=32,所以每轮要迭代 60000/32=1875次,共迭代 5 轮,即 5 epochs。
- 2)训练时每个 step 给出的是训练集 accuracy,不具有参考价值。有实际评判价值的是 validation_freq 中设置的、隔若干轮输出的测试集 accuracy。
3.2、使用 clas 搭建神经网络
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 与 sequential 搭建神经相比,只有实例化 model 的方法不同
class MnistModel(Model):
# __init__ 函数中定义了 call 函数中所用到的层
def __init__(self):
super(MnistModel, self).__init__()
self.flatten = Flatten()
self.d1 = Dense(128, activation='relu')
self.d2 = Dense(10, activation='softmax')
# cell 函数中从输入 x 到输出 y,走过一次前向传播返会输出 y
def call(self, x):
x = self.flatten(x)
x = self.d1(x)
y = self.d2(x)
return y
# 实例化 model,其余代码和 Sequential 实现手写数字识别模型训练的代码是完全一样的
model = MnistModel()
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()
# 随着训练集迭代轮数的增加,手写数字识别准确率不断提高
四、FASHION 衣裤识别数据集及训练
Fashion_mnist 数据集与 MNIST 数据集几乎一样,一共有 7w 张图片,每张图片都是 28 行 28 列像素点的灰度值数据。其中 6w 张用于训练和1w 张用于测试,图片被分为十类(如T恤、裤子、套头衫等等),每张图片为28×28的分辨率(像素点的灰度值数据)。
**训练衣服、裤子等图片的识别模型:**与训练MNIST数据集的不同之处就是加载数据集的代码不同,在此不再赘述。
fashion = tf.keras.datasets.fashion_mnist
(x_train, y_train),(x_test, y_test) = fashion.load_data() # 可以使用.load_data()直接从fashion数据集中读取训练集和测试集
最后识别准确率为 87.50%。