参考: https://www.bilibili.com/video/BV16A41157LW?p=15
视频及课件来源 北京大学 曹建
搭建神经网络的八股文
tf.keras 搭建神经网络六部法
第一步:import 相关模块,如 import tensorflow as tf。
第二步:指定输入网络的训练集和测试集,如指定训练集的输入 x_train 和标签y_train,测试集的输入 x_test 和标签 y_test。
第三步:逐层搭建网络结构,model = tf.keras.models.Sequential()。 # 见名词解释(1)
第四步:在 model.compile()中配置训练方法,选择训练时使用的优化器、损失函数和最终评价指标。 # 见名词解释(2)
第五步:在 model.fit()中执行训练过程,并输入参数。 # 见名词解释(3)
第六步:使用 model.summary()打印网络结构,统计参数数目。 # 见名词解释(4)
名词解释
(1) tf.keras.models.Sequential
Sequential 函数是一个容器,描述了神经网络的网络结构,在 Sequential函数的输入参数中描述从输入层到输出层的网络结构。
# 例如可以填入 拉直层: tf.keras.layers.Flatten() 拉直层 不含计算 只进行形状转换
全连接层: tf.keras.layers.Dense( 神经元个数, activation=”激活函数”, kernel_regularizer=”正则化方式”)
告知神经元个数
激活函数(以字符串形式填入 可选 relu(常用)、softmax、sigmoid、tanh 等 )
正则方法 : 正则化 可以传入tf.keras.regularizers.l1()、tf.keras.regularizers.l2()
还有卷积神经层 和 LSTM 层
(2) model.compile()中配置训练方法,选择训练时使用的优化器、损失函数和最终评价指标
Model.compile( optimizer = 优化器, loss = 损失函数, metrics = [“准确率”])
optimizer: 可以是字符串形式给出的优化器名字,也可以是函数形式,使用函数形式可以设置学习率、动量和超参数。
loss: 可以是字符串形式给出的损失函数的名字,也可以是函数形式。
Metrics: 评测指标 可选
‘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]
(3) model.fit()
model.fit (x_train, y_train,
batch_size= , epochs= ,
validation_data=(测试集的输入特征,测试集的标签),
validation_split=从训练集划分多少比例给测试集,
validation_freq = 多少次epoch测试一次)
x_train: 训练集的输入特征(没标签)
y_train: 训练集的标签(没标签)
batch_size: 每次喂入神经网络的样本数
epochs: 循环次数
validation_data:(跟测试有关) 和validation_split 二选一, validation_data要告知 (测试集的输入特征,测试集的标签)
validation_split:从训练集划分多少比例给测试集,
validation_freq: 每多少次测试一次结果
(4) model.summary()
可以打印网络结构和参数统计
案例 使用搭建六步法实现鸢尾花分类
鸢尾花数据来源
def get_iris_data():
# 获取鸢尾花数据集
# x_data 输入特征
from sklearn import datasets
x_data = datasets.load_iris().data
# y_data 标签
y_data = datasets.load_iris().target
# 实现数据集乱序
import numpy as np
np.random.seed(116) # 使用相同的seed,保证输入特征和标签一一对应
np.random.shuffle(x_data)
np.random.seed(116)
np.random.shuffle(y_data)
return x_data, y_data
神经网络代码:
import tensorflow as tf
def train_demo(x_train, y_train):
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(3, # 神经元个数 3
activation='softmax', # 激活函数
kernel_regularizer=tf.keras.regularizers.l2() # 正则化方法
)
])
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1), # 选择sgd 优化器 学习率0.1
# 损失函数 from_logits=False 因为使用softmax激活函数,不是原始输出
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
# 数据集给的标签时 0 1 2 神经网络的前向输出时概率分布
metrics=['sparse_categorical_accuracy'])
# x_train 训练集 y_train 训练标签
# batch_size 每次喂入神经网络 32组数据(2的n次幂)
# epochs 迭代循环次数 500
# validation_split 从训练集的20% 作为测试集
# validation_freq 每迭代20次 从测试集中验证一次准去率
model.fit(x_train, y_train, batch_size=32, epochs=1000, validation_split=0.2, validation_freq=20)
model.summary() # 打印出网络结构和参数统计
if __name__ == '__main__':
x_data, y_data = get_iris_data()
train_demo(x_data, y_data)
但是
Sequential 可以搭建出上层输出就是下层输入的顺序网络结构
但是无法搭建一些带有跳连的废顺序网络结构
此时 我们可以使用类(class)搭建神经网络结构,使用类封装一个神经网络结构
继承 tensorflow.python.keras.models import Model
重要的两个函数 __init__
和 call
函数
init 函数用来定义网络
call 调用网络结构块 实现前向传播
import tensorflow as tf
class MyIrisModel(tf.keras.Model):
def __init__(self):
super(MyIrisModel, self).__init__()
# 鸢尾花神经网络 3层, 激活函数 softmax #正则化方法 tf.keras.regularizers.l2()
self.d1 = tf.keras.layers.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
def train_class_demo(x_train, y_train):
model = MyIrisModel()
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
# x_train 训练集 y_train 训练标签
# batch_size 每次喂入神经网络 32组数据(2的n次幂)
# epochs 迭代循环次数 500
# validation_split 从训练集的20% 作为测试集
# validation_freq 每迭代20次 从测试集中验证一次准去率
model.fit(x_train, y_train, batch_size=32, epochs=1000, validation_split=0.2, validation_freq=20)
model.summary()
if __name__ == '__main__':
x_data, y_data = get_iris_data()
train_class_demo(x_data, y_data)