Расчет внешнего продукта по numpy einsum - PullRequest
3 голосов
/ 06 мая 2020

Я пытаюсь погрузиться в нотацию einsum . Этот вопрос и мне очень помогли.

Но теперь я не могу asp использовать механизм einsum при вычислении внешнего продукта:

x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
np.einsum('i,j->ij', x, y)

array([[ 4.,  5.,  6.],
        [ 8., 10., 12.],
        [12., 15., 18.]])

Этот ответ дает следующее правило:

Повторяя метку i в обоих входных массивах, мы сообщаем einsum, что эти две оси должны быть умножены вместе.

Я не могу понять, как произошло это умножение, если бы мы не указали повторяющуюся метку оси в np.einsum('i,j->ij', x, y)?

Не могли бы вы назвать шаги, которые np.einsum предпринял в этом пример?

Или, может быть, более широкий вопрос, как einsum работает, когда не указаны соответствующие метки осей?

Ответы [ 2 ]

4 голосов
/ 06 мая 2020

В выводе np.einsum('i,j->ij', x, y) элемент [i,j] - это просто произведение элемента i в x и элемента j в y. Другими словами, np.einsum('i,j->ij', x, y)[i,j] = x[i]*y[j].

Сравните его с np.einsum('i,i->i', x, y), где элемент i вывода равен x[i]*y[i]:

np.einsum('i,i->i', x, y)

[ 4 10 18]

И если метка на входе отсутствует в output, это означает, что на выходе вычислена сумма по оси отсутствующих меток. Вот простой пример:

np.einsum('i,j->i', x, y)

[15 30 45]

Здесь метка j на входе отсутствует на выходе, что эквивалентно суммированию по axis=1 (соответствует метке j):

np.sum(np.einsum('i,j->ij', x, y), axis=1)

[15 30 45]
1 голос
/ 22 мая 2020

В общем, вы можете сначала понять эйнсум, зная точно размер или форму входных и выходных данных, которые ожидаются и вычисляются нотации эйнсума.

Чтобы облегчить объяснение, скажем, x.shape = [3], y.shape = [4]

x = np.array([1, 2, 3])
y = np.array([4, 5, 6, 7])
np.einsum('i,j->ij', x, y)
array([[ 4,  5,  6,  7],
       [ 8, 10, 12, 14],
       [12, 15, 18, 21]])

Размерность

Для перекрестного произведения np.einsum('i,j->ij', x, y) 1-й ввод - это одиночный символ i . Вы можете подумать, что количество символов - это размер этого ввода. Итак, здесь первый вход x имеет только одно измерение. То же самое для j, второй вход - это всего лишь один символ j, поэтому он имеет только одно измерение. Наконец, вывод ij имеет 2 символа, поэтому он имеет 2 измерения, и это измерение должно быть [3,4], потому что количество элементов в первом вводе равно i, которое имеет 3 элемента, а количество элементов во втором ввод - j, который имеет 4 элемента.

Каждый элемент в массиве результатов

Затем вы фокусируетесь на обозначении результата ij. Теперь мы знаем, что это 2D-массив или матрица 3 на 4, ij говорит о том, как ОДИН элемент вычисляется в местоположении i строки j столбца. Элемент должен быть рассчитан из произведения входов. Здесь означает, что конкретный элемент в местоположении [i, j] является произведением ввода a его местоположения i и ввода b его местоположения j

Итак, элемент в местоположении [0,0] рассчитывается путем взятия 1-го входного местоположения 0, которое является вашим x [0] = 1, и второго входного местоположения [0], которое составляет * 1038. * y [0] = 4, результат этого ОДНОГО элемента [0,0] = 1 * 4 = 4.

То же самое, элемент в местоположении результата [2,3] принимает x [2] и y [3] = 3 * 7 = 21

Короче говоря, подумайте, что ij из i,j->ij будет i раз j этого ОДНОГО элемента результата двух измерений (из-за двух символов). Фактический элемент, который вы берете из ввода i и ввода j, соответствует индексу местоположения ij

Вы можете найти транспонирование внешнего продукта в одной строке

Это означает, что транспонирование внешнего произведения просто i,j->ji. Здесь у нас есть два символа в результате, поэтому это 2D-массив. Номер элемента 1-го измерения должен быть размером j, потому что он идет первым. и это 2-й вход, который имеет 4 элемента. То же logi c для 2-го измерения, поэтому мы знаем, что результирующий массив имеет форму (4,3).

Тогда ОДИН элемент в местоположении [3,2] результирующего 2D-массива равен ji, что означает ввод j умножить на ввод i, поэтому это элемент 3 из j = y [3] = 7, а элемент 2 из i = x [2] = 3. Результат: 7 * 3 = 21

Следовательно, результат

np.einsum('i,j->ji', x, y)
array([[ 4,  8, 12],
       [ 5, 10, 15],
       [ 6, 12, 18],
       [ 7, 14, 21]])
...