2016-05-28 16 views
2

私は頻繁に平均と共分散行列を更新する必要があるPythonスクリプトを持っています。Pythonの平均と共分散の高速増分更新

data.append(x) # My `data` is just a list of lists of floats (i.e., x is a list of floats) 
self.mean = np.mean(data, axis=0) # self.mean is a list representing the center of data 
self.cov = np.cov(data, rowvar=0) 

問題は、それは私のために十分な速さではないです。私は現在やっていることは、次のように私は新しいデータポイントの$ Xの$(ベクトル)を取得するたびに、私は平均と共分散を再計算することです。いずれにしても、に基づいて再計算せずに、meancovを徐々に更新すると効率的ですか?

コンピューティングの平均を段階的に簡単にする必要があります。私の主な問題は、共分散行列self.covを更新する方法です。平均計算の

+0

読む[このWikipediaの記事] (https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance)、分散と共分散の両方についてオンラインアルゴリズムを使用します。数値的に不安定である可能性があるので、四角形の合計を追跡するために、以下の提案から離れてください。 – Jaime

答えて

-1

、あなたは、前にN個のデータの平均値を格納し、それが「before_mean」と呼ばれると仮定して、新しいデータxが来るとき可能性があり、新しいこれらのNの平均+ 1のデータは、単純に前のように計算されます。

new_mean = float(before_mean * N + x)/(N + 1) 

データの前に再計算する必要はありません。

covの場合、単純にその問題を解決する方法はないと思います。数字以外のリストでcovが常に使用されるため、データ入力についてはわかりません。興味があるだけのために、私はそれはO(N)だとしてあなたは、データセットその大きくない場合は、この気にする必要はありませんだと思う

が、それは〜

を役に立てば幸い======= =====更新===========

import numpy as np 
import random 

data = [] 
means = [] 
for m in range(3): 
    sample_data = random.sample(range(10), 5) 
    means.append(np.mean(sample_data)) 
    data.append(sample_data) 

# calculate origin cov 
origin_cov = np.cov(data) 
print origin_cov 

# new data 
x = random.sample(range(10), 5) 
mean_x = np.mean(x) 
var_x = np.var(x) 
new_line_cov = [] 
new_cov = np.empty([len(data)+1, len(data)+1]) 
for idx, sample_data in enumerate(data): 
    mul_x_sample = 0 
    for (elem_x, elem_sample) in zip(x, sample_data): 
      mul_x_sample += (elem_x * elem_sample) 
    mul_x_sample = mul_x_sample/len(x) 
    cov_x_sample = mul_x_sample - mean_x * means[idx] 
    new_cov[idx] = np.append(origin_cov[idx],cov_x_sample) 
    new_line_cov.append(cov_x_sample) 
new_line_cov.append(var_x) 
new_cov[len(data)] = np.array(new_line_cov) 

print new_cov 

出力結果を以下のように:

原点

分散(共分散行列の対角のみ)について

新しい

[[ 9.7 2.7 -4.05 0.56] 
[ 2.7 3.7 -3.05 1.56] 
[-4.05 -3.05 5.7 0.36] 
[ 0.56 1.56 0.36 8.56]] 
+0

平均は徐々に計算するのが簡単です。私の問題は、主に共分散行列を更新する方法でした。私の 'data'は単なるフロートのリストです。 – eLearner

+0

@eLearner、私はそれがnumpyで直接サポートされているとは思わないが、手動でチェックすることができます、私の更新された回答コードを確認してください、ありがとう – linpingta

0

それは簡単です。また、データの平方和を保つ必要があります。分散の式は以下の通りであることを想起してください。Var(x)= E [x^2] - (E [x])^ 2)だから、各段階であなたの普通の平均と平方和の平均を計算しています。

これは、完全共分散行列の多変量変数に対して一般化することができます。見てくださいhere

2

私は二乗和と合計を追跡することにより、それを行うだろうと行うことができます考え出しました。追記で

self.sumx = 0 
self.sumx2 = 0 

そして:

__init__

data.append(x) 
self.sumx += x 
self.sumx2 += x * x[:,np,newaxis] 

self.mean = sumx/len(data) 
self.cov = (self.sumx2 - self.mean * self.mean[:,np,newaxis])/len(data) 

[:,np.newaxis]は、要素のすべてのペアの農産物を見つけるために、放送に注目し