NumPy中的线性回归与非常大的矩阵 - 如何节省内存?

时间:2012-10-30 21:47:10

标签: python numpy

所以我有这些巨大的矩阵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。理想情况下,该过程也会在很短的时间内运行,但内存限制更严格。

我尝试过的另一种方法是将计算的中间步骤保存为文本文件,并在每个步骤后重新加载它们。但那很慢。

3 个答案:

答案 0 :(得分:3)

X的大小为100e6 x 10 Y的大小是100e6 x 1

因此(X^T*X)^-1 * X^T * Y的最终尺寸为10 x 1

您可以按照以下步骤计算:

  1. 计算a = X^T*X - > 10 x 10
  2. 计算b = X^T*Y - > 10 x 1
  3. 计算a^-1 * b
  4. 步骤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并且你已经计算了所有

  • X1' * X1
  • X1' * Y1
  • X2' * X2
  • X2' * Y2

现在你想对组合数据集X = [X1; X2]和Y = [Y1; Y2],你实际上不必非常重新计算。关系

  • X' * X = X1' * X1 + X2' * X2
  • X' * Y = X1' * Y1 + X2' * Y2

按住,所以使用这些计算你只需计算

  • beta = inv(X' * X)*(X' * Y)

你完成了。这导致在非常大的数据集上使用简单的OLS算法:

  • 加载部分数据集(例如,前一百万行)并计算X' * X和X' * Y(非常小的矩阵)并存储它们。
  • 继续为下一百万行执行此操作,直到您处理完整个数据集为止。
  • 将所有X'加在一起。 * Xs和X' *你存储的是
  • 计算beta = inv(X' * X)\(X' * Y)

这并不比一次加载整个数据集慢得多,而且它使用的内存要少得多。

最后的注释:你永远不应该通过先计算(X' * X)并找到它的逆来计算beta(有两个原因 - 1.它很慢,而且它很容易数值误差。)

相反,你应该解决线性系统 -

  • (X' * X)* beta = X' * Y

在MATLAB中,这是一个简单的单行

beta = (X' * X) \ (X' * Y);

我希望numpy有一种类似的解决线性系统的方法,而不需要反转矩阵。

答案 2 :(得分:1)

RAM很便宜 - 你应该考虑投资。拥有24千兆内存的系统不再需要花费一条腿和一条腿 - 戴尔的一台低端服务器可以打包这么多。

如果矩阵是稀疏的(大量零),请使用稀疏矩阵类来节省大量RAM。

如果矩阵不稀疏,您可能需要更多RAM(或至少更多虚拟内存),或者使用磁盘文件进行矩阵操作。

磁盘文件当然比RAM慢一个数量级,并且根据您的访问模式,颠倒您的虚拟内存系统实际上可能会比这更糟糕。