Деление массива - перевод с MATLAB на Python - PullRequest
7 голосов
/ 16 июня 2009

У меня есть эта строка кода в MATLAB, написанная кем-то другим:

c=a.'/b

Мне нужно перевести его на Python. a, b и c - все массивы. Размеры, которые я сейчас использую для проверки кода:

a: 18x1,
b: 25x18,

, что дает мне с размерами 1x25.

Массивы не квадратные, но я бы не хотел, чтобы код не работал, если бы они были. Может кто-нибудь объяснить, что именно делает эта строка (математически) и как это сделать в Python? (т.е. эквивалент для встроенной функции mrdivide в MATLAB, если она существует в Python?)

Ответы [ 5 ]

7 голосов
/ 17 июня 2009

Линия

c = a.' / b

вычисляет решение уравнения c b = a T для c . У Numpy нет оператора, который делает это напрямую. Вместо этого вы должны решить b T c T = a для c T и транспонировать результат:

c = numpy.linalg.lstsq(b.T, a.T)[0].T
7 голосов
/ 16 июня 2009

Символ / - это матричный оператор деления справа в MATLAB, который вызывает функцию mrdivide. Из документации, матричное правое деление связано с матричным левым делением следующим образом:

B/A = (A'\B')'

Если A - квадратная матрица, B/A примерно равен B*inv(A) (хотя он вычисляется другим, более надежным способом). В противном случае x = B/A является решением в смысле наименьших квадратов недооцененной или переопределенной системы уравнений x*A = B. Более подробно об алгоритмах, используемых для решения системы уравнений, дано здесь . Обычно пакеты типа LAPACK или BLAS используются под капотом.

Пакет NumPy для Python содержит подпрограмму lstsq для вычисления решения методом наименьших квадратов для системы уравнений. Эта процедура, скорее всего, даст вам сравнимые результаты с использованием функции mrdivide в MATLAB, но вряд ли она будет точной . Любые различия в базовых алгоритмах, используемых каждой функцией, вероятно, приведут к ответам, которые немного отличаются друг от друга (то есть один может возвращать значение 1,0, тогда как другой может возвращать значение 0,999). Относительный размер этой ошибки может оказаться больше, в значительной степени зависящей от конкретной системы уравнений, которую вы решаете.

Чтобы использовать lstsq, возможно, вам придется немного скорректировать проблему. Похоже, что вы хотите решить уравнение вида cB = a , где B - 25 на 18, a - 1 на 18 и c - 1 на 25. Применение транспонирования к обеим сторонам дает уравнение B T c T = a T , которое более стандартная форма (то есть Ax = b ). Аргументы для lstsq должны быть (в этом порядке) B T (массив 18 на 25) и a T (массив из 18 элементов). lstsq должен возвращать массив из 25 элементов ( c T ).

Примечание: хотя NumPy не делает различий между массивом 1 на N или N на 1, MATLAB, безусловно, делает, и будет кричать на вас, если вы не используете правильный.

5 голосов
/ 16 июня 2009

В Matlab, A.' означает транспонирование матрицы A. Математически то, что достигается в коде, это A T / B.


Как реализовать матричное деление в Python (или любом другом языке) (Примечание: давайте рассмотрим простое деление в форме A/B; для вашего примера вам потребуется Сначала A T , а затем A T / B, и довольно просто выполнить операцию транспонирования в Python | left-as-an-упражнение:) |)

У вас есть матричное уравнение C * B = A (Вы хотите найти C как A / B)

ПРАВОЕ РАЗДЕЛЕНИЕ (/) выглядит следующим образом:

С * * тысячи двадцать-дв (В * B T * тысяча двадцать пять) = А * * В тысяче двадцать-шести T

Затем вы изолируете C инвертированием (B * B T )

т.е.,

C = A * B T * (B * B T ) '----- [1]

Поэтому, чтобы реализовать матричное деление в Python (или любом другом языке), получите следующие три метода.

  • Матричное умножение
  • Матрица транспонирования
  • Матрица обратная

Затем примените их итеративно для достижения деления, как в [1].

Только вам нужно сделать A T / B, поэтому ваша последняя операция после реализации трех основных методов должна быть:

* * Тысяча шестьдесят две А T * 1 064 ** B T * (В * 1 069 * B T * тысяча семьдесят один) '* * тысяча семьдесят-две Примечание: не забудьте основные правила приоритета операторов:)
1 голос
/ 07 марта 2018

Вы также можете приблизиться к этому, используя псевдообратное значение B, а затем умножить полученный результат на A. Попробуйте использовать numpy.linalg.pinv, затем объедините это с умножением матрицы через numpy.dot:

c = numpy.dot(a, numpy.linalg.pinv(b))
1 голос
/ 16 июня 2009

[отредактировано] Как указывал Сувеш, я был совершенно неправ. тем не менее, numpy все еще может легко выполнить процедуру, которую он дает в своем посте:

A = numpy.matrix(numpy.random.random((18, 1))) # as noted by others, your dimensions are off
B = numpy.matrix(numpy.random.random((25, 18)))
C = A.T * B.T * (B * B.T).I
...