4

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

ここでメモリに格納されている行列の数は? 一度に 3 つ以上の行列が保存されていますか? それを行うより良い方法はありますか?

このプロジェクトには約 1.5 GB のメモリがあります。他のすべてのプログラムを閉じると、おそらく2または2.5に伸ばすことができます。理想的には、プロセスも短時間で実行されますが、メモリ バウンドはより厳密です。

私が試したもう 1 つの方法は、計算の中間ステップをテキスト ファイルとして保存し、各ステップの後に再読み込みすることです。しかし、それは非常に遅いです。

4

3 に答える 3

3

Xのサイズは100e6x10です。Yのサイズは100e6x1です。

したがって、の最終的なサイズは10x1です(X^T*X)^-1 * X^T * Y

次の手順で計算できます。

  1. 計算a = X^T*X->10x 10
  2. 計算b = X^T*Y->10x 1
  3. 計算するa^-1 * b

手順3の行列は非常に小さいため、1と2を計算するには、いくつかの中間手順を実行する必要があります。

たとえば、XとYの列0を読み取り、それをで計算できますnumpy.dot(X0, Y)

float64 dtypeの場合、X0とYのサイズは約1600Mです。メモリに収まらない場合は、X0とYの前半と後半で別々にnumpy.dotを2回呼び出すことができます。

したがって、計算X^T*Yするにはnumpy.dotを20回呼び出す必要があり、計算X^T*Xするにはnumpy.dotを200回呼び出す必要があります。

于 2012-10-31T00:42:50.963 に答える
2

通常の最小二乗回帰の優れた特性は、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

保持するので、これらの計算を使用して計算するだけです

  • ベータ = inv(X' * X) * (X' * Y)

これで完了です。これにより、非常に大きなデータセットでの OLS の単純なアルゴリズムが得られます。

  • データセットの一部 (最初の 100 万行など) を読み込み、X' * X と X' * Y (非常に小さな行列) を計算して格納します。
  • データセット全体を処理するまで、次の 100 万行に対してこれを続けます。
  • 保存した X' * X と X' * Y をすべて加算します。
  • beta = inv(X' * X) \ (X' * Y) を計算します。

これは、データセット全体を一度に読み込むよりもそれほど遅くはなく、使用するメモリもはるかに少なくなります。

最後の注意:最初に (X' * X) を計算し、その逆数を求めることによってベータを計算するべきではありません (2 つの理由 - 1. 遅い、2. 数値エラーが発生しやすい)。

代わりに、線形システムを解く必要があります -

  • (X' * X) * ベータ = X' * Y

MATLAB では、これは単純なワンライナーです。

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

そして、numpy には行列を反転する必要なく線形システムを解く同様の方法があると期待しています。

于 2015-01-12T21:07:53.127 に答える
1

RAM は非常に安価です。投資を検討する必要があります。24 ギガの RAM を搭載したシステムは、必ずしも腕と脚の費用がかかるわけではありません。Dell のローエンド サーバーの 1 つは、それだけの量を詰め込むことができます。

行列が疎 (多数のゼロ) の場合は、疎行列クラスを使用して RAM を大幅に節約します。

行列がスパースでない場合は、より多くの RAM (または少なくともより多くの仮想メモリ) が必要になるか、ディスク ファイルを使用して行列操作を行う必要があります。

もちろん、ディスク ファイルは RAM よりも桁違いに遅く、アクセス パターンによっては、仮想メモリ システムのスラッシングが実際にはそれよりも悪い場合があります。

于 2012-10-30T22:11:17.520 に答える