Pytorchの行列とベクトルの間で++-/ *を実行したい。どうすれば良いパフォーマンスでできますか?エキスパンドを使おうとしましたが、本当に遅いです(小さなベクトルで大きな行列を使用しています)。
a = torch.Rand(2,3)
print(a)
0.7420 0.2990 0.3896
0.0715 0.6719 0.0602
[torch.FloatTensor of size 2x3]
b = torch.Rand(2)
print(b)
0.3773
0.6757
[torch.FloatTensor of size 2]
a.add(b)
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3066, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-17-a1cb1b03d031>", line 1, in <module>
a.add(b)
RuntimeError: inconsistent tensor size, expected r_ [2 x 3], t [2 x 3] and src [2] to have the same number of elements, but got 6, 6 and 2 elements respectively at c:\miniconda2\conda-bld\pytorch-cpu_1519449358620\work\torch\lib\th\generic/THTensorMath.c:1021
期待される結果:
0.7420-0.3773 0.2990-0.3773 0.3896-0.3773
0.0715-0.6757 0.6719-0.6757 0.0602-0.6757
ブロードキャストを利用するには、テンソルb
が2Dであるため、promoteテンソルa
の次元を2次元にする必要があります。
In [43]: a
Out[43]:
tensor([[ 0.9455, 0.2088, 0.1070],
[ 0.0823, 0.6509, 0.1171]])
In [44]: b
Out[44]: tensor([ 0.4321, 0.8250])
# subtraction
In [46]: a - b[:, None]
Out[46]:
tensor([[ 0.5134, -0.2234, -0.3252],
[-0.7427, -0.1741, -0.7079]])
# alternative way to do subtraction
In [47]: a.sub(b[:, None])
Out[47]:
tensor([[ 0.5134, -0.2234, -0.3252],
[-0.7427, -0.1741, -0.7079]])
# yet another approach
In [48]: torch.sub(a, b[:, None])
Out[48]:
tensor([[ 0.5134, -0.2234, -0.3252],
[-0.7427, -0.1741, -0.7079]])
その他の操作(+
、*
)同様に行うことができます。
パフォーマンスの観点から、1つのアプローチを他のアプローチよりも使用する利点はないようです。 3つのアプローチのいずれかを使用してください。
In [49]: a = torch.Rand(2000, 3000)
In [50]: b = torch.Rand(2000)
In [51]: %timeit torch.sub(a, b[:, None])
2.4 ms ± 8.31 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [52]: %timeit a.sub(b[:, None])
2.4 ms ± 6.94 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [53]: %timeit a - b[:, None]
2.4 ms ± 12 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
形を変えるのはどうですか?
In [2]: a = torch.Rand(2,3)
...:
In [3]: a
Out[3]:
tensor([[ 0.2207, 0.1203, 0.7908],
[ 0.6702, 0.7557, 0.0708]])
In [4]: b = torch.Rand(2)
...:
In [5]: b
Out[5]: tensor([ 0.5953, 0.7925])
In [6]: a.add(b.reshape(-1,1))
Out[6]:
tensor([[ 0.8160, 0.7156, 1.3861],
[ 1.4627, 1.5481, 0.8632]])
ブロードキャストについても確認してください: https://pytorch.org/docs/stable/notes/broadcasting.html
.unsqueeze_()メソッドを試しましたか? .unsqueeze_()メソッドを使用して、テンソルに次元を追加できますインプレース。これははるかに速いと思います。引数として、展開する必要のある軸インデックスを渡す必要があります。
a = torch.Rand(2,3)
print(a)
"""Output
0.9323 0.9162 0.9505
0.9430 0.6184 0.3671
[torch.FloatTensor of size 2x3]"""
b = torch.Rand(2)
print(b)
"""Output
0.4723
0.9345
[torch.FloatTensor of size 2]"""
b.unsqueeze_(1)
"""Output
0.4723
0.9345
torch.FloatTensor of size 2x1]"""
a.add(b)
"""Output
1.4046 1.3885 1.4228
1.8775 1.5528 1.3016
[torch.FloatTensor of size 2x3]"""