数值错误:期望目标大小为(128, 44),但实际得到的是torch.Size([128, 100]),LSTM Pytorch。

3
我想建立一个模型,根据先前的字符预测下一个字符。 我已经将文本割成了长度为100的整数序列(使用数据集和数据加载器)。
我的输入和目标变量的维度是:
inputs dimension: (batch_size,sequence length). In my case (128,100)
targets dimension: (batch_size,sequence length). In my case (128,100)

前向传递后,我得到了我的预测维度:(batch_size, sequence_length, vocabulary_size),在这种情况下是(128,100,44)。
但是当我使用nn.CrossEntropyLoss()函数计算损失时:
batch_size = 128
sequence_length   = 100
number_of_classes = 44
# creates random tensor of your output shape
output = torch.rand(batch_size,sequence_length, number_of_classes)
# creates tensor with random targets
target = torch.randint(number_of_classes, (batch_size,sequence_length)).long()

# define loss function and calculate loss
criterion = nn.CrossEntropyLoss()
loss = criterion(output, target)
print(loss)

我遇到了一个错误:
ValueError: Expected target size (128, 44), got torch.Size([128, 100])

问题是:如何处理多对多LSTM预测的损失函数计算?特别是序列维度?根据nn.CrossEntropyLoss,维度必须为(N,C,d1,d2...dN),其中N是batch_size,C是类别数。但是D是什么?它与序列长度有关吗?

你的输入是(128,100,44),而你正在尝试预测下一个字符(基本上是第“101”个字符)。为什么你的预测具有100seq_length?就我个人而言,我会输出(128, 44)(因为我猜测dim=1是长度为44的OHE),并使用该字符预测计算CrossEntropyLoss。编辑:也许我读错了,你是要在每个时间步长(即在输入序列的每个字符预测之后)计算CEL吗? - Ivan
@Ivan:不,我的输入维度为(128,100)-(batch_size,sequence_length)。基本上,我已经将标记化的文本(字符串)转换为整数,然后将输入定义为tokenized_text[:-1],将目标定义为tokenized_text[1:]。因此,目标向右移动一个标记。我的目标是:使用Cross_entropy比较输出中每个预测的整数(一个批次中的100个整数)与目标中的整数(一个批次中的100个整数)。 - Daniel Yefimov
@Ivan 我没有进行One Hot编码,我认为这并不是必需的。因此,我想在每个时间步预测字符。 - Daniel Yefimov
1个回答

3
作为一般性评论,我想说您提出了许多不同的问题,这使得别人难以回答。建议每个StackOverflow帖子只问一个问题,即使这意味着发布多个帖子。我将仅回答我认为您正在问的主要问题:“为什么我的代码崩溃了,如何修复?”并希望这会解决您其他的问题。
根据您的代码,您的模型输出具有尺寸(128, 100, 44)=(N,D,C)。在这里,N是小批量大小,C是类别数目,D是您的输入的维度。您正在使用的交叉熵损失期望输出具有尺寸(N,C,D),并且目标具有尺寸(N,D)。请注意,文档中写着(N,C,D1,D2,...,Dk),记住,您的输入可以是任意维度的任意张量。在您的情况下,输入长度为100,但是没有什么可以阻止某人制作一个以100x100图像作为输入的模型。在那种情况下,损失将期望输出具有尺寸(N,C,100,100)。但在您的情况下,您的输入是一维的,因此您只有一个D = 100作为输入的长度。
现在我们看到了错误,输出应该是(N,C,D),但您的输出是(N,D,C)。您的目标具有正确的尺寸(N,D)。您有两个解决问题的方法。第一种是更改网络结构,使其输出为(N,C,D),这可能很容易或不容易,在您的模型上下文中是否合适。第二个选项是在损失计算时转置轴使用torch.transposehttps://pytorch.org/docs/stable/generated/torch.transpose.html
batch_size = 128
sequence_length   = 100
number_of_classes = 44
# creates random tensor of your output shape (N, D, C)
output = torch.rand(batch_size,sequence_length, number_of_classes)
# transposes dimensionality to (N, C, D)
tansposed_output = torch.transpose(output, 1, 2)
# creates tensor with random targets
target = torch.randint(number_of_classes, (batch_size,sequence_length)).long()

# define loss function and calculate loss
criterion = nn.CrossEntropyLoss()
loss = criterion(transposed_output, target)
print(loss)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接