我正在尝试使用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,'-')
答案 0 :(得分: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
如果您根据公式的平均值偏移一个因数,则可以正确分离公式,例如:
yr = (-1 / weights[1].item()) * (weights[0].item() * xr + bias.item() - 0.5)
但是我不能正式提出理由。
答案 1 :(得分:0)
我设法用两种不同的方法解决了这个问题:
方法1-更改-1和1中的标签
只需将标签从(0,1)更改为(-1,1),即可正确计算平面。
因此,新标签(相同数据)为:
labels = torch.tensor([-1,-1,-1,1], dtype=torch.float32)
方法2-退出后添加S形函数
使用(0,1)标签,在计算出之后立即添加一个S型函数,方法是:
out = torch.add(torch.dot(weights, X), bias)
out = torch.sigmoid(out)
我认为方法1 解释了感知器的符号功能,因为该计划必须根据输出的符号来区分点。
方法2 通过使用挤压函数将这种推理用于(0,1)标签。
这些只是临时的,部分的解释。尝试在下面用更准确的评论。