読者です 読者をやめる 読者になる 読者になる

MyEnigma

とあるエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

全データを保持せずに、統計値をオンライン計算する方法

はじめに

最近は、プログラミングで統計値を使うことが多くなってきました。


しかし、

あるデータが出尽くしているような状態で解析を実施する

いわゆるオフライン解析ではあまり問題にならないですが、

ロボティクスのように、センサのデータを逐次的に解析するような

オンライン解析を実施するプログラムでは、

統計値の計算の際に悩んでしまうことがあります。


例えば、有るデータの平均値を計算したい時に、

普通の平均の計算は全データを必要としますが、

そのためにはすべてのデータをメモリ上に保持しなくてはいけません。

しかし、オンライン計算が必要な組み込みシステムでは

使用できるメモリが限られているという問題があります。


そこで、

すべてのデータを保持せずに、

統計値を計算する方法が提案されているので、

それらの方法を説明したいと思います。

最大値最小値の逐次計算

これは簡単です、

最小値と最大値を格納する変数を準備し、

非常に大きい値と、小さい値に初期化しておいて、

逐次的に最大値と最小値を更新することで実現できます。


平均値の逐次計算

平均値は一つ前の平均値と、

これまで計算した値の数を保持することで、

逐次的に平均値を計算することができます。



更新の計算方法は下記の式の通りです。

\bar{x}は平均値、xは得られた値、そしてNはデータ数になります。


上記の式を使うことにより、

平均値とこれまで計算に使った値のみを保持すれば良いので、

受け取ったデータをすべて保持すること無く、

平均値の計算することができます。


C++でクラスを作成すると、このような感じでしょうか。

/** 
 * @brief 逐次平均計算によるMean Filterを実施するクラスライブラリ
 * @note 使い方 
 * 		 MeanFilter filter;
 *		 while(true){
 *			double rawData=GetData();
 *			double mean=filter.CalcMean(rawData); //平均値の取得
 *		 }
 */
class MeanFilter{
  public:
    MeanFilter(){
      InitMember();
    }
    
    /**
     * @brief 平均値を計算する関数
     *
     * @param value 生データ
     *
     * @return 平均値
     */
    double CalcMean(double value){
      totalNumber_++;
      mean_+=(value-mean_)/static_cast<double>(totalNumber_);
      return mean_;
    }

  private:

    unsigned int totalNumber_;//データの総数
    double mean_;//平均値
  
    /**
     * @brief メンバ変数の初期化関数
     */
    void InitMember(){
      totalNumber_=0;
      mean_=0;
    }
};

ガウス分布パラメータの逐次計算

作成中

参考資料