【问题标题】:Pytorch Linear Regression with squared features具有平方特征的 Pytorch 线性回归
【发布时间】:2021-05-14 13:12:16
【问题描述】:

我是 PyTorch 的新手,我想部分地使用 PyTorch 实现线性回归,部分地自己实现。我想在回归中使用平方特征:

import torch

# init
x = torch.tensor([1,2,3,4,5])
y = torch.tensor([[1],[4],[9],[16],[25]])
w = torch.tensor([[0.5], [0.5], [0.5]], requires_grad=True)

iterations = 30
alpha = 0.01

def forward(X):
    # feature transformation [1, x, x^2]
    psi = torch.tensor([[1.0, x[0], x[0]**2]])
    for i in range(1, len(X)):
        psi = torch.cat((psi, torch.tensor([[1.0, x[i], x[i]**2]])), 0)
    return torch.matmul(psi, w)
    
def loss(y, y_hat):
    return ((y-y_hat)**2).mean()

for i in range(iterations):
    
    y_hat = forward(x)

    l = loss(y, y_hat)
    l.backward()
    
    with torch.no_grad():
        w -= alpha * w.grad 
    w.grad.zero_()

    if i%10 == 0:
        print(f'Iteration {i}: The weight is:\n{w.detach().numpy()}\nThe loss is:{l}\n')

当我执行我的代码时,回归没有学习到正确的特征,并且损失会永久增加。输出如下:

Iteration 0: The weight is:
[[0.57 ]
 [0.81 ]
 [1.898]]
The loss is:25.450000762939453

Iteration 10: The weight is:
[[ 5529.5835]
 [22452.398 ]
 [97326.12  ]]
The loss is:210414632960.0

Iteration 20: The weight is:
[[5.0884394e+08]
 [2.0662339e+09]
 [8.9567642e+09]]
The loss is:1.7820802835250162e+21

有人知道,为什么我的模型没有学习吗?

更新

它的表现如此糟糕是否有原因?我认为这是因为训练数据数量少。但也有 10 个数据点,它表现不佳:

【问题讨论】:

  • 您在绘图之前是否对值进行了非规范化?
  • 我采用新数据: - 点是预期值 (1,2^2,3^2,..10^2) - 然后我使用从模型接收到的权重和偏差计算 x=1,2,3,..10 的预测。 --> 再说一遍,不应该只有权重中的平方特征为 1,其余(偏差和线性特征)为 0?
  • 如果您在归一化输入上训练模型以预测归一化目标,那么您的权重会针对该任务进行训练。这就是为什么我问你是否,基本上你需要标准化你的测试数据(或psi,这是我在下面的回答中的情况),然后取消标准化psi@w + b 以获得实际预测(@__matmul__ )。
  • 我就是这么做的。我想是你说的:plt.plot(x,[i**2 for i in range(1, 11)], ".") # predictions y_hat = np.linspace(1, 10, 10) y_hat = [(torch.matmul(torch.tensor([x, x**2]).float(), w) + b)[0].item() for x in y_hat] plt.plot(x, y_hat)
  • 否:您评论中的代码显示您尚未规范化 torch.tensor([x, x**2]),也未规范化 y_hat

标签: python pytorch regression


【解决方案1】:

您应该标准化您的数据。此外,由于您试图适应x -> ax² + bx + cc 本质上是偏见。最好将其从训练数据中删除(我在这里指的是psi)并为偏差使用单独的参数。

可以做什么:

  • 用均值和标准差标准化您的输入数据和目标。

  • 将参数分成w(一个双分量权重张量)和b(偏差)。

  • 您不需要在每次推断时都构造 psi,因为 x 是相同的。

  • 你可以用torch.stack([torch.ones_like(x), x, x**2], 1) 构建psi,但在这里我们不需要那些,因为我们基本上已经从权重张量中分离了偏差。

如下所示:

x = torch.tensor([1,2,3,4,5]).float()
psi = torch.stack([x, x**2], 1).float()
psi = (psi - psi.mean(0)) / psi.std(0)

y = torch.tensor([[1],[4],[9],[16],[25]]).float()
y = (y - y.mean(0)) / y.std(0)

w = torch.tensor([[0.5], [0.5]], requires_grad=True)
b = torch.tensor([0.5], requires_grad=True)

iterations = 30
alpha = 0.02
def loss(y, y_hat):
    return ((y-y_hat)**2).mean()

for i in range(iterations):
    y_hat = torch.matmul(psi, w) + b
    l = loss(y, y_hat)
    l.backward()
    
    with torch.no_grad():
        w -= alpha * w.grad 
        b -= alpha * b.grad 
    w.grad.zero_()
    b.grad.zero_()

    if i%10 == 0:
        print(f'Iteration {i}: The weight is:\n{w.detach().numpy()}\nThe loss is:{l}\n')

结果:

Iteration 0: The weight is:
[[0.49954653]
 [0.5004535 ]]
The loss is:0.25755801796913147

Iteration 10: The weight is:
[[0.49503425]
 [0.5049657 ]]
The loss is:0.07994867861270905

Iteration 20: The weight is:
[[0.49056274]
 [0.50943726]]
The loss is:0.028329044580459595

【讨论】:

    猜你喜欢
    • 2018-01-02
    • 2020-05-19
    • 2017-10-24
    • 2020-05-27
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 2019-04-07
    • 2021-12-14
    相关资源
    最近更新 更多