我正在编写一个线性回归。我在使用SciPy稀疏矩阵时遇到了.dot()
产品的问题。这是一个最小可重复的例子,有200个观测值,50个回归量和400个输出。
import numpy as np
import scipy
n_row = 200
n_col = 50
n_outcomes = 400
x = np.random.rand(n_row, n_col)
y = scipy.sparse.rand(n_row, n_outcomes, format="csc", density=0.05)
print(x.shape) # (200, 50)
print(y.shape) # (200, 400)
print((x.T @ y).shape) # (50, 400)
print(((x.T).dot(y)).shape) # (50, 200) <- WRONG, it should be (50, 400)
xx_inv = np.linalg.inv(x.T.dot(x))
xx_inv.dot((x.T).dot(y)) # this calculation takes a long time
阅读the documentation,它说对于二维矩阵,.dot()
就像矩阵乘法@
,但使用@
也可以。.dot()
对稀疏矩阵做了什么,为什么它这样做而不是抛出错误?
2条答案
按热度按时间vh0rcniy1#
使用
@
矩阵乘法的稀疏定义,产生与密集等价物相同的东西-但更快一点。y.A
是将稀疏转换为密集(.toarray()
)的正确方法。np.array(y)
错误。不仅形状不对,dtype也不对,而且时间要长得多。当形状出乎意料时,进一步挖掘,确保dtype,甚至元素值是有意义的。
另一种正确计算的方法
测试
matmul
建议:此错误是因为
np.array(y)
是0 d对象dtype数组;只是一个粗糙的数组 Package 器围绕稀疏矩阵。与dot
相比,matmul
不能对0 d,标量,对象或数组进行操作。chhqkbe12#
您可能已经从我们在评论中的讨论中了解到了这一点,但是您看到这种差异的原因可能是因为您对
matmul
使用了操作符,而对dot
使用了函数/方法。首先使用调用对象的运算符实现。但是,如果失败,则调用另一个操作数的等效反射运算符,在本例中为__rmatmul__
,它由稀疏矩阵实现。当调用dot
时,它总是使用调用对象的dot
实现,这无法正确处理稀疏数组。