Имеется произведение матриц a*b=c. Причем произведение матриц - это результат numpy.dot, а не поэлементное произведение. Известны матрицы a и c. Требуется найти матрицу b. Каким образом это можно сделать в python, не прибегая к решению системы уравнений с множеством неизвестных? Если просто делить numpy.matrix, то получается совсем не тот результат.
Вот пример:
import numpy as np
a = np.matrix([[ 1., 2.],[ 3., 4.]])
c = np.matrix([[ 2.],[ 1.]])
c/a
Out[201]:
matrix([[ 2. , 1. ],
[ 0.33333333, 0.25 ]])
Решил письменно обратную задачу, получил ответ:
([[-3. ],
[ 2.5]])
Проверяем:
b= np.matrix([[-3. ],[ 2.5]])
a*b
Out[207]:
matrix([[ 2.],
[ 1.]])
Если переводить в ndarray, то то же самое получается:
c.getA()/a.getA()
Out[213]:
array([[ 2. , 1. ],
[ 0.33333333, 0.25 ]])
Ответ
Воспользуйтесь обратной (inverse) матрицей
In [224]: b = np.linalg.inv(a) * c
In [225]: b
Out[225]:
matrix([[-3. ],
[ 2.5]])
Это будет работать для объектов типа numpy.matrix.
Если a и c - объекты типа numpy.ndarray, то нужно использовать dot product (как в ответе @MarianD):
In [8]: np.linalg.inv(a).dot(c)
Out[8]:
matrix([[-3. ],
[ 2.5]])
PS использование dot product (операции умножения матриц как это понимается в линейной алгебре) - является более универсальным решением, т.к. оно правильно работает как для объектов типа numpy.matrix так и для numpy.ndarray
In [10]: np.linalg.inv(a.getA()).dot(c.getA())
Out[10]:
array([[-3. ],
[ 2.5]])
Пояснение:
A * B = C | умножим обе части на A-1
умножение матриц операция некомутативная, т.е. A * B != B * A, поэтому чтобы получилась единичная матрица будем делать так:
A-1 * A * B = A-1 * C
=>
B = A-1 * C
UPDATE: во многих случаях гораздо выгоднее решить систему уравнений, по сравнению с нахождением обратной матрицы (спасибо @jfs за подсказку):
In [328]: b = np.linalg.solve(a, c)
In [329]: b
Out[329]:
matrix([[-3. ],
[ 2.5]])
Вот некоторые из преимуществ подхода решения системы линейных уравнений по сравнению с нахождением обратной матрицы:
решение СЛУ (системы линейных уравнений) дает более точные численные результаты по сравнению с методами, использующими перемножение матриц. Пример скалярного произведения возвращающего неточный результат
при использовании разреженных матриц (sparse matrices) есть методы, позволяющие найти решение и возвращающие также разреженные матрицы (если это возможно), что существенно экономит использование памяти. Обратная же матрица в общем случае не будет разреженной и может занимать на несколько порядков больше памяти. Например разреженная матрица размерности 1.000.000 x 1.000.000 у которой всего 1.000.000 ненулевых элементов (например единичная матрица или такая, у которой в каждой строке/столбце по одному ненулевому элементу) легко поместится в памяти и займет приблизительно: объем памяти необходимый для данного типа (np.int8, np.int16, np.int32, np.int64, np.float64, etc.) плюс небольшие накладные расходы (информация о позиции ненулевых элементов в разреженной матрице). Если преобразовать такую матрицу в обычную или найти обратную ей то в результате надо будет хранить в памяти уже 1.000.000 x 1.000.000 = 1.000.000.000.000 (один триллион элементов, или около 3.6 TiB для 32-битных элементов)
Комментариев нет:
Отправить комментарий