LeNet-5实战
Tip
我不能创造的事物,我就还没有完全理解它。−理查德·費曼
LeNet-5模型介绍
LeNet-5
是Yann LeCun
在1998年设计的用于手写数字识别的卷积神经网络,当年美国大多数银行就是用它来识别支票上面的手写数字的,它是早期卷积神经网络中最有代表性的实验系统之一。
实战代码
前置引入
import os
import tensorflow as tf
from tensorflow import keras
os.environ["TF_CPP_MIN_LOG_LEVEL"] = '2'
创建LeNet-5网络模型
model = tf.keras.Sequential([
# 第1层-卷积层 滤波器尺寸5*5,6个
keras.layers.Conv2D(6, 3),
# 第2层-池化层,滤波器尺寸为2×2,步长为2
keras.layers.MaxPooling2D(pool_size=2, strides=2),
keras.layers.ReLU(),
# 第3层-卷积层 滤波器尺寸5*5,16个
keras.layers.Conv2D(16, 3),
# 第4层-池化层,滤波器尺寸为2×2,步长为2
keras.layers.MaxPooling2D(pool_size=2, strides=2),
keras.layers.ReLU(),
keras.layers.Flatten(), # 拉平之后方便做全连接
# 第5层-全连接层
keras.layers.Dense(120, activation='relu'),
# 第6层-全连接层
keras.layers.Dense(84, activation='relu'),
# 第7层-全连接层
keras.layers.Dense(10, activation='softmax') # 最后输出10类,0-9的数字
])
model.build(input_shape=(4, 28, 28, 1)) # 28*28*1 1个通道
# 打印出网络结构
model.summary()
# 编译
model.compile(
optimizer=keras.optimizers.Adam(),
loss=keras.losses.CategoricalCrossentropy(),
metrics=['accuracy']
)
数据预处理与加载
# 数据预处理
def preprocess(x, y):
x = tf.cast(x, dtype=tf.float32) / 255
x = tf.reshape(x, [-1, 28, 28, 1])
y = tf.one_hot(y, depth=10)
return x, y
# 加载数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 查看类型
print('x_train=', type(x_train))
print('y_train=', type(y_train))
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train))
print('train_db=', type(train_db))
train_db = train_db.shuffle(10000) # 打乱数据
train_db = train_db.batch(128)
train_db = train_db.map(preprocess)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
print('test_db=', type(test_db))
test_db = test_db.shuffle(10000)
test_db = test_db.batch(128)
test_db = test_db.map(preprocess)
模型训练
# 开始训练
model.fit(train_db, epochs=10)
# 在测试集上验证
model.evaluate(test_db)
详细部分
点击查看代码
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = '2'
import tensorflow as tf
from tensorflow.keras import Sequential, layers
network = Sequential([ # 网络容器
layers.Conv2D(6, kernel_size=3, strides=1), # 第一个卷积层, 6 个 3x3 卷积核
layers.MaxPooling2D(pool_size=2, strides=2), # 高宽各减半的池化层
layers.ReLU(), # 激活函数
layers.Conv2D(16, kernel_size=3, strides=1), # 第二个卷积层, 16 个 3x3 卷积核
layers.MaxPooling2D(pool_size=2, strides=2), # 高宽各减半的池化层
layers.ReLU(), # 激活函数
layers.Flatten(), # 打平层,方便全连接层处理
layers.Dense(120, activation='relu'), # 全连接层,120 个节点
layers.Dense(84, activation='relu'), # 全连接层,84 节点
layers.Dense(10) # 全连接层,10 个节点
])
# build 一次网络模型,给输入 X 的形状,其中 4 为随意给的 batchsz
network.build(input_shape=(4, 28, 28, 1))
# 统计网络信息
network.summary()
# 导入误差计算,优化器模块
from tensorflow.keras import losses, optimizers
# 创建损失函数的类,在实际计算时直接调用类实例即可
criteon = losses.CategoricalCrossentropy(from_logits=True)
# 优化器,加快训练速度
optimizer = optimizers.Adam(lr=1e-3)
# 数据预处理
def preprocess(x, y):
x = tf.cast(x, dtype=tf.float32) / 255
return x, y
# 加载数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 查看类型
print('x_train=', type(x_train))
print('y_train=', type(y_train))
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train))
print('train_db=', type(train_db))
train_db = train_db.shuffle(10000) # 打乱数据
train_db = train_db.batch(128)
train_db = train_db.map(preprocess)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
print('test_db=', type(test_db))
test_db = test_db.shuffle(10000)
test_db = test_db.batch(128)
test_db = test_db.map(preprocess)
# 生成train数据的迭代器
db_iter = iter(train_db)
sample = next(db_iter)
print(f'batch: {sample[0].shape, sample[1].shape}')
def main():
for epoch in range(10):
for step, (x, y) in enumerate(train_db):
# 构建梯度记录环境
with tf.GradientTape() as tape:
# 插入通道维度,=>[b,28,28,1]
x = tf.expand_dims(x, axis=3) # 前向计算,获得 10 类别的概率分布,[b, 784] => [b, 10]
out = network(x)
# 真实标签 one-hot 编码,[b] => [b, 10]
y_onehot = tf.one_hot(y, depth=10) # 计算交叉熵损失函数,标量
loss = criteon(y_onehot, out)
# 自动计算梯度
grads = tape.gradient(loss, network.trainable_variables)
# 自动更新参数
optimizer.apply_gradients(zip(grads, network.trainable_variables))
if step % 100 == 0:
print(epoch, step, f'loss: {float(loss)}')
# 记录预测正确的数量,总样本数量
correct, total = 0, 0
for x, y in test_db: # 遍历所有训练集样本
# 插入通道维度,=>[b,28,28,1]
x = tf.expand_dims(x, axis=3) # 前向计算,获得 10 类别的预测分布,[b, 784] => [b, 10]
out = network(x)
# 真实的流程时先经过 softmax,再 argmax
# 但是由于 softmax 不改变元素的大小相对关系,故省去
pred = tf.argmax(out, axis=-1)
y = tf.cast(y, tf.int64)
# 统计预测正确数量
correct += float(tf.reduce_sum(tf.cast(tf.equal(pred, y), tf.float32)))
# 统计预测样本总数
total += x.shape[0] # 计算准确率
print('test acc:', correct / total)
if __name__ == '__main__':
main()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具