使用 pytorch 和 tensorflow 实现 BandRNN
Implementing BandRNN with pytorch and tensorflow
所以我想弄清楚如何以我将获得 BandRNN 的方式训练我的矩阵。
BandRnn 是一个对角线 RNN 模型,每个神经元具有不同数量的连接。
例如:
C是每个神经元的连接数。
我发现有一种方法可以关闭 for 循环中的某些梯度,以防止它们被训练如下:
for p in model.input.parameters():
p.requires_grad = False
但我找不到合适的方法来使我的矩阵成为 BandRNN。
希望有人能帮我解决这个问题。
据我所知,您只能 activate/deactivate requires_grad
在张量上,而不是在该张量的不同分量上。相反,你可以做的是将带外的值归零。
首先为乐队创建一个面具,你可以使用torch.ones
with torch.diagflat
:
>>> torch.diagflat(torch.ones(5), offset=1)
通过为 torch.ones
设置正确的维度以及正确的偏移量,您可以生成具有一致形状的偏移对角矩阵。
>>> N = 10; i = -1
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[0., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.]])
>>> N = 10; i = 0
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
>>> N = 10; i = 1
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0.]])
你明白了,按元素对这些矩阵求和可以得到掩码:
>>> N = 10; b = 3
>>> mask = sum(torch.diagflat(torch.ones(N-abs(i)), i) for i in range(-b//2,b//2+1))
>>> mask
tensor([[1., 1., 0., 0., 0.],
[1., 1., 1., 0., 0.],
[1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1.],
[0., 0., 1., 1., 1.]])
然后您可以将 nn.Linear
:
上带外的值归零
>>> m = nn.Linear(N, N)
>>> m.weight.data = m.weight * mask
>>> m.weight
Parameter containing:
tensor([[-0.3321, -0.3377, -0.0000, -0.0000, -0.0000],
[-0.4197, 0.1729, 0.2101, 0.0000, 0.0000],
[ 0.3467, 0.2857, -0.3919, -0.0659, 0.0000],
[ 0.0000, -0.4060, 0.0908, 0.0729, -0.1318],
[ 0.0000, -0.0000, -0.4449, -0.0029, -0.1498]], requires_grad=True)
请注意,您可能需要在每次前向传递时执行此操作,因为带外的参数可能会在训练期间更新为非零值。当然也可以初始化mask
一次,保存在内存中
将所有内容包装成自定义的 nn.Module
.
会更方便
所以我想弄清楚如何以我将获得 BandRNN 的方式训练我的矩阵。
BandRnn 是一个对角线 RNN 模型,每个神经元具有不同数量的连接。
例如:
我发现有一种方法可以关闭 for 循环中的某些梯度,以防止它们被训练如下:
for p in model.input.parameters():
p.requires_grad = False
但我找不到合适的方法来使我的矩阵成为 BandRNN。
希望有人能帮我解决这个问题。
据我所知,您只能 activate/deactivate requires_grad
在张量上,而不是在该张量的不同分量上。相反,你可以做的是将带外的值归零。
首先为乐队创建一个面具,你可以使用torch.ones
with torch.diagflat
:
>>> torch.diagflat(torch.ones(5), offset=1)
通过为 torch.ones
设置正确的维度以及正确的偏移量,您可以生成具有一致形状的偏移对角矩阵。
>>> N = 10; i = -1
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[0., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.]])
>>> N = 10; i = 0
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
>>> N = 10; i = 1
>>> torch.diagflat(torch.ones(N-abs(i)), offset=i)
tensor([[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0.]])
你明白了,按元素对这些矩阵求和可以得到掩码:
>>> N = 10; b = 3
>>> mask = sum(torch.diagflat(torch.ones(N-abs(i)), i) for i in range(-b//2,b//2+1))
>>> mask
tensor([[1., 1., 0., 0., 0.],
[1., 1., 1., 0., 0.],
[1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1.],
[0., 0., 1., 1., 1.]])
然后您可以将 nn.Linear
:
>>> m = nn.Linear(N, N)
>>> m.weight.data = m.weight * mask
>>> m.weight
Parameter containing:
tensor([[-0.3321, -0.3377, -0.0000, -0.0000, -0.0000],
[-0.4197, 0.1729, 0.2101, 0.0000, 0.0000],
[ 0.3467, 0.2857, -0.3919, -0.0659, 0.0000],
[ 0.0000, -0.4060, 0.0908, 0.0729, -0.1318],
[ 0.0000, -0.0000, -0.4449, -0.0029, -0.1498]], requires_grad=True)
请注意,您可能需要在每次前向传递时执行此操作,因为带外的参数可能会在训练期间更新为非零值。当然也可以初始化mask
一次,保存在内存中
将所有内容包装成自定义的 nn.Module
.