Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python numpy:用c_i*c_{ij}创建矩阵的快速方法_Python_Matrix_Numpy_Scipy - Fatal编程技术网

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)
如果我每十次重复einsum和广播(更精确的计时),我会发现:

  • 艾因苏姆: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())