LeNet
共享卷积核 减少网络参数
一共五层
当时,还没有BN操作,sigmoid是主流激活函数,无drop out层
两层 卷积核
三层 全连接层
使用Lenet训练模型代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import datasets, layers, optimizers, Sequential ,metrics
(x, y), (x_test, y_test) = datasets.mnist.load_data()
x.shape
查看第一张图片
plt.imshow(x[0])
使用plt.subplots 打印出前12张图片
index=0
fig,axes = plt.subplots(4,3,figsize=(8,4),tight_layout=True)
for row in range(4):
for col in range(3):
axes[row,col].imshow(x[index]) # 展示图片
axes[row,col].axis('off') # 去掉坐标
axes[row,col].set_title(y[index]) # 设置标题
index +=1
plt.show()
查看x训练集的数据类型
x.dtype
写一个转换x和y训练集数据,类型的函数,封装一下
同时将x进行归一化处理
tf.cast 是强制转换类型的意思
# 针对x和y类型进行转换
# 对x类型进行reshape
def preprocess(x,y):
x = tf.cast(x,dtype=tf.float32)/255.0 # 转换x为浮点数
x = tf.reshape(x,[28,28,1]) # 将x重塑成28x28x1的三维数据
y = tf.cast(y,dtype=tf.int32) # 转换y为浮点数
return x,y
将训练集进行 x 和 y 一一对应的打包
这是设为32个数据组合,打为一个包
比如:batch(4) # 按照顺序取出4行数据打包
这里调用了上面封转的preprocess函数对x和分别进行了处理
shuffle(10000) # 将数据打乱,数值越大,混乱程度越大
# 打包训练集并打乱数据
# 32个x和y 为一个包
batchs =64
db = tf.data.Dataset.from_tensor_slices((x,y))
db = db.map(preprocess).shuffle(10000).batch(batchs)
打包测试集
# 打包测试集
batchs = 32
db_test = tf.data.Dataset.from_tensor_slices((x_test,y_test))
db_test = db_test.map(preprocess).shuffle(10000).batch(batchs)
小tip: 关于map函数的理解
def square(x) : # 计算平方数
return x ** 2
list(map(square, [1,2,3,4,5])) # 使用 list() 转换为列表
输出结果: [1, 4, 9, 16, 25]
搭建LeNet5模型的网络
net_layer = [
layers.Conv2D(6,kernel_size=[5,5],padding='same',activation='relu'),
layers.MaxPool2D(pool_size=[2,2],strides=2),
layers.Conv2D(6,[5,5],padding='valid',activation='relu'),
layers.MaxPool2D(pool_size=[2,2]),
layers.Flatten(),
layers.Dense(120,activation='relu'),
layers.Dense(84,activation='relu'),
layers.Dense(10,activation='softmax')
]
# 将网络放入Sequential中
model = tf.keras.models.Sequential(net_layer)
# 设置输入形状大小
model.build(input_shape=(None,28,28,1))
给创建好的模型配置参数
# 创建优化器
# optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
optimizer = 'adam'
# 模型配置参数
# 优化器 梯度下降
# 损失函数 交叉熵
# 查看参数 准确率
model.compile(optimizer=optimizer,
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['sparse_categorical_crossentropy']
# loss='sparse_categorical_crossentropy', # 指定损失函数
# metrics=['accuracy']
)
设置一个模型保存
目的是为了防止训练时间太长,选取中间进行保存一下模型,下次继续训练
这是导入os
设置模型保存文件和路径
检查在该文件下是否已经存在该模型,如果存在直接加载已经训练的模型权重
import os
checkpoint_save_path = './checkpoint/mnist.ckpt'
if os.path.exists(checkpoint_save_path+'.index'):
print("------------------load the model-----------------------------")
model.load_weights(checkpoint_save_path)
保存模型
模型保存路径
只保留训练的最佳参数
根据最好的损失和准确度
# 保存模型
tf.keras.callbacks.ModelCheckpoint(
filepath = checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
导入训练集进行训练
epochs=10 是将所有训练集 重复使用10遍
validation_data 指定测试集 上面已经打包好了
callbacks 回调函数,调用之前的训练的模型
history = model.fit(db,batch_size = 32, epochs = 10,
validation_data = db_test,
validation_freq = 1,
callbacks=[cp_callback]
)
将模型的名字 权重 和 每层网络情况 记入text文件
# print(model.trainable_variables)
file = open('./weights.txt','w')
for v in model.trainable_variables:
file.write(str(v.name) + '\n')
file.write(str(v.shape)+ '\n')
file.write(str(v.numpy()) + '\n')
file.close()
查看模型网络结构
model.summary()
查看 指标
history.history
绘制acc和loss的变化图
acc= history.history['sparse_categorical_crossentropy']
val_acc = history.history['val_sparse_categorical_crossentropy']
loss = history.history['loss']
val_loss = history.history['val_loss']
plt.figure(figsize=(20,10))
plt.subplot(1,2,1)
plt.plot(loss,label='Trainning loss')
plt.plot(val_loss,label='Validation loss')
plt.legend()
plt.grid()
plt.title('loss')
plt.subplot(1,2,2)
plt.plot(acc,label='Trainning Accuracy')
plt.plot(val_acc,label='Validation Accuracy')
plt.legend()
plt.grid()
plt.title('accuracy')
plt.show()
看这个loss曲线 貌似有点过训练过度了,我把bach改成10次,删了之前的保存模型,从头再来一下,结果如下图,这个训练刚刚好!