Pytorch的AND门

时间:2019-01-30 16:44:00

标签: python deep-learning pytorch

我是PyTorch和深度学习的新手。
我写的代码可以看到更长的时间。 我正在尝试学习简单的“与”问题,该问题是线性的,可以分开。
问题是,我的成绩很差。只有大约2/10倍才能获得正确答案。
有时,loss.item()值会停留在0.250。

只需清理

  • 为什么它只能工作2/10次?

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torch.autograd as autog

data_x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
data_y = np.array([[0, 0, 0, 1]]).T
data_x = autog.Variable(torch.FloatTensor(data_x))
data_y = autog.Variable(torch.FloatTensor(data_y), requires_grad=False)

in_dim = 2
out_dim = 1
epochs = 15000
epoch_print = epochs / 5
l_rate = 0.001

class NeuralNet(nn.Module):
    def __init__(self, input_size, output_size):
        super(NeuralNet, self).__init__()
        self.lin1 = nn.Linear(input_size, output_size)
        self.relu = nn.ReLU()

    def forward(self, x):
        out = x
        out = self.lin1(out)
        out = self.relu(out)
        return out

model = NeuralNet(in_dim, out_dim)
criterion = nn.L1Loss()
optimizer = optim.Adam(model.parameters(), lr=l_rate)

for epoch in range(epochs):
    pred = model(data_x)
    loss = criterion(pred, data_y)
    loss.backward()
    optimizer.step()
    if (epoch + 1) % epoch_print == 0:
        print("Epoch %d  Loss %.3f" %(epoch + 1, loss.item()))


for x, y in zip(data_x, data_y):
    pred = model(x)
    print("Input", list(map(int, x)), "Pred", int(pred), "Output", int(y))

1 个答案:

答案 0 :(得分:1)

1。在优化器中使用zero_grad

您没有使用optimizer.zero_grad()来清除渐变。您的学习循环应如下所示:

for epoch in range(epochs):
    optimizer.zero_grad()
    pred = model(data_x)
    loss = criterion(pred, data_y)
    loss.backward()
    optimizer.step()
    if (epoch + 1) % epoch_print == 0:
        print("Epoch %d  Loss %.3f" %(epoch + 1, loss.item()))

在这种特殊情况下,梯度不会累积任何有害影响,但是当您循环遍历同一数据集时,它几乎没有任何区别(不过,您应该养成这种习惯,因为您将使用它)在您的整个深度学习过程中。

2。成本函数

您正在使用均值绝对误差,它是回归损失函数,而不是分类函数(您所做的是二进制分类)。

因此,您应该使用BCELoss并进行S字形激活,或者(我更喜欢这样做),从网络返回登录并使用BCEWithLogitsLoss,两者都计算二进制交叉熵(交叉熵的简化版本)。

参见下文:

class NeuralNet(nn.Module):
    def __init__(self, input_size, output_size):
        super(NeuralNet, self).__init__()
        self.lin1 = nn.Linear(input_size, output_size)

    def forward(self, x):
        # You may want to use torch.nn.functional.sigmoid activation
        return self.lin1(x)

...
# Change your criterion to nn.BCELoss() if using sigmoid
criterion = nn.BCEWithLogitsLoss()
...

3。预测

如果使用logits版本,则分类器将学习为0标签分配负值,并为1分配正值。必须修改显示功能以结合以下知识:

for x, y in zip(data_x, data_y):
    pred = model(x)
    # See int(pred > 0), that's the only change
    print("Input", list(map(int, x)), "Pred", int(pred > 0), "Output", int(y))

如果您的转发将sigmoid应用于输出,则此步骤不适用。哦,最好使用torch.round而不是强制转换为int