Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中均值和协方差的快速增量更新_Python_Numpy_Normal Distribution - Fatal编程技术网

Python中均值和协方差的快速增量更新

Python中均值和协方差的快速增量更新,python,numpy,normal-distribution,Python,Numpy,Normal Distribution,我有一个Python脚本,需要经常更新均值和协方差矩阵。我目前正在做的是,每次我得到一个新的数据点$x$(一个向量),我重新计算平均值和协方差,如下所示: 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

我有一个Python脚本,需要经常更新均值和协方差矩阵。我目前正在做的是,每次我得到一个新的数据点$x$(一个向量),我重新计算平均值和协方差,如下所示:

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)
问题是这对我来说不够快。通过增量更新
mean
cov
而无需基于所有
数据重新计算它们,是否会提高效率


增量计算平均值应该很容易,我能计算出来。我的主要问题是如何更新协方差矩阵
self.cov

对于平均值计算,您可以存储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]
 [ 2.7   3.7  -3.05]
 [-4.05 -3.05  5.7 ]]
新的

对于方差(仅协方差矩阵的对角线),它很简单。您还需要保留数据的平方和。回想一下,方差的公式是:Var(x)=E[x^2]-(E[x])^2)。所以每一步你都要计算你的常规平均值,和平方和的平均值


这可以推广到全协方差矩阵的多元变量。看一看。

我刚刚发现,使用mdp库可以很容易地做到这一点

我会通过跟踪平方和和和来做到这一点

\uuuu init\uuuu
中:

self.sumx = 0
self.sumx2 = 0
然后在附录中:

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]
广播以查找每对元素的产生量

平均值易于增量计算。我的问题主要是如何更新协方差矩阵。我的
数据
只是一个浮点数列表。@eLearner,我认为numpy不直接支持它,但可以手动检查,请检查我更新的答案代码,谢谢阅读并使用在线算法,包括方差和协方差。远离下面的建议来跟踪平方和,因为它们在数值上可能是不稳定的。本文介绍了一种更新平均值和其他矩的快速方法,我很想看看你是如何应用它的。
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)