2016-10-15 1 views
1

У меня есть другой вопрос, связанный с моей последней проблемой (Python tensor product). Там я нашел ошибку в своих расчетах. С np.tensordot я вычисляю следующее уравнение: enter image description here < ..> должен отображать среднее значение. В питона коде это выглядит следующим образом (КИД вектор и вновь тензор):Среднее тензорное произведение

q1 = numpy.tensordot(re, ewp, axes=(1, 0)) 
q2 = numpy.tensordot(q1, ewp, axes=(1, 0)) 
serc = q2 ** 2 

или

serc = numpy.einsum('im, m -> i', numpy.einsum('ilm, l -> im', 
numpy.einsum('iklm, k -> ilm', numpy.einsum('ijklm, j -> iklm', 
numpy.einsum('ijk, ilm -> ijklm', re, re), ewp), ewp), ewp), ewp) 

Теперь в обоих питона кодов я пренебрегаем, что все возможности умножаются. Но, конечно, w_j и w_k не являются независимыми для j=k. В случае, что только j и k являются одинаковыми, получаем < w_j*w_j*w_l*w_m> = <w_j>*<w_l>*<w_m>. Для j=k=l мы получаем: < w_j*w_j*w_j*w_m> = <w_j>*<w_m>. Для j=k=l=m: < w_j*w_j*w_j*w_j> = <w_j>. Только если все переменные различны, независимость верна, и мы получаем: < w_i*w_j*w_l*w_m> = <w_i>*<w_j>*<w_l>*<w_m>. Теперь это то, что делает код для всех возможностей. Надеюсь, это делает мою проблему понятной. Теперь мой вопрос: как я могу представить это в своем коде?

Редактировать: Идея, которую я имею, - это сначала создать 4dim. тензор, который представляет <w_j w_k w_l w_m>:

wtensor = numpy.einsum('jkl, m -> jklm', numpy.einsum('jk, l -> jkl', 
numpy.einsum('j, k -> jk', ewp, ewp), ewp), ewp) 

Тогда мне нужно изменить значение, которые не являются Независимыми. Я предполагаю, что они должны быть по диагонали? Но я действительно не так много знаю о тензорном исчислении, поэтому в этот момент я борюсь. После манипуляций с тензором ш я хотел бы получить результат, выполнив:

serc = numpy.einsum('ijklm, jklm -> i', numpy.einsum('ijk, ilm -> 
ijklm', re, re), wtensor) 

Edit2: В другом посте я спросил, как именно я могу манипулировать 4dim так, что он подходит здесь. Divakar было действительно красивое решение, которое можно увидеть здесь: Fill a multidimensional array efficiently that have many if else statements

from itertools import product 

n_dims = 4 # Number of dims 
# Create 2D array of all possible combinations of X's as rows 
idx = np.sort(np.array(list(product(np.arange(gn), 
repeat=n_dims))),axis=1) 
# Get all X's indexed values from ewp array 
vals = ewp[idx] 
# Set the duplicates along each row as 1s. With the np.prod coming up 
next, 
#these 1s would not affect the result, which is the expected pattern 
here. 
vals[:,1:][idx[:,1:] == idx[:,:-1]] = 1 
# Perform product along each row and reshape into multi-dim array 
out = vals.prod(1).reshape([gn]*n_dims) 

массив, который я получаю здесь wtensor, которые теперь я могу использовать в приведенном выше коде:

serc = numpy.einsum('ijklm, jklm -> i', numpy.einsum('ijk, ilm -> 
ijklm', re, re), wtensor) 

Это дает мне, наконец, результат, который я хотел и в основном отвечал на вопрос. Хотя есть одна проблема. Длина EWP, которая затем также определяет размер тензоров, не должна быть больше, чем 6. В противном случае код будет использовать много памяти. Мое намерение заключалось в том, чтобы использовать его до размера 8, так что, к сожалению, теперь это моя следующая проблема.

+0

Do: 'mewp = КИД/LEN (КИД)', а затем использовать 'mewp' вместо' EWP 'с тем же кодом? Или просто используйте метод на конечном выходе: 'serc/(len (ewp) ** 4)'? – Divakar

+0

@ Дивакар: Извините, но я не вижу смысла? Моя проблема заключается в том, что только разные значения независимы друг от друга, и только тогда ' = ' is true. – HighwayJohn

ответ

1

Ну вы можете сделать это эффективно с комбинацией np.tensordot и np.einsum, как так -

serc = np.einsum('ilm,ilm->i',re,np.tensordot(re,wtensor,axes=[(1,2),(0,1)])) 
+0

Хорошо, это действительно ускоряет работу :) Но один вопрос? Как оси команды tenordot связаны с np.ininsum? Я прочитал руководство по тендердоту, но я все еще немного озадачен тем, как я должен представить себе топоры и как решить, какие из них правильные. – HighwayJohn

+0

@HighwayJohn Ну, я исходил из уравнения, не глядя на решение 'einsum'.Итак, позвольте мне попытаться дать вам этот угол: первая группа редукции находится между «R (i, j, k)» и «w (j, k, l, m)», и мы выполняем два уровня sum- сокращений. Первое сокращение суммы использует вторую ось R с первой из «w», поэтому: axes = [(1, ...), (0, ....)]. Точно так же между третьей осью R со второй из 'w', поэтому: axes = [(..., 2), (...., 1)]. Надеюсь это поможет! – Divakar

+0

Ну ладно, понял! Благодаря :) – HighwayJohn

Смежные вопросы