Давайте начнем с вспомогательную функцию, которая создает ListOfLists (а LoL) из r
строк, каждая из которых состоит из c
колонн:
In [1]: def lol(r,c): return [[i*c+j for j in range(c)] for i in range(r)]
и создать два списка списков
In [2]: a = lol(2,5) ; b = lol(5,4)
Мы хотим чтобы убедиться, что наш код ниже, предназначенный для работы с матричным продуктом с использованием двух LOL, работает правильно, поэтому мы создаем два ndarray
s от a
и b
и формируем их внутренний продукт
In [3]: from numpy import array
In [4]: aa = array(a) ; ab = array(b) ; aa.dot(ab)
Out[4]:
array([[120, 130, 140, 150],
[320, 355, 390, 425]])
Теперь мы можем проверить наш код для внутренних или матриц, произведение два Lols
In [5]: [[sum(x*y for x, y in zip(ar,bc)) for bc in zip(*b)] for ar in a]
Out[5]: [[120, 130, 140, 150], [320, 355, 390, 425]]
Это нормально, не так ли? (Я должен сказать, что на первой итерации кода я вышел с транспонированием результата ...).
Теперь, когда у нас есть немного уверенности, давайте попробуем что-то более существенное
In [6]: a = lol(200,50) ; b = lol(50,400)
In [7]: aa = array(a) ; ab = array(b)
In [8]: %timeit c = aa.dot(ab)
100 loops, best of 3: 4.53 ms per loop
In [9]: %timeit c = [[sum(x*y for x, y in zip(ar,bc)) for bc in zip(*b)] for ar in a]
1 loops, best of 3: 469 ms per loop
Как вы можете видеть, numpy
есть два порядка быстрее, чем работает в списках, но это более интересно, в контекст ОП вопрос, чтобы попробовать наш список код на ndarray
с:
In [10]: %timeit c = [[sum(x*y for x, y in zip(ar,bc)) for bc in zip(*ab)] for ar in aa]
1 loops, best of 3: 1.32 s per loop
о, если у вас есть numpy
массивов это лучше использовать методы массива, а не работать на отдельных элементах ... ноподождите, у нас есть более быстрая альтернатива внутренних zip
:
In [11]: %timeit c = [[sum(x*y for x, y in zip(ar,bc)) for bc in ab.T] for ar in aa]
1 loops, best of 3: 1.34 s per loop
In [12]:
нет, даже если мы используем транспонирование свойство ndarray
мы имеем те же результаты.
Резюме: никогда не использовать по отдельности доступны numpy
элементов массива, чтобы сделать тяжелую вычислительную лифтинг ...
Спасибо ipython
и его %timeit
магия, что сделал это бессвязное легче и весело (для меня) ,
Просто из любопытства это для школы, или вы на самом деле пытаетесь сделать матричное умножение для какой-то реалистической цели? Если последний, используйте 'np.dot'. Не зацикливайте массивы Numpy по элементам в Python, если вы можете помочь. – Iguananaut
@Iguananaut На самом деле мне нужно рассчитать и сравнить время вычисления этих двух методов и np.dot. – Sage