Pytorch,在将一个向量的排列添加到矩阵的条目时摆脱 for 循环?
Pytorch, get rid of a for loop when adding permutation of one vector to entries of a matrix?
我正在尝试实现这篇论文,并坚持这个简单的步骤。虽然这与注意力有关,但我坚持的是如何在不使用 for 循环的情况下实现添加到矩阵的向量的排列。
注意力分数添加了学习偏差向量,理论上它编码分数代表的两个标记的相对位置 (j-i)
所以 alpha 是一个 T x T 矩阵,T 取决于被转发的 batch,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, 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)])]
基本上尽量不使用 for 循环遍历每一行。
但我知道这一定非常低效,而且当这个模型非常大时成本很高。我正在对每一行进行显式 for 循环以获得学习偏差向量的排列。
任何人都可以通过智能广播帮助我找到更好的方法吗?
想了想,不用实例化一个零矩阵,但还是摆脱不了for循环?并且不能使用收集,因为 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]
尽管后者是一个 out-of-place 操作,这通常是一件好事。如果您确实想要 in-place 操作,请将 a =
替换为 a[...] =
。
请注意,这是 integer array indexing 的示例,其中我们使用与 a
.
形状相同的张量对 b
进行索引
我正在尝试实现这篇论文,并坚持这个简单的步骤。虽然这与注意力有关,但我坚持的是如何在不使用 for 循环的情况下实现添加到矩阵的向量的排列。
注意力分数添加了学习偏差向量,理论上它编码分数代表的两个标记的相对位置 (j-i)
所以 alpha 是一个 T x T 矩阵,T 取决于被转发的 batch,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, 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)])]
基本上尽量不使用 for 循环遍历每一行。
但我知道这一定非常低效,而且当这个模型非常大时成本很高。我正在对每一行进行显式 for 循环以获得学习偏差向量的排列。
任何人都可以通过智能广播帮助我找到更好的方法吗?
想了想,不用实例化一个零矩阵,但还是摆脱不了for循环?并且不能使用收集,因为 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]
尽管后者是一个 out-of-place 操作,这通常是一件好事。如果您确实想要 in-place 操作,请将 a =
替换为 a[...] =
。
请注意,这是 integer array indexing 的示例,其中我们使用与 a
.
b
进行索引