initialization - 为什么这个模型在没有手动权重初始化步骤的情况下无法收敛(pytorch 线性回归)
问题描述
我正在尝试创建一个最简单的 1 线性层网络来拟合线性回归。只是为了帮助自己更好地理解 Pytorch 的工作原理。但是,我在模型训练中遇到了一个奇怪的问题。
在我的模型的 init() 方法中,我必须添加一个手动初始化步骤(如下所示),以使模型快速收敛到我的回归函数。(权重值 2、3 是随机数,我可以在这里放任何值,模型仍然会收敛)
self.layer1.weight = torch.nn.Parameter(torch.Tensor([2, 3]))
没有这条线,模型永远不会收敛,训练损失只是在几十万范围内随机波动。有了这条线,它迅速下降到接近 1。
我假设这是因为默认初始权重参数太小,如果我不将它们初始化为远离零。然后我改变了初始值,发现只要我有这条线,收敛总是有效的,我设置的确切值无关紧要。我尝试使用调试器单步执行这一行并使用vars()方法检查self.layer1的属性,唯一改变的是权重,其他一切都保持不变。有人可以解释这里的幕后情况吗?谢谢。
我的整个脚本:
import torch
import numpy as np
class Net(torch.nn.Module):
def __init__(self, input_dim, output_dim):
super(Net, self).__init__()
self.layer1 = torch.nn.Linear(input_dim, output_dim, bias=False)
# the line below is the strange initialization required to
# have the model converge.
self.layer1.weight = torch.nn.Parameter(torch.Tensor([2, 3]))
def forward(self, x):
x = self.layer1(x)
return x
# generate data using the linear regression setup y = 5 * x1 + 3 * x2
sample_size = 10000
input_dim = 2
output_dim = 1
epoch = 30
bs = 100
data = np.random.randn(sample_size, 3)
data[:, :2] = data[:, :2] * 100
# add a normal noise term
data[:, 2] = 5 * data[:, 0] + 3 * data[:, 1] + np.random.randn(sample_size)
data = torch.Tensor(data)
train_x = data[:, :input_dim]
train_y = data[:, input_dim]
net = Net(input_dim, output_dim)
criterion = torch.nn.MSELoss()
optimizer = torch.optim.RMSprop(net.parameters(), lr=.01)
for i in range(epoch):
batch = 0
while batch * bs < train_x.shape[0]:
batch_x = train_x[batch * bs : (batch + 1) * bs, :]
batch_y = train_y[batch * bs : (batch + 1) * bs]
pred_y = net.forward(batch_x)
loss = criterion(pred_y, batch_y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
#print(f"{i} {batch} {loss}")
print(net.layer1.weight)
batch += 1
解决方案
快速说明:您的代码无法编译,请修改此行,如下所示:
self.layer1.weight = torch.nn.Parameter(torch.Tensor([[2, 3]]))
无论权重初始化如何,我都无法让您的模型收敛。经过一些实验,我发现将批量大小降低到一个就可以了:
$ python main.py
Parameter containing:
tensor([[0.7388, 0.3678]], requires_grad=True)
Parameter containing:
tensor([[1.7438, 1.0657]], requires_grad=True)
Parameter containing:
tensor([[2.3338, 1.5431]], requires_grad=True)
Parameter containing:
tensor([[2.9008, 1.9784]], requires_grad=True)
Parameter containing:
tensor([[3.2375, 2.1437]], requires_grad=True)
Parameter containing:
tensor([[3.6419, 2.4014]], requires_grad=True)
Parameter containing:
tensor([[4.0652, 2.6458]], requires_grad=True)
Parameter containing:
tensor([[4.5095, 2.7628]], requires_grad=True)
Parameter containing:
tensor([[4.7711, 2.8982]], requires_grad=True)
Parameter containing:
tensor([[4.9131, 2.9768]], requires_grad=True)
Parameter containing:
tensor([[4.9887, 2.9979]], requires_grad=True)
...
推荐阅读
- heroku - Rails 部署期间的“意外令牌:名称(closeBootstrapDatepicker)”
- react-native - 如何在 React Native 中检测键盘何时打开或关闭
- python-3.x - h5py 的 hdf5 版本
- tensorflow - 使用 TensorFlow Transform 有效地将标记转换为词向量
- python - 限制 Tesseract 中的多处理核心
- reactjs - 在创建反应应用程序中安装 sass 的最佳方法
- html - 需要借助类名来访问
- css - 保持下拉
- css - 标准媒体查询使网站响应
- android - Windows emulator.exe PANIC:缺少“x86”CPU 的仿真器引擎程序