Перевод np.einsum () в MATLAB - PullRequest
       104

Перевод np.einsum () в MATLAB

0 голосов
/ 20 февраля 2020

У меня проблемы с пониманием документации np.einsum(). Как интерпретируется subscripts?

Я пытаюсь написать np.einsum('a...c,b...c', Y, conj(Y)), где Y - это матрица формы C, F, T для оригинала python. Кроме того, из-за предыдущих различий в реализации мой MATLAB Y имеет размер [F, T, C].

Что индексирует 'a...c,b...c' в каждом компоненте? Я в замешательстве.

Как мне написать те же инструкции в MATLAB?

1 Ответ

5 голосов
/ 20 февраля 2020

Цитирование со страницы документации einsum:

Для включения и контроля трансляции используйте многоточие. Трансляция в стиле NumPy по умолчанию выполняется путем добавления многоточия слева от каждого термина, например np.einsum('...ii->...i', a). Чтобы провести трассировку вдоль первой и последней осей, вы можете сделать np.einsum('i...i', a), или сделать матрично-матричный продукт с крайними левыми индексами вместо правого, можно сделать np.einsum('ij...,jk...->ik...', a, b).

Позже приведен пример:

>>> a = np.arange(25).reshape(5,5)
>>> np.einsum('...j->...', a)
array([ 10,  35,  60,  85, 110])

Эквивалентный MATLAB-код для этого примера:

>> a = reshape(0:24, [5,5]).';
>> sum(a,2).'
ans =
    10    35    60    85   110

Несколько замечаний:

  1. Оператор с многоточием (...) следует понимать не как «диапазон», а как «все, что должно быть там».
  2. " Broadcasting " относится к автоматической c репликации массива по соответствующему измерению для определения математической операции. Эта функция существует в MATLAB начиная с R2016b (так называемое «неявное расширение»).
  3. Вы можете заметить несколько операций транспонирования (.') в эквиваленте MATLAB. Это связано с тем, что массивы numpy являются основными по строкам, а массивы MATLAB - основными по столбцам. Практически, в то время как базовые данные имеют тот же последовательный порядок, массив numpy выглядит транспонированным по сравнению с MATLAB. Транспонирование было сделано так, чтобы массивы выглядели одинаково на промежуточных этапах.

Другой пример из этих документов:

>>> a = np.arange(6).reshape((3,2))
>>> b = np.arange(12).reshape((4,3))
>>> np.einsum('ki,jk->ij', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('ki,...k->i...', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('k...,jk', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])

, который можно записать в MATLAB следующим образом :

A = reshape(0:5, [2 3]).';
B = reshape(0:11, [3 4]).';

A.' * B.'
permute(sum( permute(A, [3 1 2]) .* B,2), [3 1 2])
shiftdim(sum( shiftdim(A, -1) .* B, 2), 2)

Несколько замечаний:

  1. При переходе от np.einsum('ki,jk->ij', a, b) к np.einsum('ki,...k->i...', a, b) видно, что j -ое измерение заменено на .... Тот факт, что оба эти примера содержат ->, означает, что он находится в явном режиме .
  2. При переходе от np.einsum('ki,jk->ij', a, b) к np.einsum('k...,jk', a, b) вы можете видеть, что теперь i -ое измерение заменено на .... Пропуск ->...j просто демонстрирует неявный режим (где выходные размеры упорядочены в алфавитном порядке).
...