numpy.linalg.multi_dot

numpy.linalg.multi_dot(arrays)

Функция linalg.multi_dot() вычисляет скалярное произведение двух и более массивов с автоматической оптимизацией расстановки множителей (точнее, расстановки скобок).

Все массивы, кроме первого и последнего должны быть двумерными. Если первый массив является одномерным, то он обрабатывается как вектор-строка, а если одномерный вектор находится в конце, то он обрабатывается как вектор столбец.

Не смотря на то, что произведение матриц обладает ассоциативным свойством, т.е. (AB)C = A(BC), скорость этого умножения зависит от порядка множителей (скобок).

Параметры:
arrays - последовательность массивов NumPy или подобных массиву объектов.
Только первый и последний массив могут быть одномерными, остальные должны быть двумерными.
Возвращает:
результат - массив NumPy или число
Скалярное произведение массивов. Если первый и последний массивы это векторы, то результатом будет число.

Замечание

Количество операций, необходимое для умножения двух матриц A и B, можно оценить по следующему правилу:

n(AB) = A.shape[0]*A.shape[1]*B.shape[1]

Предположим, у нас есть три массива A, B и C с формами A.shape = (4, 200), B.shape = (200, 100) и C.shape = (100, 10), тогда можно рассчитать количество операций необходимое для произведений (AB)C и A(BC):

n((AB)C) = 4*200*100 + 4*100*10 = 80000 + 4000 = 84000
n(A(BC)) = 200*100*10 + 4*200*10 = 200000 + 8000 = 208000
Смотрите так же:
dot, matmul, linalg.matrix_power

Примеры

Результатом произведения массивов может быть число если первый и последний множитель это одномерные массивы:

>>> import numpy as np
>>> 
>>> a = [1, 2]
>>> b = [3, 4]
>>> 
>>> np.linalg.multi_dot([a, b])
11
>>> 
>>> c = [[2, 2], [3, 3]]
>>> 
>>> np.linalg.multi_dot([a, c, b])
56

Все матрицы в произведении должны иметь совместимую форму, т.е. если первый массив имеет форму (i, i, j), то второй должен иметь форму (j, k):

>>> A = np.arange(4*100).reshape(4, 100)
>>> B = np.arange(100*20).reshape(100, 20)
>>> C = np.arange(20*7).reshape(20, 7)
>>> D = np.arange(7*15).reshape(7, 15)
>>> E = np.arange(15*2).reshape(15, 2)
>>> F = np.arange(2*4).reshape(2, 4)
>>> 
>>> np.linalg.multi_dot([A, B, C, D, E, F])
array([[ -457760064,  1009652560, -1817902112,  -350489488],
       [   -2629440,  -500265008,  -997900576, -1495536144],
       [  452501184, -2010182576,  -177899040,  1654384496],
       [  907631808,   774867152,   642102496,   509337840]])

Мы можем воспользоваться эквивалентными командами, но если вы не знаете наилучшей последовательности выполнения умножения (наилучшей расстановки скобок в произведении), то эти команды окажутся медленнее:

>>> np.dot(np.dot(np.dot(np.dot(np.dot(A, B), C), D), E), F)
array([[ -457760064,  1009652560, -1817902112,  -350489488],
       [   -2629440,  -500265008,  -997900576, -1495536144],
       [  452501184, -2010182576,  -177899040,  1654384496],
       [  907631808,   774867152,   642102496,   509337840]])
>>> 
>>> A.dot(B).dot(C).dot(D).dot(E).dot(F)
array([[ -457760064,  1009652560, -1817902112,  -350489488],
       [   -2629440,  -500265008,  -997900576, -1495536144],
       [  452501184, -2010182576,  -177899040,  1654384496],
       [  907631808,   774867152,   642102496,   509337840]])