问题描述
我正在尝试实施本文,并坚持了这一简单步骤。尽管这是要引起注意的,但我坚持要做的只是如何在不使用for循环的情况下实现添加到矩阵的向量的排列。
注意力得分上添加了一个学习的偏向矢量,理论上讲,它对得分代表的两个标记的相对位置(j-i)进行编码 因此,alpha是一个T x T矩阵,T取决于要转发的批次,而B是一个学习的偏差矢量,其长度必须固定且最大为2T。我相信本文所建议的当前实现是:
def __init__(...):
...
self.bias = torch.nn.Parameter(torch.randn(config.n),requires_grad = True)
stdv = 1. / math.sqrt(self.bias.data.size(0))
self.bias.data.uniform_(-stdv,stdv)
def forward(..)
...
#n = 201 (2* max_seq_len + 1)
B_matrix = torch.zeros(self.T,self.T) # 60 x 60
for i in range(self.T):
B_matrix[i] = self.bias[torch.arange(start=n//2-i,end=n//2-i+T)])]
attention_scores = attention_scores + B_matrix.unsqueeze(0)
# 64 x 60 x 60
...
这是唯一相关的部分
B_matrix = torch.zeros(self.T,end=n//2-i+T)])]
基本上试图不使用for循环遍历每一行。
但我知道这在模型很大时肯定是效率低下的,而且成本很高。我正在对每行进行显式的for循环,以获取学习到的偏差向量的排列。
有人可以通过智能广播帮助我更好的方法吗?
考虑之后,我不需要实例化零矩阵,但是仍然不能摆脱for循环吗?并且不能使用Gather,因为B_matrix的大小不同于平铺的b向量。
functor = lambda i : bias[torch.arange(start=n//2-i,end=n//2-i+T)]
B_matrix = torch.stack([functor(i) for i in torch.arange(T)])
解决方法
我无法弄清楚应该在您的代码中使用n
是什么,但是我认为以下使用torch.meshgrid
的示例可以满足您的需求。
假设
n,m = 10,20 # arbitrary
a = torch.randn(n,m)
b = torch.randn(n + m)
然后
for i in range(n):
for j in range(m):
a[i,j] = a[i,j] + b[n - i + j]
等同于
ii,jj = torch.meshgrid(torch.arange(n),torch.arange(m))
a = a + b[n - ii + jj]
尽管后者是不适当的操作,这通常是一件好事。如果您确实需要就地操作,则将a =
替换为a[...] =
。
请注意,这是integer array indexing的示例,其中我们使用与b
相同形状的张量来索引a
。