所以我有这些巨大的矩阵X和Y.X和Y都有1亿行,X有10列。我正在尝试用这些矩阵实现线性回归,我需要数量(X^T*X)^-1 * X^T * Y
。如何尽可能节省空间来计算?
现在我有
X = readMatrix("fileX.txt")
Y = readMatrix("fileY.txt")
return (X.getT() * X).getI() * X.getT() * Y
这里有多少个矩阵存储在内存中?一次存储两个以上的矩阵吗?有没有更好的方法呢?
这个项目我有大约1.5 GB的内存。如果我关闭所有其他程序,我可以将它拉伸到2或2.5。理想情况下,该过程也会在很短的时间内运行,但内存限制更严格。
我尝试过的另一种方法是将计算的中间步骤保存为文本文件,并在每个步骤后重新加载它们。但那很慢。
答案 0 :(得分:3)
X的大小为100e6 x 10 Y的大小是100e6 x 1
因此(X^T*X)^-1 * X^T * Y
的最终尺寸为10 x 1
您可以按照以下步骤计算:
a = X^T*X
- > 10 x 10 b = X^T*Y
- > 10 x 1 a^-1 * b
步骤3中的矩阵非常小,所以你只需要做 一些中间步骤来计算1& 2。
例如,您可以读取X和Y的第0列,
并按numpy.dot(X0, Y)
计算。
对于float64 dtype,X0和Y的大小约为1600M,如果 它不能适合内存,你可以调用numpy.dot两次 X0&的前半部分和后半部分Y分开。
所以计算X^T*Y
你需要调用numpy.dot 20次,
计算X^T*X
你需要调用numpy.dot 200次。
答案 1 :(得分:2)
普通最小二乘回归的一个简洁属性是,如果你有两个数据集X1,Y1和X2,Y2并且你已经计算了所有
现在你想对组合数据集X = [X1; X2]和Y = [Y1; Y2],你实际上不必非常重新计算。关系
按住,所以使用这些计算你只需计算
你完成了。这导致在非常大的数据集上使用简单的OLS算法:
这并不比一次加载整个数据集慢得多,而且它使用的内存要少得多。
最后的注释:你永远不应该通过先计算(X' * X)并找到它的逆来计算beta(有两个原因 - 1.它很慢,而且它很容易数值误差。)
相反,你应该解决线性系统 -
在MATLAB中,这是一个简单的单行
beta = (X' * X) \ (X' * Y);
我希望numpy有一种类似的解决线性系统的方法,而不需要反转矩阵。
答案 2 :(得分:1)
如果矩阵是稀疏的(大量零),请使用稀疏矩阵类来节省大量RAM。
如果矩阵不稀疏,您可能需要更多RAM(或至少更多虚拟内存),或者使用磁盘文件进行矩阵操作。
磁盘文件当然比RAM慢一个数量级,并且根据您的访问模式,颠倒您的虚拟内存系统实际上可能会比这更糟糕。