numpy.einsum
-
numpy.einsum(subscripts, *operands, out=None, dtype=None, order='K', casting='safe', optimize=False)[source] -
Вычисляет соглашение об индексе Эйнштейна для операндов.
Используя соглашение об индексе Эйнштейна, многие распространённые операции с многомерными массивами могут быть представлены простым способом. Эта функция предоставляет способ вычисления таких суммирований. Лучший способ понять эту функцию – это попробовать примеры ниже, которые показывают, как многие распространённые функции NumPy могут быть реализованы как вызовы к
einsum.Параметры: подстроки : str
Указывает индексы для суммирования.
операнды : список array_like
Это массивы для операции.
out : {ndarray, None}, необязательно
Если предоставлено, вычисление выполняется в этом массиве.
dtype : {тип данных, None}, необязательно
Если предоставлено, вычисление принудительно выполняется с указанным типом данных. Обратите внимание, что вам может потребоваться также указать более либеральный параметр
castingдля разрешения преобразований. По умолчанию значение None.order : {‘C’, ‘F’, ‘A’, ‘K’}, необязательно
Управляет расположением памяти результата. ‘C’ означает, что он должен быть непрерывным в стиле C. ‘F’ означает, что он должен быть непрерывным в стиле Fortran, ‘A’ означает, что он должен быть ‘F’, если все входные данные имеют ‘F’, иначе ‘C’. ‘K’ означает, что он должен быть максимально похожим на расположение входных данных, включая произвольно переставленные оси. По умолчанию значение ‘K’.
casting : {‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, необязательно
Управляет тем, какие преобразования типов данных могут произойти. Не рекомендуется устанавливать это значение в ‘unsafe’, так как это может негативно повлиять на накопления.
- ‘no’ означает, что типы данных вообще не должны преобразовываться.
- ‘equiv’ означает, что разрешены только изменения порядка байтов.
- ‘safe’ означает, что разрешены только преобразования, которые могут сохранить значения.
- ‘same_kind’ означает, что разрешены только безопасные преобразования или преобразования внутри одного типа, например, float64 в float32.
- ‘unsafe’ означает, что любые преобразования данных могут быть выполнены.
По умолчанию значение ‘safe’.
optimize : {False, True, ‘greedy’, ‘optimal’}, необязательно
Управляет, будет ли происходить оптимизация промежуточных операций. Оптимизация не будет происходить, если значение False, а True по умолчанию соответствует алгоритму ‘greedy’. Также принимает явный список сокращений от функции
np.einsum_path. См.np.einsum_pathдля получения более подробной информации. По умолчанию значение False.Возвращаемое значение: результат : ndarray
Вычисление на основе соглашения об индексе Эйнштейна.
См. также
Примечания
Введено в версии 1.6.0.
Строка подстрок представляет собой список подстрочных меток, разделённых запятыми, где каждая метка относится к размерности соответствующего операнда. Повторные метки подстрок в одном операнде принимают диагональ. Например,
np.einsum('ii', a)эквивалентноnp.trace(a).Всякий раз, когда метка повторяется, она суммируется, поэтому
np.einsum('i,i', a, b)эквивалентноnp.inner(a,b). Если метка встречается только один раз, она не суммируется, поэтомуnp.einsum('i', a)создаёт представлениеaбез изменений.Порядок меток в результате по умолчанию алфавитный. Это означает, что
np.einsum('ij', a)не влияет на 2D-массив, аnp.einsum('ji', a)берёт его транспонирование.Результат можно контролировать, указав метки выходных подстрок. Это определяет порядок меток и позволяет запретить или принудительно выполнить суммирование по мере необходимости. Вызов
np.einsum('i->', a)похож наnp.sum(a, axis=-1), аnp.einsum('ii->i', a)похож наnp.diag(a). Разница заключается в том, чтоeinsumпо умолчанию не допускает расширения.Для включения и управления расширением используйте многоточие. По умолчанию NumPy-стиль расширения осуществляется путём добавления многоточия слева от каждого элемента, как в
np.einsum('...ii->...i', a). Чтобы получить след по первым и последним осям, можно использоватьnp.einsum('i...i', a), а для выполнения матрично-матричного произведения с левыми индексами вместо правых можно использоватьnp.einsum('ij...,jk...->ik...', a, b).Когда имеется только один операнд, оси не суммируются, и параметр output не предоставлен, возвращается представление операнда, а не новый массив. Таким образом, получение диагонали как
np.einsum('ii->i', a)приводит к представлению.Альтернативный способ предоставления подстрок и операндов – это
einsum(op0, sublist0, op1, sublist1, ..., [sublistout]). Примеры ниже имеют соответствующие вызовыeinsumс методами с двумя параметрами.Введено в версии 1.10.0.
Представления, возвращаемые функцией einsum, теперь могут быть изменяемыми, если входной массив изменяем. Например,
np.einsum('ijk...->kji...', a)теперь будет иметь тот же эффект, что иnp.swapaxes(a, 0, 2), иnp.einsum('ii->i', a)вернёт изменяемое представление диагонали 2D-массива.Введено в версии 1.12.0.
Добавлен аргумент
optimize, который оптимизирует порядок сокращения выражения einsum. Для сокращения с тремя или более операндами это может значительно повысить вычислительную эффективность за счёт увеличения занимаемой памяти во время вычислений.См.
np.einsum_pathдля получения более подробной информации.Примеры
>>> a = np.arange(25).reshape(5,5) >>> b = np.arange(5) >>> c = np.arange(6).reshape(2,3)
>>> np.einsum('ii', a) 60 >>> np.einsum(a, [0,0]) 60 >>> np.trace(a) 60>>> np.einsum('ii->i', a) array([ 0, 6, 12, 18, 24]) >>> np.einsum(a, [0,0], [0]) array([ 0, 6, 12, 18, 24]) >>> np.diag(a) array([ 0, 6, 12, 18, 24])>>> np.einsum('ij,j', a, b) array([ 30, 80, 130, 180, 230]) >>> np.einsum(a, [0,1], b, [1]) array([ 30, 80, 130, 180, 230]) >>> np.dot(a, b) array([ 30, 80, 130, 180, 230]) >>> np.einsum('...j,j', a, b) array([ 30, 80, 130, 180, 230])>>> np.einsum('ji', c) array([[0, 3], [1, 4], [2, 5]]) >>> np.einsum(c, [1,0]) array([[0, 3], [1, 4], [2, 5]]) >>> c.T array([[0, 3], [1, 4], [2, 5]])>>> np.einsum('..., ...', 3, c) array([[ 0, 3, 6], [ 9, 12, 15]]) >>> np.einsum(',ij', 3, C) array([[ 0, 3, 6], [ 9, 12, 15]]) >>> np.einsum(3, [Ellipsis], c, [Ellipsis]) array([[ 0, 3, 6], [ 9, 12, 15]]) >>> np.multiply(3, c) array([[ 0, 3, 6], [ 9, 12, 15]])>>> np.einsum('i,i', b, b) 30 >>> np.einsum(b, [0], b, [0]) 30 >>> np.inner(b,b) 30>>> np.einsum('i,j', np.arange(2)+1, b) array([[0, 1, 2, 3, 4], [0, 2, 4, 6, 8]]) >>> np.einsum(np.arange(2)+1, [0], b, [1]) array([[0, 1, 2, 3, 4], [0, 2, 4, 6, 8]]) >>> np.outer(np.arange(2)+1, b) array([[0, 1, 2, 3, 4], [0, 2, 4, 6, 8]])>>> np.einsum('i...->...', a) array([50, 55, 60, 65, 70]) >>> np.einsum(a, [0,Ellipsis], [Ellipsis]) array([50, 55, 60, 65, 70]) >>> np.sum(a, axis=0) array([50, 55, 60, 65, 70])>>> a = np.arange(60.).reshape(3,4,5) >>> b = np.arange(24.).reshape(4,3,2) >>> np.einsum('ijk,jil->kl', a, b) array([[ 4400., 4730.], [ 4532., 4874.], [ 4664., 5018.], [ 4796., 5162.], [ 4928., 5306.]]) >>> np.einsum(a, [0,1,2], b, [1,0,3], [2,3]) array([[ 4400., 4730.], [ 4532., 4874.], [ 4664., 5018.], [ 4796., 5162.], [ 4928., 5306.]]) >>> np.tensordot(a,b, axes=([1,0],[0,1])) array([[ 4400., 4730.], [ 4532., 4874.], [ 4664., 5018.], [ 4796., 5162.], [ 4928., 5306.]])>>> 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]])>>> # since version 1.10.0 >>> a = np.zeros((3, 3)) >>> np.einsum('ii->i', a)[:] = 1 >>> a array([[ 1., 0., 0.], [ 0., 1., 0.], [ 0., 0., 1.]])
© 2005–2019 NumPy Developers
Licensed under the 3-clause BSD License.
https://docs.scipy.org/doc/numpy-1.14.5/reference/generated/numpy.einsum.html