Python scipy.sparse稀疏矩阵使用感悟

默认使用csr格式的稀疏矩阵

1、如果要统计稀疏矩阵全部元素的和,不要用sum(a),用np.sum(a)或则a.sum()就好。对于shape=10000*10000的矩阵而言,全部求和采用np.sum比sum高效得多:

number = np.sum(sum(xtest_mask),axis=1)[0,0]   2.2秒

number = np.sum(xtest_mask)  0.004秒

更应该直接用xtest_mask.sum()  速度也超快

2、逐元素操作效率

注意:

xtrain 和xtrain_mask

<10000x10000 sparse matrix of type '<class 'numpy.int64'>'

       with 6897746 stored elements in Compressed Sparse Row format>

xtest 和xtest_mask

<10000x10000 sparse matrix of type '<class 'numpy.int64'>'

       with 1719466 stored elements in Compressed Sparse Row format>

两者是四倍关系,。

xtrain_mask[xtrain_mask > 0] = 1  0.73秒  

xtest_mask[xtest_mask > 0] = 1  0.17秒

时间上也是接近四倍关系。符合预期。

3、转换为np.array的效率

q=xtrain.toarray() 1.5秒

q=xtest.toarray() 0.37秒

4、求范数

norm_train = linalg.norm(xtrain,axis=1)  0.17秒

norm_train = np.linalg.norm(q,axis=1) 1.479秒

注意,求出范数后维度是(10000,),需要用reshape转换为(10000,1),此步几乎不耗时间。

norm_train = norm_train.reshape(np.shape(norm_train)[0],1)

5、矩阵乘法(尺寸改为5000*5000)

sim = (xtrain * xtrain.T) 12.45秒 (这个默认执行的是矩阵乘法而不是按位乘法))

先将xtrain转换为np.array():q,然后再计算:

sim2=np.dot(q,q.T) 矩阵乘法。这个计算的结果耗时很长很长。 183秒 

sim22=np.dot(q,q) 矩阵乘法。这个计算的结果耗时很长很长。 很长时间都没有算出来。 

为什么呢?因为矩阵是整型。转换成浮点型就会快很多倍!

q1=q.astype(float)

sim2=np.dot(q1,q1.T) 4.80

sim2=np.dot(q1,q1) 8.11秒

但这个对于稀疏矩阵的矩阵乘法而言则没有明显增益。

x1=xtrain.astype(float)

simf=x1*x1.T 12.19秒

sim3=q*q.T 默认执行的是按位乘法而不是矩阵乘法。 0.5秒 (如果后者不转置只需要0.18秒)

sim4=np.multiply(q,q.T) 执行的是按位乘法。时间结果同上。

sim5=np.multiply(xtrain ,xtrain.T) 12.64秒  同sim

如果直接用sparse内置的算法呢?

sim = xtrain.dot(xtrain.T) 12.42秒(同*号)

再做一点测试(norm_all是一个5000*5000的稠密的array)

test1=xtrain*norm_all 14.23array 矩阵乘法

test11=xtrain.toarray()*norm_all 0.34array  按位乘

test2=xtrain.dot(norm_all) 14.11array 矩阵乘法,同test1

test13=np.dot(xtrain.toarray(),norm_all) 9.53array 矩阵乘法

test14=np.dot(norm_all,norm_all) 7.84

test15=np.dot(norm_all,norm_all.T) 4.5

test3=xtrain.multiply(norm_all) 0.15  coo稀疏矩阵

q*norm_all=0.18

test3=xtrain.multiply(norm_all[0]) 0.09秒 coo稀疏矩阵

test3=xtrain.multiply(norm_all[0,0]) 0.016秒 csr稀疏矩阵

6、矩阵除以一个常数

sim/2   24.36秒 (100002)

sim/2   2.45秒 (50002)

sim.multiply(0.5)  0.24秒 (50002)

sim2/2  0.15mioa (50002)

7、矩阵按位除以矩阵

sim/sim  3.9秒 (50002)matrix

sim.toarray()/sim.toarray() 0.65秒 array

sim/sim.toarray() 0.68秒

sim.toarray()/sim 不支持

xtrain/xtrain 0.55秒  matrix

q/q 0.13

norm_all = (norm_train * norm_train.T)  0.12  array

norm_all_re = np.power(norm_all,-1) 1.36 得到按位倒数矩阵(方便做等价按位除法)

sim_norm = sim/norm_all 0.48  float的matrix

sim_norm = sim.toarray()/norm_all 0.45 floatarray

norm_all_re = np.power(norm_all,-1)  1.36

sim_norm2 = (sim.multiply(norm_all_re))  1.56 得到coo稀疏阵再通过tocsr转换要0.38秒

注:sim_re=sim.power(-1) 会报错,稀疏矩阵的Power函数不支持负数,所以就不能通过sim.multiply(sim_re)的方式实现按位除了。

 

总结:

  1. 对稀疏矩阵求范数、求解Ax=b、求逆、矩阵分解等操作可以直接用稀疏矩阵自带的算法进行求解,会高效很多;。
  2. 涉及到矩阵乘法还是转换成array更快!一定要转换!
  3. 矩阵乘法,如果是浮点型array,是最快的。若是整型array,则会超级超级慢!注意!浮点型和整型对稀疏矩阵的矩阵乘法没有太大的影响。
  4. 对于array而言,*默认为按位乘法。对于稀疏矩阵sparse而言,*默认为矩阵乘法。
  5. 按位乘法,如果是两者都是矩阵,则array远快于稀疏矩阵。如果其中一个为标量,则稀疏矩阵更快。
  6. 按位除法,如果是两者都是矩阵,则array远快于稀疏矩阵。如果其中一个为标量,则可以转换为按位乘法,稀疏矩阵更快。

 

总之,稀疏矩阵是不适合用于矩阵与矩阵之间的运算的。不论是按位运算还是矩阵运算。

 

参考资料

https://blog.csdn.net/mantoureganmian/article/details/80612137

scipy.sparse稀疏矩阵内积点乘--效率优化!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值