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
Примеры
Результатом произведения массивов может быть число если первый и последний множитель это одномерные массивы:
>>> 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]])