【问题标题】:(Single Layer) Perceptron in PyTorch, bad convergence(单层)PyTorch 中的感知器,收敛性差
【发布时间】:2018-12-14 08:08:16
【问题描述】:

我正在尝试使用 PyTorch (v0.4.0) 开发一个简单的单层感知器来分类 AND 布尔运算。 我想通过使用 autograd 计算权重和偏差的梯度,然后以 SGD 方式更新它们来开发它。

代码很简单,如下:

# AND points and labels
data = torch.tensor([
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
    ], dtype=torch.float32)
labels = torch.tensor([0,0,0,1], dtype=torch.float32)

weights = torch.zeros(2, dtype=torch.float32, requires_grad=True)
bias = torch.zeros(1, requires_grad=True)
losses = []
epochs = 100
eta = 0.01
for epoch in range(epochs):
    total_loss = 0
    for idx in range(4):
        # take current input
        X = data[idx,:]
        y = labels[idx]

        # compute output and loss
        out = torch.add(torch.dot(weights, X), bias)
        loss = (out-y).pow(2)
        total_loss += loss.item()
        # backpropagation
        loss.backward()

        # compute accuracy and update parameters
        with torch.no_grad():
            weights -= eta * weights.grad
            bias -= eta * bias.grad
            # reset gradient to zero
            weights.grad.zero_()
            bias.grad.zero_()
    losses.append(total_loss)

从学习曲线可以看出,模型收敛 但生成的飞机是:

准确率达到 50%。

我尝试了不同的初始参数,也尝试了 PyTorch 的 SGD 优化器,但没有任何改变。 我知道 MSE 是一种回归损失,但我认为问题不存在。

有什么想法吗?

更新 平面是用这两行代码计算出来的

xr = np.linspace(0, 1, 10)
yr = (-1 / weights[1].item()) * (weights[0].item() * xr  + bias.item())
plt.plot(xr,yr,'-')

【问题讨论】:

  • 1.由此产生的飞机对我来说看起来是正确的。 2. 尝试将损失更改为 NLL。
  • 平面不正确,因为在 AND 中它应该将右上角与所有其他点分开,因为它是唯一带有标签 1 的点。
  • 你是如何计算平面的?
  • 查看上面的更新问题
  • 您是如何得出yr 的公式的?或者你从哪里得到的?

标签: pytorch perceptron


【解决方案1】:

你用来计算平面的方程

yr = (-1 / weights[1].item()) * (weights[0].item() * xr  + bias.item())

是在y_i = [+1, -1] 并且有一个符号函数的情况下得出的:它是通过寻找分离正例和负例的平面来计算的。如果您更改目标,此假设将不再有效。

如果你画这个:

x1 = np.linspace(0, 1, 10)
x2 = np.linspace(0, 1, 10)
X, Y = np.meshgrid(x1, x2)
w1, w2 = weights.detach().numpy()[0, 0], weights.detach().numpy()[1, 0]
b = bias.detach().numpy()[0]
Z = w1*X + w2*Y + b

这是正确的 3D 平面,你得到正确的分离

如果您抵消一个取决于标签平均值的因素,您可以使用公式获得正确的分离,例如:

yr = (-1 / weights[1].item()) * (weights[0].item() * xr  + bias.item() - 0.5)

但我无法正式证明它的合理性。

【讨论】:

  • 是的,它对我有用。使用 (-1, 1) 标签的平均值(即进行分类的偏移量)为 0,但使用 (0,1) 标签的偏移量为 0.5,因此您必须减去该值才能获得前一个案子。谢谢!
【解决方案2】:

我设法通过两种不同的方式解决了这个问题:

方法 1 - 更改 -1 和 1 中的标签
只需将标签从 (0, 1) 更改为 (-1, 1) 即可正确计算平面。

因此,新标签(相同数据)为:

labels = torch.tensor([-1,-1,-1,1], dtype=torch.float32)

方法二——out后添加sigmoid函数
使用 (0, 1) 标签,在计算出来之后添加一个 sigmoid 函数,这样:

out = torch.add(torch.dot(weights, X), bias)
out = torch.sigmoid(out)

我认为方法1解释了感知器的符号函数,因为计划必须根据输出的符号来区分点。
方法 2 通过使用压缩函数将这种推理应用于 (0,1) 标签。
这些只是初步的、部分的解释。尝试在下面发表更准确的评论。

【讨论】:

    猜你喜欢
    • 2018-10-05
    • 1970-01-01
    • 2021-06-28
    • 2020-08-01
    • 2018-10-29
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2018-02-21
    相关资源
    最近更新 更多