liblinearモデルファイルのフォーマットを確認

はじめに

ちょっと気になったので、liblinearで扱われているモデルのフォーマットについて確認する。
言語処理などで高次元なものを扱う場合、線形カーネル(ただの内積)を扱った方が精度がよい場合が結構あるので、自力でモデルファイルをパースできるようにしておくと便利かも。

確認の仕方

liblinear-1.93のソースコードの「linear.cpp」のload_model関数を追ってみる

モデル形式

パラメータ情報
  • solver_type
    • 学習器の種類
      • L2R_LRやL1R_L2LOSS_SVCなど文字列
  • nr_class
    • クラス数
      • 整数値
  • nr_feature
    • 素性数
      • 整数値
  • bias
    • バイアス値
      • 小数値
  • label
    • ラベル名
      • nr_class数だけ、整数値番号が並ぶ
  • w
    • 重みの値
      • この行以降、nr_feature数分、重みのデータが並ぶ
      • また、この行が終わった後の情報は無視される(ようなコードになっている)
重み情報
  • 1行あたり、スペース区切りでnr_class個、小数値が並ぶ
  • 行は、素性番号0からnr_feature-1まで順番になっている
    • bias値によって素性数が異なることに注意

predict

  • ついでにパースしたモデルから予測する関数も確認する
処理の流れ
  • bias値が0以上の場合は、バイアス部分を考えるため、nr_feature+1個を考える
    • 最後の重みがバイアスの値として学習したもの
    • テストデータもnr_feature+1個目はバイアス用に拡張して扱われる
      • そのときの値はbias値が入る(predict.c)
  • クラス数が2&学習器がMCSVM_CSでない場合
    • 重みの合計値を出すのは1つ
  • クラス数が2より大きいorクラス数が2でMCSVM_CSの場合
    • 重みの合計値を出すのはnr_class数分
  • テストデータの「idx:value」について
    • w(c, idx) * valueを足し合わせ、重みの合計値を出す
  • クラス数が2の場合
    • L2R_L[1,2]LOSS_SVR[_DUAL]ならば、合計値を返す
    • それ以外なら、sign(合計値)に応じてラベルを返す
  • クラス数が2より大きい場合
    • 一番重みの合計値が高いクラスのラベルを返す
  • 確率値を計算できるモデルのときは、重みの合計値を使った計算式から確率を計算