np.dot 3x3,带有 N 个 1x3 数组

ice*_*itz 5 python numpy matrix linear-algebra array-broadcasting

我有一个 N 1x3 数组的 ndarray 我想与 3x3 矩阵执行点乘法。我似乎无法找到一种有效的方法来做到这一点,因为所有 multi_dot 和 tensordot 等方法似乎都是递归求和或乘以每个操作的结果。我只想像应用标量一样应用点乘法。我可以使用 for 循环或列表理解来完成此操作,但对于我的应用程序来说太慢了。

N = np.asarray([[1, 2, 3], [4, 5, 6], [7, 8, 9], ...])
m = np.asarray([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
Run Code Online (Sandbox Code Playgroud)

我想执行类似这样的操作,但没有任何 python 循环:

np.asarray([np.dot(m, a) for a in N])
Run Code Online (Sandbox Code Playgroud)

这样它就简单地返回[m * N[0], m * N[1], m * N[2], ...]

最有效的方法是什么?有没有办法做到这一点,以便如果 N 只是一个 1x3 矩阵,它只会输出与 np.dot(m, N) 相同的结果?

Mad*_*Lee 4

尝试这个:

import numpy as np
N = np.asarray([[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 2, 3], [4, 5, 6]])
m = np.asarray([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
re0 = np.asarray([np.dot(m, a) for a in N])  # original
re1 = np.dot(m, N.T).T  # efficient
print("result0:\n{}".format(re0))
print("result1:\n{}".format(re1))
print("Is result0 == result1? {}".format(np.array_equal(re0, re1)))
Run Code Online (Sandbox Code Playgroud)

输出:

result0:
[[ 140  320  500]
 [ 320  770 1220]
 [ 500 1220 1940]
 [ 140  320  500]
 [ 320  770 1220]]
result1:
[[ 140  320  500]
 [ 320  770 1220]
 [ 500 1220 1940]
 [ 140  320  500]
 [ 320  770 1220]]
Is result0 == result1? True
Run Code Online (Sandbox Code Playgroud)

时间成本:

import timeit
setup = '''
import numpy as np
N = np.random.random((1, 3))
m = np.asarray([[10, 20, 30], [40, 50, 60], [70, 80, 790]])
'''

>> timeit.timeit("np.asarray([np.dot(m, a) for a in N])", setup=setup, number=100000)
0.295798063278
>> timeit.timeit("np.dot(m, N.T).T", setup=setup, number=100000)
0.10135102272
# N = np.random.random((10, 3))
>> timeit.timeit("np.asarray([np.dot(m, a) for a in N])", setup=setup, number=100000)
1.7417007659969386
>> timeit.timeit("np.dot(m, N.T).T", setup=setup, number=100000)
0.1587108800013084
# N = np.random.random((100, 3))
>> timeit.timeit("np.asarray([np.dot(m, a) for a in N])", setup=setup, number=100000)
11.6454949379
>> timeit.timeit("np.dot(m, N.T).T", setup=setup, number=100000)
0.180465936661
Run Code Online (Sandbox Code Playgroud)