3.1-3.5随机梯度,优化器,损失函数,参数初始化方法
PyTorch 网络参数、初始化与优化器练习
本节主要练习 PyTorch 中神经网络参数相关的基本操作,包括:
nn.Module定义神经网络parameters()查看模型参数nn.Sequential组织网络层weight与bias- 神经网络参数初始化
model.apply()批量初始化- 为不同网络模块设置不同学习率
- Adam 优化器
- PyTorch 标准训练流程
- 权重分布可视化
1. 查看神经网络参数
首先创建一个简单的全连接层:
import torch.nn as nn
hidden = nn.Linear(10, 5)
这一层表示:
10维输入
↓
Linear(10, 5)
↓
5维输出
全连接层本质上执行:
[
y = Wx + b
]
其中:
weight的 shape 为[5, 10]bias的 shape 为[5]
可以使用:
print(type(hidden.parameters()))
查看 parameters() 返回的类型:
<class 'generator'>
也就是说,parameters() 返回的是一个生成器,可以把它转换成列表观察:
params_list = list(hidden.parameters())
print(f"这一层有 {len(params_list)} 个参数变量")
print(params_list[0].shape)
print(params_list[1].shape)
输出:
这一层有 2 个参数变量
torch.Size([5, 10])
torch.Size([5])
因此:
params_list[0] → weight → 5 × 10
params_list[1] → bias → 5
也可以直接查看权重中的具体数值:
print(params_list[0])
这些数值就是网络中真正需要通过训练不断调整的参数。
2. 使用 nn.Module 定义网络
PyTorch 中通常通过继承 nn.Module 定义自己的神经网络:
import torch
import torch.nn as nn
import torch.optim as optim
class TestNet(nn.Module):
def __init__(self):
super(TestNet, self).__init__()
self.hidden = nn.Sequential(
nn.Linear(13, 10),
nn.ReLU(),
)
self.regression = nn.Linear(10, 1)
def forward(self, x):
x = self.hidden(x)
output = self.regression(x)
return output
testnet = TestNet()
网络的数据流:
13维输入
↓
Linear(13, 10)
↓
ReLU
↓
Linear(10, 1)
↓
1维输出
其中:
nn.Sequential(...)
可以把多个网络层按照顺序组合起来。
3. 为不同网络模块设置不同学习率
PyTorch 的优化器可以把模型参数分成多个 parameter group,并为不同参数组指定不同学习率。
例如:
optimizer = optim.Adam(
[
{
"params": testnet.hidden.parameters(),
"lr": 0.0001
},
{
"params": testnet.regression.parameters(),
"lr": 0.02
}
],
lr=1e-2
)
这里相当于告诉 Adam:
TestNet
│
├── hidden
│ └── lr = 0.0001
│
└── regression
└── lr = 0.02
也就是说:
hidden部分学习得慢一些regression部分学习得快一些
最外面的:
lr=1e-2
是优化器的默认学习率。
如果某个 parameter group 已经单独设置了 lr,则该组使用自己的学习率。
4. PyTorch 标准训练流程
基本训练循环:
for input, target in dataset:
optimizer.zero_grad()
output = testnet(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
整个过程:
input
↓
forward()
↓
output
↓
与 target 比较
↓
loss
↓
backward()
↓
计算参数梯度
↓
optimizer.step()
↓
更新 weight / bias
optimizer.zero_grad()
optimizer.zero_grad()
清除上一轮训练留下的梯度。
forward
output = testnet(input)
调用:
TestNet.forward()
进行前向传播,计算网络输出。
loss
loss = loss_fn(output, target)
比较:
模型预测 output
↓
loss
↑
真实结果 target
用于衡量模型当前预测结果和目标之间的差异。
backward
loss.backward()
通过 PyTorch 的自动微分系统计算 loss 对各个可学习参数的梯度。
计算完成之后,可以通过:
parameter.grad
查看对应参数的梯度。
optimizer.step()
optimizer.step()
优化器根据:
参数当前值
+
参数梯度
+
优化算法
+
learning rate
更新模型参数。
5. 定义包含卷积层的网络
例如:
import torch
import torch.nn as nn
class TestNet(nn.Module):
def __init__(self):
super(TestNet, self).__init__()
self.conv1 = nn.Conv2d(3, 16, 3)
self.hidden = nn.Sequential(
nn.Linear(100, 100),
nn.ReLU(),
nn.Linear(100, 50),
nn.ReLU(),
)
self.cla = nn.Linear(50, 10)
def forward(self, x):
x = self.conv1(x)
x = x.view(x.shape[0], -1)
x = self.hidden(x)
output = self.cla(x)
return output
testnet = TestNet()
print(testnet)
打印网络:
TestNet(
(conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1))
(hidden): Sequential(
(0): Linear(in_features=100, out_features=100, bias=True)
(1): ReLU()
(2): Linear(in_features=100, out_features=50, bias=True)
(3): ReLU()
)
(cla): Linear(in_features=50, out_features=10, bias=True)
)
整体结构:
Image
↓
Conv2d
↓
Feature Maps
↓
Flatten
↓
Linear(100, 100)
↓
ReLU
↓
Linear(100, 50)
↓
ReLU
↓
Linear(50, 10)
↓
10维输出
其中:
x = x.view(x.shape[0], -1)
表示:
保留 batch 维度
+
把后面的所有维度展开
例如:
[32, 16, 5, 5]
↓
[32, 400]
这样卷积层产生的特征才能继续输入 Linear。
需要注意:
nn.Linear(100, 100)
要求前面的卷积结果展开后必须正好有 100 个特征。
因此这个网络目前主要用于练习网络定义,实际使用时需要根据输入图片大小计算卷积后的 shape。
6. 神经网络参数初始化
创建网络层时,PyTorch 会自动初始化参数。
例如:
conv1 = torch.nn.Conv2d(3, 16, 3)
此时 conv1 已经拥有:
weight
bias
也可以手动重新初始化。
7. 正态分布初始化
例如:
torch.nn.init.normal_(
conv1.weight,
mean=0,
std=1
)
表示使用正态分布初始化权重:
[
W \sim N(0,1)
]
其中:
mean = 0
std = 1
8. 均匀分布初始化
例如:
torch.nn.init.uniform_(
m.weight,
a=-0.1,
b=0.1
)
表示:
[
W \sim U(-0.1,0.1)
]
权重会从:
[-0.1, 0.1]
之间随机产生。
9. 常数初始化
偏置可以直接初始化成固定值:
torch.nn.init.constant_(
conv1.bias,
val=0.1
)
也可以:
m.bias.data.fill_(0.01)
将所有 bias 设置为:
0.01
10. 使用 apply() 初始化整个网络
可以定义自己的初始化函数:
def init_weight(m):
if type(m) == nn.Conv2d:
torch.nn.init.normal_(
m.weight,
mean=0,
std=0.5
)
if type(m) == nn.Linear:
torch.nn.init.uniform_(
m.weight,
a=-0.1,
b=0.1
)
m.bias.data.fill_(0.01)
然后:
testnet.apply(init_weight)
apply() 会遍历网络中的各个 module,并把它们依次传给 init_weight()。
因此可以根据网络层的类型选择不同初始化方法:
TestNet
│
├── Conv2d
│ └── Normal(mean=0, std=0.5)
│
├── Linear
│ └── Uniform(-0.1, 0.1)
│
├── ReLU
│
├── Linear
│ └── Uniform(-0.1, 0.1)
│
├── ReLU
│
└── Linear
└── Uniform(-0.1, 0.1)
ReLU 没有需要初始化的 weight 和 bias,因此函数不会对它进行处理。
11. 随机种子
可以使用:
torch.manual_seed(13)
设置 PyTorch 随机数生成器的随机种子。
这样在相同环境和相同操作顺序下,更容易复现随机初始化结果。
需要注意代码执行顺序。
例如:
conv1 = torch.nn.Conv2d(3, 16, 3)
torch.manual_seed(12)
创建 Conv2d 时默认初始化已经发生了,因此后面设置 seed 不会改变刚才已经产生的随机参数。
如果希望控制 Conv2d 创建时的默认随机初始化,应写:
torch.manual_seed(12)
conv1 = torch.nn.Conv2d(3, 16, 3)
即:
设置 seed
↓
产生随机数
12. 查看 Conv2d 的 weight
创建:
conv1 = torch.nn.Conv2d(3, 16, 3)
查看:
print(conv1.weight.shape)
得到:
torch.Size([16, 3, 3, 3])
四个维度分别表示:
[out_channels, in_channels, kernel_height, kernel_width]
因此:
16 → 16个卷积核 / 输出通道
3 → 每个卷积核处理3个输入通道
3 → kernel height
3 → kernel width
可以进一步:
print(conv1.weight[0])
查看第一个卷积核的权重。
13. 可视化权重分布
可以使用 Matplotlib 查看网络权重的分布。
import torch
import matplotlib.pyplot as plt
conv1 = torch.nn.Conv2d(3, 16, 3)
torch.nn.init.normal_(
conv1.weight,
mean=0,
std=1
)
plt.figure(figsize=(8, 6))
plt.hist(
conv1.weight.data.numpy().reshape(-1),
bins=30
)
plt.show()
如果使用:
torch.nn.init.normal_(
conv1.weight,
mean=0,
std=1
)
那么权重理论上服从:
[
N(0,1)
]
直方图应该大致呈现正态分布。
这个实验可以帮助理解:
神经网络中的 weight 并不是什么抽象的东西,本质上就是一个由大量浮点数组成的 Tensor。
训练网络的过程,就是不断调整这些 Tensor 中的数值。
整体理解
这一部分练习可以串成一条完整逻辑:
定义网络
↓
nn.Module
↓
Linear / Conv2d 等网络层
↓
产生可学习 Parameter
↓
weight + bias
↓
初始化参数
↓
model.parameters()
↓
交给 optimizer
↓
输入 x
↓
forward()
↓
得到 output
↓
与 target 计算 loss
↓
loss.backward()
↓
得到 parameter.grad
↓
optimizer.step()
↓
修改 weight / bias
↓
进入下一轮训练
因此,可以把目前对 PyTorch 神经网络训练的理解概括为:
神经网络本质上是一个包含大量可学习参数的函数。输入数据
x经过网络得到预测结果output,再与真实目标target计算loss。PyTorch 通过自动微分计算每个参数对 loss 的梯度,优化器再根据这些梯度调整 weight 和 bias,使模型的预测结果逐渐接近目标。
本节涉及的核心 API
nn.Module
nn.Linear
nn.Conv2d
nn.Sequential
nn.ReLU
model.parameters()
model.named_parameters()
model.apply()
torch.nn.init.normal_
torch.nn.init.uniform_
torch.nn.init.constant_
torch.manual_seed()
optim.Adam()
optimizer.zero_grad()
loss.backward()
optimizer.step()
posted on 2026-08-15 14:01 tintin7790 阅读(5) 评论(0) 收藏 举报
浙公网安备 33010602011771号