多クラス Passive Aggressive アルゴリズムの平均化

先日実装した多クラス Passive Aggressive アルゴリズムに平均化を実装してみた.コードは

を参照.実装したと言っても大したものではなく,本質的には追加したのは4行(USE_AVERAGING で囲われたところ).平均化すると,収束を待つ必要がなくなるので,繰り返し回数を 20->5 に変更して実験.

# MacBook Air (Mid 2011); Intel Core i7 1.7 Ghz CPU, 4 GB Memory

> g++ -DUSE_AVERAGING -std=c++0x -Wall -O2 spa.cc -o spaa
# covtype
> run spaa PA1 covtype.train covtype.test 0.1 5
read: 0.827s
train: .....0.965s
test: 0.073s
 class	       1       2       3       4       5       6       7         precision

     1	   12720    4460       0       0       2       0     713     17895 (0.711)
     2	    5084   19477     338       0     784     372      11     26066 (0.747)
     3	       6     319    2663     131      24     797       0      3940 (0.676)
     4	       0       1      41      83       0       9       0       134 (0.619)
     5	       0      16       0       0       4       0       0        20 (0.200)
     6	       4      81     130      19       1     279       0       514 (0.543)
     7	     392      27       0       0       0       0    1012      1431 (0.707)

	   18206   24381    3172     233     815    1457    1736     50000
recall	  (0.699) (0.799) (0.840) (0.356) (0.005) (0.191) (0.583)          (0.725)
elapsed (real): 2.209s; RSS=123.3M

# mnist
> run spaa PA1 mnist.train mnist.test 0.005 5
read: 1.143s
train: .....0.700s
test: 0.186s
 class	       0       1       2       3       4       5       6       7       8       9         precision

     0	     966       0       5       2       1      10      10       2       5      10      1011 (0.955)
     1	       0    1115       7       0       2       2       3       5       8       6      1148 (0.971)
     2	       0       3     930      19       3       2       3      24       5       1       990 (0.939)
     3	       1       2      14     925       2      32       2       8      17       9      1012 (0.914)
     4	       0       0       8       0     914      10       9       6       9      26       982 (0.931)
     5	       1       1       4      20       0     771      17       1      28       9       852 (0.905)
     6	       7       4      13       3      13      16     910       0      10       0       976 (0.932)
     7	       2       2       9      12       3       8       2     953      10      19      1020 (0.934)
     8	       3       8      37      21      10      35       2       4     877       9      1006 (0.872)
     9	       0       0       5       8      34       6       0      25       5     920      1003 (0.917)

	     980    1135    1032    1010     982     892     958    1028     974    1009     10000
recall	  (0.986) (0.982) (0.901) (0.916) (0.931) (0.864) (0.950) (0.927) (0.900) (0.912)          (0.928)
elapsed (real): 2.135s; RSS=156.8M

covtype の方では顕著に分類精度(0.716 -> 0.725; liblinear 1.8: 0.722)が上がった.mnist の方は上がっていないが,そもそもパラメタのチューニングがズル(テストでチューニング)なので,あまり議論しても仕方がない.
Passive Aggressive では(学習されるモデルの)分類精度という観点では平均化は(Perceptron におけるそれほど)必須ではない*1が,収束を待つ必要がなくなり訓練時間を削減できるという旨みの他に,ハイパーパラメタの影響が小さくなったりと,結果のモデルを「鈍らす」効果があるので,トータルの実験時間を減らしたい場合は基本使うようすると良いと思う.
IO がボトルネックなのは見ての通り.標準の訓練データのフォーマット

label(?: feature_index:feature_value)*\n

から読み込む限り,これ以上大きく速度を改善するのは難しい(少しはできる).なので,ハイパーパラメタを変えて何度も学習を繰り返す場合には,

のように,訓練データをバイナリ,あるいは符号化してディスクに保存して使う方が良いだろう.

*1:PA-I, PA-II の場合.PA の場合は Perceptron 同様,平均化で分類精度は大きく向上する.