手动计算pytorch中的交叉熵损失
manually computing cross entropy loss in pytorch
我正在尝试在 Pytorch 中为编码器-解码器模型手动计算 cross_entropy 损失。
我使用这里发布的代码来计算它:
我更新了代码以丢弃填充的令牌 (-100)。最终代码是这样的:
class compute_crossentropyloss_manual:
"""
y0 is the vector with shape (batch_size,C)
x shape is the same (batch_size), whose entries are integers from 0 to C-1
"""
def __init__(self, ignore_index=-100) -> None:
self.ignore_index=ignore_index
def __call__(self, y0, x):
loss = 0.
n_batch, n_class = y0.shape
# print(n_class)
for y1, x1 in zip(y0, x):
class_index = int(x1.item())
if class_index == self.ignore_index: # <------ I added this if-statement
continue
loss = loss + torch.log(torch.exp(y1[class_index])/(torch.exp(y1).sum()))
loss = - loss/n_batch
return loss
为了验证它是否正常工作,我在文本生成任务上对其进行了测试,并使用 pytorch.nn 实现并使用此代码计算了损失。
损失值不相同:
使用 nn.CrossEntropyLoss
:
使用上面 link 中的代码:
我是不是漏掉了什么?
我试图获取 nn.CrossEntropyLoss
的源代码,但我无法获取。在第 2955 行的 link nn/functional.py 中,您将看到该函数指向另一个名为 torch._C._nn.cross_entropy_loss
的 cross_entropy 损失;我在 repo 中找不到这个函数。
编辑:
我注意到只有当我在黄金中有 -100
个代币时才会出现差异。
演示示例:
y = torch.randint(1, 50, (100, 50), dtype=float)
x = torch.randint(1, 50, (100,))
x[40:] = -100
print(criterion(y, x).item())
print(criterion2(y, x).item())
> 25.55788695847976
> 10.223154783391905
当我们没有 -100
:
x[40:] = 30 # any positive number
print(criterion(y, x).item())
print(criterion2(y, x).item())
> 24.684453267596453
> 24.684453267596453
我通过更新代码解决了这个问题。我在 -100
标记(上面的 if 语句)之前丢弃了,但我忘记减小 hidden_state 大小(在上面的代码中称为 n_batch
)。这样做之后,损失数字与 nn.CrossEntropyLoss
值相同。最终代码:
class CrossEntropyLossManual:
"""
y0 is the vector with shape (batch_size,C)
x shape is the same (batch_size), whose entries are integers from 0 to C-1
"""
def __init__(self, ignore_index=-100) -> None:
self.ignore_index=ignore_index
def __call__(self, y0, x):
loss = 0.
n_batch, n_class = y0.shape
# print(n_class)
for y1, x1 in zip(y0, x):
class_index = int(x1.item())
if class_index == self.ignore_index:
n_batch -= 1
continue
loss = loss + torch.log(torch.exp(y1[class_index])/(torch.exp(y1).sum()))
loss = - loss/n_batch
return loss
我正在尝试在 Pytorch 中为编码器-解码器模型手动计算 cross_entropy 损失。
我使用这里发布的代码来计算它:
我更新了代码以丢弃填充的令牌 (-100)。最终代码是这样的:
class compute_crossentropyloss_manual:
"""
y0 is the vector with shape (batch_size,C)
x shape is the same (batch_size), whose entries are integers from 0 to C-1
"""
def __init__(self, ignore_index=-100) -> None:
self.ignore_index=ignore_index
def __call__(self, y0, x):
loss = 0.
n_batch, n_class = y0.shape
# print(n_class)
for y1, x1 in zip(y0, x):
class_index = int(x1.item())
if class_index == self.ignore_index: # <------ I added this if-statement
continue
loss = loss + torch.log(torch.exp(y1[class_index])/(torch.exp(y1).sum()))
loss = - loss/n_batch
return loss
为了验证它是否正常工作,我在文本生成任务上对其进行了测试,并使用 pytorch.nn 实现并使用此代码计算了损失。
损失值不相同:
使用 nn.CrossEntropyLoss
:
使用上面 link 中的代码:
我是不是漏掉了什么?
我试图获取 nn.CrossEntropyLoss
的源代码,但我无法获取。在第 2955 行的 link nn/functional.py 中,您将看到该函数指向另一个名为 torch._C._nn.cross_entropy_loss
的 cross_entropy 损失;我在 repo 中找不到这个函数。
编辑:
我注意到只有当我在黄金中有 -100
个代币时才会出现差异。
演示示例:
y = torch.randint(1, 50, (100, 50), dtype=float)
x = torch.randint(1, 50, (100,))
x[40:] = -100
print(criterion(y, x).item())
print(criterion2(y, x).item())
> 25.55788695847976
> 10.223154783391905
当我们没有 -100
:
x[40:] = 30 # any positive number
print(criterion(y, x).item())
print(criterion2(y, x).item())
> 24.684453267596453
> 24.684453267596453
我通过更新代码解决了这个问题。我在 -100
标记(上面的 if 语句)之前丢弃了,但我忘记减小 hidden_state 大小(在上面的代码中称为 n_batch
)。这样做之后,损失数字与 nn.CrossEntropyLoss
值相同。最终代码:
class CrossEntropyLossManual:
"""
y0 is the vector with shape (batch_size,C)
x shape is the same (batch_size), whose entries are integers from 0 to C-1
"""
def __init__(self, ignore_index=-100) -> None:
self.ignore_index=ignore_index
def __call__(self, y0, x):
loss = 0.
n_batch, n_class = y0.shape
# print(n_class)
for y1, x1 in zip(y0, x):
class_index = int(x1.item())
if class_index == self.ignore_index:
n_batch -= 1
continue
loss = loss + torch.log(torch.exp(y1[class_index])/(torch.exp(y1).sum()))
loss = - loss/n_batch
return loss