<jupyter_start><jupyter_text>LeNetLeNet[1] 即 LeNet5，于1988年提出，是最早的卷积神经网络之一。原论文的网络结构是用于训练手写数字的，本节尝试用 LeNet 训练 Fashion MNIST 数据集，因此结构上会有点微调。一共有五层网络（不算输入层），两层卷积层和三层全连接层：**注** CBAPD 即 **C**onvolutional、**B**atch Normalization、**A**ctivation、**P**ooling、**D**ropout + 第一层：卷积层  + C：使用 6 个 $5\times5$ 的卷积核，步长为 1，不使用全 0 填充（valid）  + B：不使用批标准化（LeNet 提出时间在 Batch Normalization[2] 提出时间之前）  + A：使用 sigmoid 激活函数（那个时候是主流的激活函数）  + P：使用 $2\times2$ 的池化核，采用最大值池化，步长为 2，不使用全 0 填充（valid）  + D：不使用 Dropout（LeNet 提出时间在 Dropout[3] 提出时间之前） + 第二层：卷积层  + C：使用 16 个 $5\times5$ 的卷积核，步长为 1，不使用全 0 填充（valid）  + B：不使用批标准化  + A：使用 sigmoid 激活函数  + P：使用 $2\times2$ 的池化核，采用最大值池化，步长为 2，不使用全 0 填充（valid）  + D：不使用 Dropout + Flatten 拉伸卷积层传来的输入特征  + 第三层：全连接层  + 120 个神经元  + 使用 sigmoid 激活函数  + 第四层：全连接层  + 84 个神经元  + 使用 sigmoid 激活函数 + 第五层：全连接层（输出层）  + 10 个神经元  + 使用 softmax 激活函数关于 Fashion MNIST 数据集的信息可以看上一节。+ [1] <NAME> , <NAME> . Gradient-based learning applied to document recognition[J]. Proceedings of the IEEE, 1998, 86(11):2278-2324.+ [2] <NAME> , <NAME> . Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift[J]. 2015.+ [3] <NAME> , <NAME> , <NAME> , et al. Dropout: A Simple Way to Prevent Neural Networks from Overfitting[J]. Journal of Machine Learning Research, 2014, 15(1):1929-1958.<jupyter_code>import tensorflow as tf
import numpy as np
import os
from matplotlib import pyplot as plt
from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten, Dense<jupyter_output><empty_output><jupyter_text>在上一版 baseline 的基础上进行修改<jupyter_code>lenet5 = [
    Conv2D(filters=6, kernel_size=5, activation='sigmoid'),
    MaxPool2D(pool_size=2, strides=2),
    Conv2D(filters=16, kernel_size=5, activation='sigmoid'),
    MaxPool2D(pool_size=2, strides=2),
    Flatten(),
    Dense(120, activation='sigmoid'),
    Dense(84, activation='sigmoid'),
    Dense(10, activation='softmax')
]
# 导入数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
# LeNet5 
model = tf.keras.models.Sequential(lenet5)
# 配置模型参数
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])
# 设置断点续训
checkpoint_save_path = './checkpoint/LeNet5.ckpt'
if os.path.exists(checkpoint_save_path + '.index'):
    model.load_weights(checkpoint_save_path)
# 设置保存最优模型参数回调
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                save_best_only=True,
                                                save_weights_only=True)
# 训练模型
history = model.fit(x_train, y_train,
                    batch_size=128,
                    epochs=5,
                    validation_data=(x_test, y_test),
                    validation_freq=1,
                    callbacks=[cp_callback])
# 打印网络结构
model.summary()
np.set_printoptions(threshold=np.inf)
# 保存参数信息
with open('./data/weights.txt', 'w') as file:
    for v in model.trainable_variables:
        file.write(str(v.name) + '\n')
        file.write(str(v.shape) + '\n')
        file.write(str(v.numpy()) + '\n')
# 获取 acc 和 loss 曲线数据
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
# 可视化 acc 曲线
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.show()
# 可视化 loss 曲线
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13362740010378826, 'fraction_numerical': 0.031914893617021274, 'mean_word_length': 4.216508795669824, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '115111', 'license': 'Apache-2.0', 'n_tokens_mistral': 1778, 'n_tokens_neox': 1793, 'n_words': 291, 'path': '12. LeNet.ipynb', 'repo_name': 'InnoFang/tensorflow2-from-zero', 'size': '3875'}