Python numpy:用c_i*c_{ij}创建矩阵的快速方法
我正在寻找一种从给定向量Python numpy:用c_i*c_{ij}创建矩阵的快速方法,python,matrix,numpy,scipy,Python,Matrix,Numpy,Scipy,我正在寻找一种从给定向量bii和另一个向量创建新矩阵的快速方法 矩阵C{ij}。新矩阵的组成部分应具有以下形式: A_{ij} = b_i * C_{ij}. 到目前为止,我使用的是点(diag(b),C),但是点积自然有很多乘法 使用零,这是非常低效的。有更好的方法吗?将矩阵转换为数组,执行(广播)数组乘法,然后再转换回: np.matrix(b * np.asarray(C)) 使用*,这是具有适当广播功能的元素型产品: >>> b = array([1,2,3]) &
bii
和另一个向量创建新矩阵的快速方法
矩阵C{ij}
。新矩阵的组成部分应具有以下形式:
A_{ij} = b_i * C_{ij}.
到目前为止,我使用的是点(diag(b),C)
,但是点积自然有很多乘法
使用零,这是非常低效的。有更好的方法吗?将矩阵转换为数组,执行(广播)数组乘法,然后再转换回:
np.matrix(b * np.asarray(C))
使用
*
,这是具有适当广播功能的元素型产品:
>>> b = array([1,2,3])
>>> C = arange(9).reshape(3,3)
>>> dot(diag(b), C)
array([[ 0, 1, 2],
[ 6, 8, 10],
[18, 21, 24]])
>>> atleast_2d(b).T * C
array([[ 0, 1, 2],
[ 6, 8, 10],
[18, 21, 24]])
至少_2d(b).T
(或b.reformate(-1,1)
)将向量b
重塑为列向量。
b[:,np.newaxis] * C
或
您还可以使用:
在我的机器上,这种方法比两者都快
np.dot(np.diag(b), C)
及
对于100000个循环,einsum需要1.16秒,dot需要1.61秒,至少_2d需要2.03秒
如果您熟悉,那么einsum是一个非常有用的函数。使用索引表示法可以更容易地表述许多简单的线性代数运算,而增加的执行速度只是锦上添花。结合已经给出的答案,并尝试一种新的(但效率低下的)方法,我给出了以下计时
- einsum:0.54秒(Thycydides)
- 广播:0.44秒(拉斯曼)
- 点对角线:15.6秒(亨利克,TS)
- 稀疏直径矩阵:16.8秒(自己尝试,失败惨重:-p)
- 艾因苏姆:5.2秒
- 广播:4.5秒
import timeit
from scipy.sparse.dia import dia_matrix
import numpy as np
def get_bc():
N = 10000
M = 10000
b = np.random.random(size=N)
c = np.random.random(size=[N, M])
return b, c
def multiply_dot_diag():
global b, c
return np.dot(np.diag(b), c)
def multiply_broadcast():
global b, c
return np.atleast_2d(b).T * c
def mulitply_sparse():
global b, c
N = b.size
return dia_matrix((b, 0), shape=[N, N]).todense().dot(c)
def multiply_einsum():
global b, c
return np.einsum('i,ij->ij', b, c)
if __name__ == '__main__':
global b, c
b, c = get_bc()
print (b, c)
print (timeit.timeit(multiply_einsum, number=1))
print (timeit.timeit(multiply_broadcast, number=1))
print (timeit.timeit(multiply_dot_diag, number=1))
print (timeit.timeit(mulitply_sparse, number=1))
np.testing.assert_array_equal(multiply_dot_diag(), multiply_broadcast())
np.testing.assert_array_equal(multiply_dot_diag(), mulitply_sparse())
np.testing.assert_array_equal(multiply_dot_diag(), multiply_einsum())
那么,哈达玛积中的向量参数是否自动展开为对角矩阵?原因很好,哈达玛积只适用于相同维度的矩阵,对吗?@Christoph:我删除了令人困惑的术语哈达玛积,因为你是对的:
*
并不总是哈达玛积。没有建立中间矩阵;应用,就像矩阵的标量积(C*2
)一样。我也喜欢b[:,None]*C
,但这是一个品味问题。这正是我想要的,谢谢!对于10000x1000随机矩阵,它的速度似乎是我以前的解决方案的两倍。@henrikr:如果计算完成后不需要原始的C
,您可以使用C*=b.reformate(-1,1)
,就地执行。我想知道这里的意图。从数学上讲,乘积应该是向量,而不是一个i-by-j矩阵,对吧?克里斯托夫,不,如果我对i求和的话就是这样,这不是我想要的!
np.dot(np.diag(b), C)
np.atleast_2d(b).T * C
import timeit
from scipy.sparse.dia import dia_matrix
import numpy as np
def get_bc():
N = 10000
M = 10000
b = np.random.random(size=N)
c = np.random.random(size=[N, M])
return b, c
def multiply_dot_diag():
global b, c
return np.dot(np.diag(b), c)
def multiply_broadcast():
global b, c
return np.atleast_2d(b).T * c
def mulitply_sparse():
global b, c
N = b.size
return dia_matrix((b, 0), shape=[N, N]).todense().dot(c)
def multiply_einsum():
global b, c
return np.einsum('i,ij->ij', b, c)
if __name__ == '__main__':
global b, c
b, c = get_bc()
print (b, c)
print (timeit.timeit(multiply_einsum, number=1))
print (timeit.timeit(multiply_broadcast, number=1))
print (timeit.timeit(multiply_dot_diag, number=1))
print (timeit.timeit(mulitply_sparse, number=1))
np.testing.assert_array_equal(multiply_dot_diag(), multiply_broadcast())
np.testing.assert_array_equal(multiply_dot_diag(), mulitply_sparse())
np.testing.assert_array_equal(multiply_dot_diag(), multiply_einsum())