[機械学習] AROWの落ち穂拾い

前回の記事でAROWを実装して、パラメータの影響に関して簡単な実験をしてみた。

まず、パラメータr=0.1,10.0,50.0とした場合の誤り率の収束は下図のようになった。(データは前回と同様にnews20.binaryを用いた)

これを見るとr=0.1のときはすぐに収束しているのに対して、r=50のときはなかなか収束しないということが分かる。

一方で元データのラベルを10%反転させたものを訓練データとして用いた場合は以下のような図が得られる。このときr=0.1と10は明らかに過学習となっているのに対し、r=50のときは反復ごとに誤り率が減少していることが分かる。

そもそもパラメータrは式(1)で表される、以前の確率分布からのずれと正しく分類できるかどうかのトレードオフパラメータであった。これが小さい場合は確率分布から大きくずれてもいいから分類を正しくすることを要求し、大きい場合は大きなずれに対してペナルティが働くため多少の分類誤りは許容するということを表す。

そのためノイズが混じっているようなデータに関してはノイズデータに引きずられないようにrを大きくする方がよいが、そうでないときはrを小さくすることで収束を早めるということができる。

この辺のrの調整や反復回数を何回にするかは論文ではクロスバリデーションないしはバリデーションセットを使って決めているがこの辺も適応的に決まるようになると面白いのではないかと思った。

[機械学習] AROWの落ち穂拾い2

とりあえず以下のコードをollのoll.cppに突っ込むことによってAROWを使うようにできる。(あとoll.hppやoll_train.cppの学習手法が並んでいるところにAROW用の値を付け加える)

バイアスの部分とかはちゃんとなってるかあまり自信ないです。

CW(Confidence-weighted)のコードと非常によく似たコードになっている。

  //
  // Adaptive Regularization Of Weight Vector
  //
  void oll::updateAROW(const fv_t& fv, const int y, const float alpha) {
    for (size_t i = 0; i < fv.size(); i++){
      if (cov.size() <= fv[i].first) {
        w.resize(fv[i].first+1);
        const size_t prevSize = cov.size();
        cov.resize(fv[i].first+1);
        for (size_t j = prevSize; j < cov.size(); j++){
          cov[j] = 1.f;
        }
      }
      w[fv[i].first] += fv[i].second * alpha * y * cov[fv[i].first];
      cov[fv[i].first] = 1.f / (1.f/cov[fv[i].first] + fv[i].second * fv[i].second / C);
    }
    b += alpha * y * covb * bias;
    covb = 1.f / (1.f/ covb + bias * bias / C);
  }

  template <>
  void oll::trainExample(const AROW_s& a, const fv_t& fv, const int y) {
    const float score = getMargin(w, b, fv) * y;
    if(score >= 1){
      return ;
    }
    const float var   = getVariance(fv);
    const float beta  = 1.0 / (var + C);
    const float alpha = (1.0 - score) * beta;
    updateAROW(fv, y, alpha);
  }