2014-01-31 3 views
2

Каков наилучший способ сделать это?Python/Numpy - Matrix Умножить двумерный массив и каждую строку другого двумерного массива

a = 3x3 array 
b = 20x3 array 
c = 20x3 array = some_dot_function(a, b) where: 
c[0] = np.dot(a, b[0]) 
c[1] = np.dot(a, b[1]) 
c[2] = np.dot(a, b[2]) 
...etc... 

Я знаю, что это можно сделать с помощью простого цикла питона или с помощью apply_along_axis Numpy, но мне интересно, если есть хороший способ сделать это полностью в пределах базового кода C в NumPy. Я смотрел на тендердот и некоторые другие функции, но не повезло. Я также попытался следующие:

c = np.dot(a, b[:, :, np.newaxis] 
#c.shape = (3, 59, 1) 

Это на самом деле бежал и дал результаты, которые выглядели примерно правильно, за исключением того, что полученный массив не 20x3. Я могу найти способ изменить его в массив, который я хочу, но я подумал, что должен быть более простой/более чистый/понятный встроенный метод, который мне не хватает?

ответ

6

Это дает (что смотрит на меня как) правильный результат:

numpy.dot(b, a.T) 

Вот пример вывода:

>>> a = numpy.arange(9).reshape(3, 3) 
>>> b = numpy.arange(60).reshape(20, 3) 
>>> numpy.dot(b, a.T) 
array([[ 5, 14, 23], 
     [ 14, 50, 86], 
     [ 23, 86, 149], 
     [ 32, 122, 212], 
     .... 
2
import numpy 
a = numpy.arange(9).reshape(3,3) 
b = numpy.arange(60).reshape(20,3) 
c1 = numpy.dot(b, a.T) # as in the answer of senderle 
c2 = numpy.einsum('ji,ki->kj',a,b) 

и полученный c1 и c2 являются такими же, как что вы хотите (подтверждено с помощью вашего c[i] = np.dot(a, b[i]))

преимущество numpy.einsum заключается в том, что этот трюк 'ji,ki->kj' расскажет, что нужно сделать для того, что измерение также работает для больших размеров.

больше объяснений на einsum

, например, если вы хотите сделать следующую операцию:

a = numpy.arange(60.).reshape(3,4,5) 
b = numpy.arange(24.).reshape(4,3,2) 
d1 = numpy.zeros((5,2)) 

for i in range(5): 
    for j in range(2): 
     for k in range(3): 
      for n in range(4): 
       d1[i,j] += a[k,n,i] * b[n,k,j] 

вы можете сделать то же самое гораздо быстрее, делая:

d2 = numpy.einsum('kni,nkj->ij', a, b) 
# the 'kni,nkj->ij' is what you otherwise do with the indices as in 
# d1[i,j] += a[k,n,i] * b[n,k,j] 

, или если вам не нравится этот способ указания того, что должно произойти, вы также можете использовать numpy.tensordot вместо numpy.einsum и указать ось следующим образом:

d3 = numpy.tensordot(a,b, axes=([1,0],[0,1])) 

поэтому этот метод einsum является очень общим и может быть использован для быстрого доступа для петель (которые в противном случае медленно, если вы их в Python), и очень интересно для фанков тензорного-материала

для получения дополнительной информации см http://docs.scipy.org/doc/numpy/reference/generated/numpy.tensordot.html и http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html

+0

Я видел этот метод, но я не могу показаться, чтобы обернуть вокруг головы, как это работает. Это кажется очень сильным, и я просто трачу некоторое время на чтение. Даже в документации говорится, что лучший способ понять это с примерами. Может быть, мне нужно больше поиграть с ним, но я не понимаю с места битвы, как здесь работают суммы. –

+0

@ScottB, подумайте о строке, указав форму, которую примет оператор присваивания, если вы пишете его на чистом питоне, используя серию вложенных циклов. 'i' - это самый внешний индекс,' j', следующий и т. д., а формат - '{индексы}, {b индексы} -> {выходные индексы}'. Другими словами, 'output [i, j] + = a [i, j] * b [j, k]' становится 'ij, jk-> ij''. Посмотрите, как это работает? ИМО, используя 'dot' и' T', здесь более разборчиво, но для необычных суммирования 'einsum' - это абсолютно путь. – senderle

+0

@ScottB Я добавил несколько строк после d2 = ...чтобы объяснить немного больше, что вы делаете с этими индексами, на самом деле это довольно просто, как только вы обнимаете его (просто напишите, как в четверке для цикла, например d1 [i, j] = ..., а затем напишите, что вы делаете с индексами, но в одной строке, как и в d2 = ... – usethedeathstar

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

  • Нет связанных вопросов^_^