我试图用Pytorch实现Transformer模型,并尝试了this GitHub repo中的示例,该示例与here in the documentation链接,并在模型中的PositionalEncoding类中遇到了问题。 py。
该类的__init__()
函数的代码如下:
def __init__(self, d_model, dropout=0.1, max_len=5000):
super(PositionalEncoding, self).__init__()
self.dropout = nn.Dropout(p=dropout)
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
pe = pe.unsqueeze(0).transpose(0, 1)
self.register_buffer('pe', pe)
以d_model = 103运行的这段代码在最后一行(pe[:, 0::2] =
...)上引发了以下错误:
RuntimeError:张量(52)的扩展大小必须与非单维度1上的现有大小(51)相匹配。目标大小:[5000,52]。张量大小:[5000,51]
我发现此错误相当难以理解,并且编写自己的类似有效实现并没有取得太大的成功。 我的第一个猜测是,这是Python / PyTorch中版本更改的问题,但当然可能是我所缺少的其他东西。
答案 0 :(得分:1)
尝试
0:51:2 instead of 0::2
0 :: 2将生成-> [0,2,4,...,直到元素末尾]
答案 1 :(得分:0)
你可以这样做:
class PositionalEncoding(nn.Module):
def __init__(self, d_model, max_len=1000):
super().__init__()
self.d_model = d_model
self.max_len = max_len
def forward(self):
pos = torch.arange(self.max_len).view(-1, 1).float()
pe = torch.arange(self.d_model).repeat(self.max_len, 1).float()
pe[:, 0::2] = torch.sin(pos / (10000 ** (2 * pe[:, 0::2] / self.d_model)))
pe[:, 1::2] = torch.cos(pos / (10000 ** (2 * pe[:, 1::2] / self.d_model)))
return pe.unsqueeze(0)
当用切片求和时:
x + pe[:, :x.size(1)])
答案 2 :(得分:0)
此错误是因为您的 d_model
是一个奇数。您可以看到 div_term
的形状取决于 torch.arange(0, d_model, 2)
,在您的情况下,形状为 51。
然而,pe[:, 0::2]
的形状是 52。
这通常不会发生,因为在 Transformer 模型中,在将张量放入 PositionalEncoding 之前,它会被放入嵌入层以嵌入成通常为 的形状>偶数(512、128 等)。当 d_model
为偶数时,pe[:, 0::2]
的形状和 div_term
的形状将相等。
所以在你的情况下,你可以通过
d_model
成为偶数(通过将您的输入嵌入到偶数维度中);div_term
pe[:, 0::2]
等于 div_term
def __init__(self, d_model, dropout=0.1, max_len=5000):
super(PositionalEncoding, self).__init__()
self.dropout = nn.Dropout(p=dropout)
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model-1, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 1::2] = torch.cos(position * div_term)
pe = pe.unsqueeze(0).transpose(0, 1)
self.register_buffer('pe', pe)
PS:如果你把pe[:, 0::2]
修改成pe[:, 0:d_model-1:2]
,当然可以,因为你把它变成了51,就像div_term
一样。但这也意味着 pe
的最后一个维度不会被赋值,它仍然为零。这意味着输入的最后一个维度不会进行位置编码。