У меня есть массив формы N, j, j
и другой формы M, j, j
. Я хочу рассчитать их тензорную точку, чтобы в конечном итоге получить матрицу, в которой запись i,j
равна np.tensordot(arr1[i, :, :], arr2[j, :, :])
Я пробовал зацикливаться, но это смехотворно медленно, я читал о np.einsum
, но, к сожалению, не могу понять, сколько бы я ни читал.
Моя последняя попытка;
np.einsum('ilk,ium->lu', arr1, arr2)
Но я продолжаю получать ошибки, что формы не могут быть переданы. Буду признателен за любые указатели, спасибо!
пример кода:
arr1 = np.zeros((5, 2, 2))
arr2 = np.zeros((4, 2, 2))
arr2[1,:,:][1,1] = 2
arr1[1,:,:][1,1] = 3
np.tensordot(arr1[1,:,:], arr2[1,:,:])
в этом случае тензорная точка даст мне 6. Это то, что меня интересует, для каждого i,j
.
Поскольку N и M разные, первые индексы должны быть разными. `ilk,jkm->ijlm', с суммированием 'dot' по общему измерению 'k'. Поскольку последние 2 измерения одинаковы, порядок индексов может быть другим, но я предполагаю, что вы хотите обычно "последний из первого, 2-й до последнего из второго" "точка". Обратите внимание, что я сохраняю оба "i" и 'Дж'
@paisanco Отредактировано с игрушечным примером
tensordot
с 2d-массивами (а не значениями осей) является обычным dot
.
@hpaulj Спасибо за ваш пример, я изменил его на ilk, jkm-> ij, так как хочу, чтобы на выходе была 2d-матрица. Теперь я получаю предупреждение iterator is too big
, я сделал что-то не так?
Хорошо, я ошибаюсь, что tensordot
эквивалентно «kl, kl», суммируя оба последних 2 измерения. 'ikl,jkl->ij' (по умолчанию ось=2, двойное сжатие).
In [41]: x=np.arange(2*3*3).reshape(2,3,3)
In [42]: y=np.arange(4*3*3).reshape(4,3,3)
двойное сокращение на последних 2 дим.:
In [43]: np.einsum('ikl,jkl->ij',x,y)
Out[43]:
array([[ 204, 528, 852, 1176],
[ 528, 1581, 2634, 3687]])
проверить одно значение:
In [44]: np.tensordot(x[0],y[0])
Out[44]: array(204)
Та же точка (и дополнительное измерение)
In [47]: np.dot(x.reshape(-1,9),y.reshape(-1,9,1))
Out[47]:
array([[[ 204],
[ 528],
[ 852],
[1176]],
[[ 528],
[1581],
[2634],
[3687]]])
np.tensordot
с различными параметрами оси может быть немного сложно использовать. Так или иначе он изменяет форму и переставляет массивы, чтобы он мог вызывать np.dot
. Затем он может сделать некоторые дальнейшие манипуляции.
Или используя широковещательную и многоосевую сумму:
In [48]: (x[:,None,:,:]*y[None,:,:,:]).sum(axis=(2,3))
Out[48]:
array([[ 204, 528, 852, 1176],
[ 528, 1581, 2634, 3687]])
и тензорд без цикла:
In [50]: np.tensordot(x,y,axes=((1,2),(1,2)))
Out[50]:
array([[ 204, 528, 852, 1176],
[ 528, 1581, 2634, 3687]])
Большое спасибо! Насколько я понимаю, 'ikl,jkl->ij
перебирает первую ось и умножает две другие?
Я добавил эквивалент умножения и суммы. и полный тензордот.
Не могли бы вы опубликовать пример кода, демонстрирующий проблему?