前置理论
神经网络的前向传播:核心每一层都是加权求和和激活函数,实质为矩阵运算+非线性运算
常见的激活函数:
- Sigmoid()函数:可以将数据转换成0~1的概率 $$f(x)=\frac{1}{1+e^{-x}}$$
- ReLU()函数:当输入小于0时,输出0;输入大于0时则为线性函数,直接输出值$$f(x)=max(0,x)$$
- Tanh()函数:是一种三角函数,其输出范围是-1~1,对于神经网络来说,其优点是更容易处理负值(Sigmoid()和ReLU()函数没有负值) $$f(x)=\frac{\sin x}{\cos x}$$
- Softmax()函数:讲输入值转换成0~1的实数,如同是对应输入值的概率程序

神将网络损失函数:预测误差+正则化惩罚,损失函数越小,表示模型越好。
深度学习的回归问题经常使用均方误差,而分类问题则是使用交叉熵

神将网络反向传播:高效计算所有参数的误差梯度,从而指导网络向更小损失的方向更新
梯度下降法:知道参数更新方向,沿着使频率下降最快的方向更新参数
就是每一个隐藏层中的加权求和部分,神经网络最开始每一条边上的权值肯定不是一开始就好的(甚至可以说最开始每条边的权值就是随便设置的),然后通过反向传播对每条边的权值进行调整,最终是它的预测达到预期误差范围内。

神经网络的学习过程:

上面这几个图中的理论看懂个大概就可以写代码了
神经网络
这里采用:TensorFlow/Keras实战入门—训练第一个神经网络模型 进行关键程序分析
神经网络模型
分类
基础网络模型
tf.keras.Sequential这里实现了一个简单的多层感知机 MLP ,Keras 中最基础的模型容器,用于按线性顺序堆叠网络层(一层接一层,无分支、无跳跃连接等复杂拓扑)
1 2 3 4 5 6 7 8 9 10
| model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=[28,28]), tf.keras.layers.Dense(300, activation="relu"), tf.keras.layers.Dense(100, activation="relu"), tf.keras.layers.Dense(10, activation="softmax"), ])
|
配置模型
model.compile编译模型,为模型设定训练规则,确定优化器、损失函数、评估指标三大核心要素
使用 Adam 优化器(自适应学习率)和 categorical_crossentropy损失函数。
1 2 3
| model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
|
optimizer='adam' :优化器 在模型训练过程中,通过计算损失函数的梯度来更新网络权重,从而使误差最小化
loss='categorical_crossentropy':损失函数(多类交叉熵)
- 1.用于多分类问题
- 2.真实标签是整数
- 3.计算预测和真是之间的差距
metrics=['accuracy']) :评估指标 是计算模型预测正确的样本占总样本的比例(即准确率),从而直观地告诉你模型的表现如何
训练模型
model.fit:启动训练循环,将训练数据输入模型,按设定的轮次和批次迭代更新权重,同时可实时验证模型效果
1 2 3 4
| history = model.fit(train_images, train_labels_cat, epochs=20, batch_size=64, validation_split=0.2)
|
- epochs=20: 遍历数据集20次,训练20轮
- batch_size=64: 每次更新参数使用64张图片
- validation_split=0.2: 划出20%训练数据用于验证集,不参与训练,仅用于评估
如果对已知数据有很高的正确性,但是对位置数据的预测很差,就成为过度拟合,即一个没有泛化性的预测模型。
即当训练集的表现效果很好,但验证集趋于平缓,此时就会造成过拟合
回归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| tf.random.set_seed(42) norm_layer = tf.keras.layers.Normalization()
model = tf.keras.Sequential([ norm_layer, tf.leras.layers.Dense(50,actication="relu"), tf.leras.layers.Dense(50,actication="relu"), tf.leras.layers.Dense(50,actication="relu"), tf.keras.layers.Dense(1) ])
model.compile( loss="mse", optimizer="Adam", metrics=["RMSE"] )
|

随机搜索
1 2 3
| random_search_tuner = kt.RandomSearch(build_model, objective="val_accurancy", max_trials=5, overwrite=True, directory="my_fashion_mnist", project_name="my_rnd_search", seed=42)
random_search_tuner.search(X_train, y_train, epochs=10, validation_data=(X_valid, y_valid))
|
参数说明
objective:以验证集准确率(val_accuracy)作为优化目标
max_trials=5:最多尝试5组超参数组合
directory:保存调优结果的目录
project_name:本次调优项目名称
seed=42:随机种子,保证可复现
epochs=10:每个超参数组合训练10个epoch
validation_data:验证集,用于评估模型

代码
多分类任务 —— Fashion MNIST 服饰识别
采用Keras内置数据集fashion_mnist来进行训练
数据预加载和数据预处理
采用keras中内部数据进行本次实验train_images, train_labels这部分将用于训练,这部分将用于训练后的测验test_images, test_labels
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| (train_images, train_labels),(test_images, test_labels) = tf.keras.datasets.fashion_mnist.load_data()
print(f"训练集图片形状: {train_images.shape}") print(f"训练集标签形状: {train_labels.shape}") print(f"标签示例(原始): {train_labels[:5]}")
train_images = train_images / 255.0 test_images = test_images / 255.0 print(f"\n归一化后像素值范围: {train_images.min():.1f} ~ {train_images.max():.1f}")
train_labels_cat = tf.keras.utils.to_categorical(train_labels, num_classes=10) test_labels_cat = tf.keras.utils.to_categorical(test_labels, num_classes=10) print(f"\nOne-Hot前: {train_labels[0]}") print(f"One-Hot后: {train_labels_cat[0]}")
|
构建并配置模型
前面已经讲过这部分代码的作用,再简单提一下
构建模型部分:
- Flatten 仅用作数据格式转换,将n维的转换为一维的
- 两个Dense分别是
- 第 1 层隐藏层,300 个神经元,提取低级特征。输入 784 × 神经元 300 + 偏置 300 = 235500
- 第 2 层隐藏层,100 个神经元,组合低级特征形成更高级特征。输入 300 × 神经元 100 + 偏置 100 = 30100
- 第三个Dense是输出层,10 个神经元对应 10 个类别。输入 100 × 神经元 10 + 偏置 10 = 1010
编译模型部分:
优化器 adam
本质是自适应学习率的梯度下降算法。深度学习训练的目标是 “最小化损失”,梯度下降就是沿着损失下降的方向,一步步调整网络里的所有权重。
损失函数 categorical_crossentropy
损失是衡量 “模型预测错了多少” 的量化标准。多分类任务使用分类交叉熵,它计算 “预测概率分布” 和 “真实 One-Hot 分布” 之间的差距:预测越准,损失值越小;预测偏差越大,损失值越大。
评估指标 accuracy
准确率 = 预测正确的样本数 / 总样本数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=[28, 28]), tf.keras.layers.Dense(300, activation='relu'), tf.keras.layers.Dense(100, activation='relu'), tf.keras.layers.Dense(10, activation='softmax') ])
model.summary()
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
|
训练模型并测试
model.fit() 是训练的核心,背后是前面理论的最后一张图的前向传播 + 反向传播的循环迭代
epoch:把全部训练数据完整过一遍,称为 1 个 epoch。这里设置 20,就是让模型把全部训练样本反复学习 20 轮。
batch_size=64:一次性喂入 64 张图片,计算一次损失、更新一次权重。相比单张更新,批量更新提升了训练效率和梯度稳定性。
validation_split=0.2:从训练集中划出 20% 作为验证集,训练时不参与权重更新,专门用来实时评估模型在 “未见过的数据” 上的表现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| history = model.fit( train_images,train_labels_cat, epochs=20, batch_size=64, validation_split=0.2 )
test_loss, test_acc = model.evaluate(test_images,test_labels_cat,verbose=0) print(f"\n【分类】测试集准确率: {test_acc:.4f}")
predictions = model.predict(test_images[:3]) print(f"预测结果(概率):\n{np.round(predictions, 2)}") print(f"预测类别: {np.argmax(predictions, axis=1)}") print(f"真实类别: {test_labels[:3]}")
|
结合结果分析
运行结果:
一、数据加载和数据预处理
1 2 3 4 5 6 7 8 9
| PART 1: 分类任务 训练集图片形状: (60000, 28, 28) 训练集标签形状: (60000,) 标签示例(原始): [9 0 0 3 0]
归一化后像素值范围: 0.0 ~ 1.0
One-Hot前: 9 One-Hot后: [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
|
这里是model.summary() 输出的是网络的完整结构和参数量,对应你代码里搭建的三层全连接网络:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= flatten (Flatten) (None, 784) 0 dense (Dense) (None, 300) 235500 dense_1 (Dense) (None, 100) 30100 dense_2 (Dense) (None, 10) 1010 ================================================================= Total params: 266,610 Trainable params: 266,610 Non-trainable params: 0 _________________________________________________________________
|
二、训练过程详解:20 轮 Epoch 的核心规律
这是份结果最关键的部分,20 行训练日志完整呈现了深度学习「学习→拟合→过拟合」的曲线
阶段 1:正常拟合期(Epoch 1 ~ Epoch 8)
1 2 3 4 5 6 7 8 9 10 11
| Epoch 1/20 750/750 [==============================] - 2s 2ms/step - loss: 0.5064 - accuracy: 0.8193 - val_loss: 0.4630 - val_accuracy: 0.8282 Epoch 2/20 750/750 [==============================] - 1s 2ms/step - loss: 0.3691 - accuracy: 0.8649 - val_loss: 0.3757 - val_accuracy: 0.8609 ...... Epoch 6/20 750/750 [==============================] - 2s 2ms/step - loss: 0.2734 - accuracy: 0.8988 - val_loss: 0.3182 - val_accuracy: 0.8852 Epoch 7/20 750/750 [==============================] - 2s 2ms/step - loss: 0.2574 - accuracy: 0.9028 - val_loss: 0.3372 - val_accuracy: 0.8768 Epoch 8/20 750/750 [==============================] - 2s 2ms/step - loss: 0.2479 - accuracy: 0.9057 - val_loss: 0.3312 - val_accuracy: 0.8819
|
这是模型真正在「学规律」的阶段:
- 训练损失
loss:从 0.5135 持续下降到 0.2487
- 训练准确率
accuracy:从 0.8191 稳步上升到 0.9078
- 验证损失
val_loss:从 0.4132 下降到全程最低点 0.3048
- 验证准确率
val_accuracy:从 0.8535 上升到 0.8923
这个阶段里,训练集和验证集的表现同步变好,说明模型正在从数据中提取通用的服饰特征,泛化能力持续提升,是训练的最优区间。
阶段 2:过拟合显现期(Epoch 9 ~ Epoch 20)
1 2 3 4 5 6 7 8 9 10 11 12 13
| Epoch 9/20 750/750 [==============================] - 2s 3ms/step - loss: 0.2374 - accuracy: 0.9101 - val_loss: 0.3309 - val_accuracy: 0.8863 Epoch 10/20 750/750 [==============================] - 2s 3ms/step - loss: 0.2285 - accuracy: 0.9133 - val_loss: 0.3162 - val_accuracy: 0.8898 Epoch 11/20 750/750 [==============================] - 2s 3ms/step - loss: 0.2168 - accuracy: 0.9185 - val_loss: 0.3232 - val_accuracy: 0.8907 ...... Epoch 19/20 750/750 [==============================] - 2s 2ms/step - loss: 0.1622 - accuracy: 0.9380 - val_loss: 0.3314 - val_accuracy: 0.8912 Epoch 20/20 750/750 [==============================] - 2s 2ms/step - loss: 0.1588 - accuracy: 0.9389 - val_loss: 0.3549 - val_accuracy: 0.8875
【分类】测试集准确率: 0.8808
|
从第 9 轮开始,训练出现了明显的分化,也是深度学习最经典的现象:
- 训练集表现继续一路变好:损失从 0.2357 降到 0.1527,准确率从 0.9118 升到 0.9414
- 验证集表现不再提升,甚至开始变差:
- 验证损失不再下降,整体震荡走高,最后一轮涨到 0.3656
- 验证准确率在 0.88~0.89 之间反复波动,最后一轮甚至掉到 0.8823
过拟合:
模型容量足够大,训练轮数过多后,它不再只学通用规律,开始「死记硬背」训练集里的噪声、个别样本的独有细节;面对从未见过的验证集数据,泛化能力不再提升,反而下降。
三、最终测试集结果
测试集是模型全程完全没接触过的数据,相当于「最终闭卷考试」
1 2 3 4 5 6 7 8 9
| 1/1 [==============================] - 0s 43ms/step 预测结果(概率): [[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]] 预测类别: [9 2 1] 真实类别: [9 2 1]
进程已结束,退出代码为 0
|
总结
模型不是训练越久越好,前期快速学习通用规律,中期达到泛化能力峰值,继续训练就会进入过拟合
过拟合的常见解决方案
- 早停法:监控验证损失,停止下降时立即终止训练
- 正则化:L2 正则化惩罚过大权重,Dropout 随机失活神经元,降低模型对个别样本的依赖
- 降低模型复杂度:减少层数、减少神经元数量
- 增加训练数据:数据量越大,模型越难记住全部样本,越不容易过拟合
回归任务