2016-10-31 9 views
2

Я работаю над матричными умножениями в NumPy, используя np.dot(). Поскольку набор данных очень велик, я хотел бы максимально сократить общее время выполнения, т. Е. Выполнить как можно меньше продуктов np.dot().Линейная алгебра в Numpy

В частности, мне нужно рассчитать общий матричный продукт, а также соответствующий поток от каждого элемента моего вектора значений. Есть ли способ в NumPy рассчитать все это вместе в одном или двух продуктах np.dot()? В приведенном ниже коде есть ли способ уменьшить количество продуктов np.dot() и получить одинаковый результат?


import pandas as pd 
import numpy as np 

vector = pd.DataFrame([1, 2, 3], 
         ['A', 'B', 'C'], ["Values"]) 

matrix = pd.DataFrame([[0.5, 0.4, 0.1], 
         [0.2, 0.6, 0.2], 
         [0.1, 0.3, 0.6]], 
         index = ['A', 'B', 'C'], columns = ['A', 'B', 'C']) 

# Can the number of matrix multiplications in this part be reduced? 
overall = np.dot(vector.T, matrix) 
from_A = np.dot(vector.T * [1,0,0], matrix) 
from_B = np.dot(vector.T * [0,1,0], matrix) 
from_C = np.dot(vector.T * [0,0,1], matrix) 

print("Overall:", overall) 
print("From A:", from_A) 
print("From B:", from_B) 
print("From C:", from_C) 
+0

См. Обсуждение здесь - http://stackoverflow.com/questions/21562986/numpy-matrix-vector-multiplication –

+0

Можете ли вы предоставить лучший пример желаемого ввода и вывода? Не совсем понятно, что вы хотите. –

+0

Вам здесь не требуется матричное умножение. См. Мой ответ. Я думаю, что это лучше, чем выбранный в настоящий момент. –

ответ

1

Вы можете определить 3 x 3 формы 2D массив этих масштабирования значений и выполнения матричного умножения, например, так -

scale = np.array([[1,0,0],[0,1,0],[0,0,1]]) 
from_ABC = np.dot(vector.values.ravel()*scale,matrix) 

Пример запуска -

In [901]: from_A 
Out[901]: array([[ 0.5, 0.4, 0.1]]) 

In [902]: from_B 
Out[902]: array([[ 0.9, 1.6, 0.5]]) 

In [903]: from_C 
Out[903]: array([[ 0.8, 1.3, 1.9]]) 

In [904]: from_ABC 
Out[904]: 
array([[ 0.5, 0.4, 0.1], 
     [ 0.9, 1.6, 0.5], 
     [ 0.8, 1.3, 1.9]]) 

Вот вариант с np.einsum сделать все это за один шаг -

np.einsum('ij,ji,ik->jk',vector.values,scale,matrix) 

Пример запуска -

In [915]: np.einsum('ij,ji,ik->jk',vector.values,scale,matrix) 
Out[915]: 
array([[ 0.5, 0.4, 0.1], 
     [ 0.9, 1.6, 0.5], 
     [ 0.8, 1.3, 1.9]]) 
+0

Большое спасибо за быстрый ответ. Это очень полезно! – Andreas

+0

@ Андреас Рад помочь! – Divakar

+0

И 'scale' просто' np.eye (3) ' – kennytm

2

Если векторы, используемые для выбора строки действительно единичные векторы, вы гораздо лучше не делать матричное умножение на все для from_A, from_B, from_C. Умножение матриц требует намного больше сложения и умножений, чем вам нужно просто умножить каждую строку матрицы на это соответствующая запись в векторе:

from_ABC = matrix.values * vector.values 

Вам потребуется только один вызов np.dot получить overall.

+0

спасибо. Очень полезно знать, что np.dot намного медленнее, чем простой продукт с использованием *. – Andreas

+0

Это всего лишь вопрос количества операций. Мой продукт транслируется так, что есть только продукты matrix.size и без сумм. Точка имеет vector.size * matrix.size продукты и matrix.shape [0] суммы. –

+0

Я просто предположил, что у ОП был минимальный пример с размерами масштабирования, но, похоже, это фактические значения, с которыми работает OP. Итак, это хорошо! – Divakar

Смежные вопросы