Добавить / вычесть между матрицей и вектором в pytorch - PullRequest
0 голосов
/ 29 июня 2018

Я хочу сделать + / - / * между матрицей и вектором в 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

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Вы пробовали метод .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]"""
0 голосов
/ 04 июля 2018

Чтобы использовать вещание, вам нужно повысить измерение тензора b до двух измерений, поскольку тензор a является 2D.

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]])

Другие операции (+, *) могут выполняться аналогично.


С точки зрения производительности, похоже, нет преимущества в использовании одного подхода по сравнению с другими. Просто используйте любой из трех подходов.

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)
0 голосов
/ 29 июня 2018

как насчет изменения формы?

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

...