当对标签使用一种热编码时,Pytorch nn.CrossEntropyLoss 输出错误值
pytorch 259
原文标题 :Pytorch nn.CrossEntropyLoss output wrong values when using one hot encoding for label
我想传入一个包含 4 个这样的值的张量
[.45, .78, .23, .56]
并从网络中得到一个只有最后一个神经元像这样亮的输出
[0,0,0,1]
然后我想传入第二个张量[.67, .89, .34, .12]
并从中得到一个输出,看起来像这样[1,0,0,0]
只有第一个神经元亮起。
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
train = [
[torch.FloatTensor([[.45, .78, .23, .56]]), torch.FloatTensor([[0,0,0,1]]) ],
[torch.FloatTensor([[.67, .89, .34, .12]]), torch.FloatTensor([[1,0,0,0]]) ]
]
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(4, 2)
self.fc2 = nn.Linear(2, 4)
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
return F.softmax(x, dim=0)
net = Net()
print(net)
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1, momentum=0.9, nesterov=True)
criterion = nn.CrossEntropyLoss()
for epoch in range(10):
for data in train:
X, y = data
net.zero_grad()
output = net(X)
loss = criterion(output, y)
loss.backward()
optimizer.step()
print(loss)
# test
X, y = torch.tensor([.45, .78, .23, .56]), torch.tensor([0,0,0,1])
print(net(X), y)
X, y = torch.tensor([.67, .89, .34, .12]), torch.tensor([1,0,0,0])
print(net(X), y)
不幸的是,网络输出垃圾,不对应任何特定的神经元点亮
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor(1.3863, grad_fn=<DivBackward1>)
tensor([0.3175, 0.1841, 0.2063, 0.2922], grad_fn=<SoftmaxBackward0>) tensor([0, 0, 0, 1])
tensor([0.3129, 0.1935, 0.2102, 0.2834], grad_fn=<SoftmaxBackward0>) tensor([1, 0, 0, 0])
我得到这样的输出[0.3175, 0.1841, 0.2063, 0.2922]
这不是网络应该输出的。
我认为这可能是由于 CrossEntropyLoss 函数比较训练数据 (X) 和标签 y 的方式。我认为是这条线导致了问题loss = criterion(output, y)
。
我应该使用什么损失函数来获得所需的结果?
回复
我来回复-
Piotr Grzybowski 评论
问题在于模型中正向函数的输出。 Softmax 应该在维度 1 而不是 0 上计算。请更改它然后它会收敛。
dim (int) — 计算 Softmax 的维度(因此沿 dim 的每个切片的总和为 1)。
您希望它在维度 1 上加到 1 而不是 0。为数据集中的每个样本而不是每个特征求和一个。
Softmax 文档
另一方面,Softmax 只会返回总和为 1 的值。
这将不是
[0, 1, 0, 0]
的向量,而是,例如,[0.05, 0.90, 0.03, 0.01, 0.01]
。在预测之后,您仍然必须使用 argmax 或其他东西来选择最有可能的类。
2年前