为什么这个模型在没有手动权重初始化步骤(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)
...

最新更新