Страницы

Поиск по вопросам

среда, 31 октября 2018 г.

Найти матрицу-множитель в произведении матриц при известном результате

Имеется произведение матриц 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-битных элементов)

Комментариев нет:

Отправить комментарий