🧪 MNIST先导课程实验报告
| 课程名称 |
课程1 单值线性回归(无权重,直接更新预测值) |
日期 |
|
| 学生姓名 |
|
班级/学号 |
|
🎯一、实验目的
- 固定初始值, 使用不同的学习率, 观察收敛速度
- 固定学习率, 使用不同的初始值, 观察收敛速度
- 绘制损失曲线和梯度曲线, 分析两者关系
🔧 二、实验参数设置
| 参数名 |
符号 |
说明 |
| 输入线索 |
clue |
8 |
| 目标值 |
target |
10 |
| 学习率 |
η |
0.1 |
- 实验1:固定目标值(如 target=5),改变初始预测值(如 pred=8, pred=12, pred=-3),观察损失下降曲线,分析收敛速度。
- 实验2:固定初始预测值(如 pred=8),改变学习率(如 η=0.01, 0.1, 0.5),观察损失曲线的震荡或发散现象。
- 实验3:如果初始值和目标值非常接近(如 pred=5.01, target=5),学习率 η=0.1,观察损失曲线和梯度的情况。
- 实验4:使用 pydraw 同时绘制损失和预测梯度
grad_pred 的变化曲线,分析两者关系。
- 手算练习:对前4轮进行手工前向计算,填写表格。
四、代码运行结果
📊 4.1 训练过程中的损失变化曲线和梯度变化曲线
![图片]()
点击放大显示 损失变化曲线
📝 4.2 训练过程生成的数据表格 (前3行+后3行), Early stop 机制
4.2.1 输入线索 clue = 8 , 目标值 target = 10 , 学习率 η = 0.1 , 停止阈值 Threshold = 0.0001
| 轮次 |
模型输出 (预测值) |
损失 |
预测梯度 |
| 0 |
8 |
4 |
4 |
| 1 |
8.4 |
2.56 |
3.2 |
| 2 |
8.72 |
1.6384 |
2.56 |
| 30 |
/ |
/ |
/ |
| 31 |
/ |
/ |
/ |
| 32 |
/ |
/ |
/ |
4.2.2 输入线索 clue = 8 , 目标值 target = 10 , 学习率 η = 0.1 , 停止阈值 Threshold = 0.00001
| 轮次 |
模型输出 (预测值) |
损失 |
预测梯度 |
| 0 |
8 |
4 |
4 |
| 1 |
8.4 |
2.56 |
3.2 |
| 2 |
8.72 |
1.6384 |
2.56 |
| 30 |
/ |
/ |
/ |
| 31 |
/ |
/ |
/ |
| 32 |
/ |
/ |
/ |
4.2.3 输入线索 clue = 120 , 目标值 target = 10 , 学习率 η = 0.1 , 停止阈值 Threshold = 0.00001
| 轮次 |
模型输出 (预测值) |
损失 |
预测梯度 |
| 0 |
120 |
12100 |
220 |
| 1 |
98 |
7744 |
176 |
| 2 |
80 |
4956 |
140.8 |
| 30 |
10.1362 |
0.0185 |
0.2723 |
| 31 |
10.1089 |
0.0119 |
0.2179 |
| 32 |
10.0872 |
0.0076 |
0.1743 |
4.2.4 输入线索 clue = 120 , 目标值 target = 10 , 学习率 η = 0.01 , 停止阈值 Threshold = 0.0001
| 轮次 |
模型输出 (预测值) |
损失 |
预测梯度 |
| 0 |
120 |
12100 |
220 |
| 1 |
117.8 |
11620.84 |
215.6 |
| 2 |
115.644 |
11160.6547 |
211.288 |
| 30 |
70.0033 |
3600.3930 |
120.0066 |
| 31 |
68.8032 |
3457.8175 |
117.6064 |
| 32 |
67.6271 |
3320.8879 |
115.2543 |
4.2.5 输入线索 clue = 120, 目标值 target = 10, 学习率 η = 0.9, 停止阈值 Threshold = 0.0001
| 轮次 |
模型输出 (预测值) |
损失 |
预测梯度 |
| 0 |
120 |
12100 |
220 |
| 1 |
-78 |
7744 |
-176 |
| 2 |
80 |
4956 |
140 |
| 30 |
10.1362 |
0.0185 |
0.2723 |
| 31 |
9.8911 |
0.0119 |
0.2179 |
| 32 |
10.0872 |
0.0076 |
0.1743 |
4.3 最终参数与最终损失
| clue |
target |
η |
轮次 |
最终输出 |
最终损失 |
备注 |
| 5 |
8 |
0.1 |
30 |
|
0.0001 |
|
| 5 |
18 |
0.1 |
60 |
|
0.0001 |
|
| 5 |
80 |
0.1 |
70 |
|
0.0001 |
|
| 5 |
8000 |
0.1 |
130 |
|
0.0001 |
|
| 5.0.1 |
5 |
0.1 |
270 |
|
0.0001 |
|
🎉 五、观察与分析
- 学习率的影响:当学习率过大/过小时,观察到了什么现象? 当学习率过大时,梯度会发生震荡和不降反增现象;当学习率过小时,损失下降缓慢,最终停止学习
- 神经元死亡现象:是否观察到梯度为0、参数不再更新的情况?如何判断?
是的。当学习率过小时,会发生神经元死亡现象,即参数不再更新
✨ 六、实验结论
(总结本次实验的核心发现,例如:学习率需要适中才能稳定收敛;Leaky ReLU 可以有效避免神经元死亡等)
七、附录:实验代码
(可附上本次实验的核心代码片段,或说明代码存放位置)
from pydraw import pydraw
from datetime import datetime
def trainmodule1(target:int,clue:int,rate:float):
draw = pydraw()
pred=clue
for epoch in range(20):
loss = (pred-target)*(pred-target)
grad = 2*(pred-target)
print(f"epoch={epoch},pred={pred:.4f},loss={loss:.4f}")
draw.add(loss,"loss")
draw.add(grad,"grad")
pred = pred-(rate*grad)
draw.draw()
def trainmodule2(target:int,clue:int,rate:float,stop:float):
draw = pydraw()
draw.xlabel = "Epoch"
draw.ylabel = "Value"
draw.title = "课程1:简单的梯度下降"
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
desc = f"clue={clue}, t={target}, lr={rate}"
pred=clue
found = None
for epoch in range(50):
loss = (pred-target)*(pred-target)
if found is None and loss < 0.0001:
draw.annotate ("Loss<0.0001", xy=(epoch, loss))
found = epoch
grad = 2*(pred-target)
print(f"epoch={epoch},pred={pred:.4f},loss={loss:.4f},grad={grad:.4f}")
draw.add(loss,"loss")
draw.add(grad,"grad")
pred = pred-(rate*grad)
# 添加底部描述
draw.description = desc + f", Loss<0.0001 on epoch={found}, final loss={loss:.8f}" + ", " + timestamp
draw.export("trainingcurves-1.png")
draw.draw()
trainmodule2(10,8,0.1,0.0001)