# 构建CNN:两组卷积+池化,最后全连接输出
cnn_model = models.Sequential([ # 创建顺序模型
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), # 第一卷积层:32个3×3滤波器
layers.MaxPooling2D((2, 2)), # 第一池化层:2×2最大池化
layers.Conv2D(64, (3, 3), activation='relu'), # 第二卷积层:64个3×3滤波器
layers.MaxPooling2D((2, 2)), # 第二池化层:2×2最大池化
layers.Conv2D(64, (3, 3), activation='relu'), # 第三卷积层:64个3×3滤波器
layers.Flatten(), # 展平层:将多维特征图转为一维向量
layers.Dense(64, activation='relu'), # 全连接层:64个神经元
layers.Dense(10, activation='softmax') # 输出层:10个类别的softmax概率
]) # 模型构建完成
cnn_model.compile(optimizer='adam', # Adam自适应学习率优化器
loss='sparse_categorical_crossentropy', # 稀疏分类交叉熵损失
metrics=['accuracy']) # 监控准确率指标
# 训练模型(为节省时间仅训练3个epoch;生产环境建议10-20个epoch)
cnn_history = cnn_model.fit(train_images, train_labels, epochs=3, # 训练3轮
batch_size=64, validation_split=0.2, verbose=0) # 批大小64,20%验证集