我是PyTorch和深度学习的新手。
我写的代码可以看到更长的时间。
我正在尝试学习简单的“与”问题,该问题是线性的,可以分开。
问题是,我的成绩很差。只有大约2/10倍才能获得正确答案。
有时,loss.item()值会停留在0.250。
只需清理
。
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))
答案 0 :(得分:1)
您没有使用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()))
在这种特殊情况下,梯度不会累积任何有害影响,但是当您循环遍历同一数据集时,它几乎没有任何区别(不过,您应该养成这种习惯,因为您将使用它)在您的整个深度学习过程中。
您正在使用均值绝对误差,它是回归损失函数,而不是分类函数(您所做的是二进制分类)。
因此,您应该使用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()
...
如果使用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
。