Как умножать матрицы с помощью алгебры в numpy

#python #numpy #matrix #linear-algebra

Вопрос:

В моем коде есть два объекта матрицы numpy, один из которых представляет собой матрицу чисел, а другой-матрицу переменных, которым я не хочу присваивать значения. Результат, которого я хочу, таков:

 [[ 1.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.],
 [ 0.,  1.,  0.,  0.,  0.,  1., -1.,  1., -1.],
 [ 0.,  0.,  1.,  0.,  0.,  1.,  0.,  0.,  0.],
 [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1., -1.],
 [ 0.,  0.,  0.,  0.,  1., -1.,  0.,  0.,  1.]]

multiplied by the column vector

[['i8'],
 ['i4'],
 ['i9'],
 ['i5'],
 ['i2'],
 ['i1'],
 ['i7'],
 ['i6'],
 ['i3']]

Gives:
[[         i8 i1],
 [i4 i1-i7 i6-i3],
 [         i9 i1],
 [      i5 i6-i3],
 [      i2-i1 i3]]
 

Я просмотрел раздел линейной алгебры numpy и не смог найти ничего, что работало бы. Я пробовал использовать np.dot(), np.multiply(), пытался преобразовать их в массивы, и я продолжаю получать ошибку типа соответствия подписи (я предполагаю, что это связано с тем, что вторая матрица состоит из строк). Как я могу умножить их, чтобы получить свои уравнения?

  • Я знаю, что использовать объекты матрицы numpy не рекомендуется, причина, по которой они реализованы здесь, заключается в том, что пакет python, который я использую для получения этих матриц, возвращает их таким образом.

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

1. Что вы подразумеваете под «Я знаю, что использование объектов матрицы numpy не рекомендуется»? Это вообще не рекомендуется или в некоторых контекстах, подобных вашему?

2. переменные, которым я не хочу присваивать значения -numpy этого не делает.

3. @j1-ли Объекты матрицы Numpy вообще не рекомендуются, единственная причина, по которой они все еще существуют, — это взаимодействие с материалами scipy, общее намерение состоит в том, чтобы в конечном итоге удалить класс numpy.matrix. более подробная информация содержится в документах numpy

4. Использование np.matrix не имеет значения. Проблема здесь заключается в умножении чисел и строк. 1.0*'l1'

5. @CharlesKelly О, я понимаю, я даже не знал np.matrix , что существует. Я думал, ты имеешь в виду np.array . Спасибо, что разъяснили это. Сегодня я узнал кое-что новое 🙂

Ответ №1:

С массивами типов dtype объектов такие функции, как np.dot попытка делегировать действие методам умножения и добавления элементов.

Таким образом, я определяю класс:

 In [467]: class Y:
     ...:     def __init__(self,astr):
     ...:         self.value = astr
     ...:     def __repr__(self):
     ...:         return self.value
     ...:     def __mul__(self, other):
     ...:         if other==0:
     ...:             return Y('')
     ...:         elif other==1:
     ...:             return self
     ...:         elif other==-1:
     ...:             return Y('-' self.value)
     ...:         else:
     ...:             return Y(str(other) self.value)
     ...:     def __add__(self, other):
     ...:         if self.value=='':
     ...:             return other
     ...:         elif other.value=='':
     ...:             return self
     ...:         else:
     ...:             return Y(self.value ' ' other.value)
     ...: 
 

и создайте массив объектов:

 In [468]: y = np.array([Y('i1'),Y('i8'),Y('j3')])
In [469]: y
Out[469]: array([i1, i8, j3], dtype=object)
 

с учетом этого dot выглядит разумно.

 In [470]: np.dot(y,[-1,0,1])
Out[470]: -i1 j3
In [471]: type(_)
Out[471]: __main__.Y
 

Y возможно, потребуется некоторая настройка, но это дает основную идею.

Но имейте в виду, что все это умножение и сложение происходит в Python. Ничего из этого не компилируется, так что в его скорости нет ничего особенного.


И с вашими массивами, немного подправленными:

 In [474]: In [437]: x = np.array([[ 1.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.],
     ...:      ...:  [ 0.,  1.,  0.,  0.,  0.,  1., -1.,  1., -1.],
     ...:      ...:  [ 0.,  0.,  1.,  0.,  0.,  1.,  0.,  0.,  0.],
     ...:      ...:  [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1., -1.],
     ...:      ...:  [ 0.,  0.,  0.,  0.,  1., -1.,  0.,  0.,  1.]], dtype=int)
     ...:      ...:
     ...:      ...: #multiplied by the column vector
     ...:      ...:
     ...:      ...: y = np.array([['i8'],
     ...:      ...:  ['i4'],
     ...:      ...:  ['i9'],
     ...:      ...:  ['i5'],
     ...:      ...:  ['i2'],
     ...:      ...:  ['i1'],
     ...:      ...:  ['i7'],
     ...:      ...:  ['i6'],
     ...:      ...:  ['i3']])
     ...: 
In [475]: x
Out[475]: 
array([[ 1,  0,  0,  0,  0,  1,  0,  0,  0],
       [ 0,  1,  0,  0,  0,  1, -1,  1, -1],
       [ 0,  0,  1,  0,  0,  1,  0,  0,  0],
       [ 0,  0,  0,  1,  0,  0,  0,  1, -1],
       [ 0,  0,  0,  0,  1, -1,  0,  0,  1]])
In [476]: y
Out[476]: 
array([['i8'],
       ['i4'],
       ['i9'],
       ['i5'],
       ['i2'],
       ['i1'],
       ['i7'],
       ['i6'],
       ['i3']], dtype='<U2')
In [477]: y = np.frompyfunc(Y,1,1)(y)
In [478]: y
Out[478]: 
array([[i8],
       [i4],
       [i9],
       [i5],
       [i2],
       [i1],
       [i7],
       [i6],
       [i3]], dtype=object)
 

и точка:

 In [479]: np.dot(y.T,x.T)
Out[479]: 
array([[i8 i1, i4 i1 -i7 i6 -i3, i9 i1, i5 i6 -i3, i2 -i1 i3]],
      dtype=object)
 

Ответ №2:

Ваше предположение верно: умножение матриц не определено для нечисловых типов. У нас есть простая целочисленная репликация строк: «i5» * 2 дает «i5i5», а это не то, что вам нужно. Также обратите внимание, что вы используете коэффициенты с плавающей запятой, поэтому даже такая интерпретация недопустима.

Вы, кажется, работаете с символической линейной алгеброй. NumPy не имеет встроенных операций для этого домена. В зависимости от вашего приложения вы можете использовать sympy . Если нет, я ожидаю, что вам нужно определить свой собственный класс.

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

1. Создание собственного класса было моим первоначальным намерением, но я предположил, что для этого будет функция, которая будет намного эффективнее, чем просто использование базовых циклов и сравнений для построения моей выходной матрицы. Я посмотрю на сочувствие, спасибо