概要

本稿は私が初めてLIBLINEARを触った際に残したメモ書きです。

やったことは、導入、READMEに従ったサンプルの実行、自前で作ったデータを使った簡単な実践。

@CretedDate 2012/06/04
@Env LIBLINEAR1.91, Ubuntu10.04

資料を読む

まずは右も左も分からない状態なので、資料を読むことから始めます。

公式サイトは以下
http://www.csie.ntu.edu.tw/~cjlin/liblinear/

ここのDocumentationのところに参考になる資料がPDF形式で置いてあります。

LIBLINEAR: A library for large linear classificationという資料の概要には、以下のようなことが書かれています(意訳)。

LIBLINEARは大規模なデータに使えるオープンソースの線形クラスタリングライブラリです。ロジスティック回帰とSVMをサポートしています。コマンドラインでの利用とプログラムからの呼び出しが可能です。

コマンドラインツールは簡単に使えるよとか、資料はビギナー向けも用意してあるよと書かれていますが、それらはあくまでも彼らのレベルから見て、easyでありbeginners向けなのだと思われます。私レベルのbeginnerにとってはかなり難解でした。

上記資料の「3.2 Documentation」の項には、下記のようなことが書いてあります(意訳)。

READMEにQuickStartが書いてあるよ。FAQも参考になるよ。あと、train.cpredict.cは良いサンプルにもなっていると思うよ。

ということで上記に従い、まずはREADMEでも読みながら適当に使ってみることにします。

導入

とりあえずLIBLINEARをダウンロードしてmakeします。

公式サイトのDownload LIBLINEARの項からダウンロードします。

開いたら解凍して、cdして、makeします。

$ tar xzvf liblinear-1.91.tar.gz
$ cd liblinear-1.91
$ make

これでtrain(学習)とpredict(予測)という2つのバイナリが生成されました。

READMEを読む

導入の項で持ってきたディレクトリの直下にREADMEがいます。19KBのそれなりに充実した内容になっています。

READMEのQuickStartの項に、「heart_scaleというサンプルファイルがそこにいるから使うといいよ」と書いてあります。

heart_scaleは下記のような情報が並んだ28KBのテキストファイル。

+1 1:0.708333 2:1 3:1 4:-0.320755 5:-0.105023 6:-1 7:1 8:-0.419847 9:-1 10:-0.225806 12:1 13:-1
-1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1
+1 1:0.166667 2:1 3:-0.333333 4:-0.433962 5:-0.383562 6:-1 7:-1 8:0.0687023 9:-1 10:-0.903226 11:-1 12:-1 13:1
-1 1:0.458333 2:1 3:1 4:-0.358491 5:-0.374429 6:-1 7:-1 8:-0.480916 9:1 10:-0.935484 12:-0.333333 13:1
-1 1:0.875 2:-1 3:-0.333333 4:-0.509434 5:-0.347032 6:-1 7:1 8:-0.236641 9:1 10:-0.935484 11:-1 12:-0.333333 13:-1

1〜13までの要素と、-1/+1という評価が記録されたファイルのようです。

とりあえず上記ファイルを使ってtrainしてみます。走っていける。

$ ./train heart_scale

するとheart_scale.modelというファイルが生成されます。同ファイルの内容は以下。

solver_type L2R_L2LOSS_SVC_DUAL
nr_class 2
label 1 -1
nr_feature 13
bias -1
w
0.0943504742557872
0.2285415647938311
0.4265839247826413
0.2697220013945633
-0.003675415815027402
-0.1619822757462984
0.1234298617257453
-0.269227089689369
0.131079550049672
0.05224602659074058
0.1680899591799004
0.4444803957964643
0.2557915826296381

13個の要素についてスコアが割り振られた感じのファイルになっています。1行目のL2R_L2LOSS_SVC_DUALは、L2-regularized L2-loss support vector classification (dual)の略で、デフォルトで使われる手法らしい。

指定できるタイプはヘルプを見れば出てきます。

$ ./train -h

各手法の説明はPDFに書かれているけど、不勉強なのでちゃんとは理解できてない。あとで勉強する。

trainしただけでは寂しいので、predictもしてみる。試しにheart_scale.tというファイルを作って、そこに適当な情報を書き込み、predictしてみることに。

$ vi heart_scale.t

よく分からないけど適当なデータをでっち上げる。

1 1:0.5 2:0.5 3:0.5 4:-0.5 5:-0.5 6:-0.5 7:-0.5 8:-0.5 9:0.5 10:-1 12:0 13:1
-1 1:0.3 2:0.3 3:0.3 4:-0.3 5:-0.8 6:-0.8 7:-0.9 8:-0.8 9:0.7 10:-1 12:0 13:1

predictは引数に、対象データ(今回はheart_scale.t)、モデル(heart_scale.model)、出力結果(仮にheart_scale.resultとする)の3つを渡す。

$ ./predict heart_scale.t heart_scale.model heart_scale.result
Accuracy = 50% (1/2)

出力された結果ファイルには下記のように出力されていました。

1
1

上記のテストデータだと結果は両方とも1になるらしい。このデータがどういう意味なのか知らないけど、こうやってファイルを渡せば結果を予測してくれることは分かりました。

あとはこれを利用して、何らかの問題を解かせてみれば良いのですな。

Wikipediaから文章が書かれたブロックを抽出する

今、手元にWikipediaのwiki記法をgwtwikiを使ってHTMLに変換したファイルがあります。

こんな感じのファイル

このファイルを形態素解析のコーパスとして用いたいと考えています。コーパスとして用いる場合、目次とか他言語へのリンクとか関連記事へのリンクとかの要素は邪魔になるので削除したいです。

HTMLの各ブロックごとに特徴量を出してLIBLINEARに食べさせれば、自動で文章が書かれたブロックだけを抽出できそうな気がします。

というわけで、各ブロックに対して下記の9つの値を算出し、trainを実行してみることにします。

  1. 手動で付けた評価 -1/1 (1は文章、-1はいらない子)
  2. 要素名(p, divなど)
  3. 文字列の長さ
  4. リンク(a要素)内の文字列の長さ
  5. 句読点の数
  6. 平仮名の数
  7. カタカナの数
  8. アルファベットの数
  9. 記号の数

まずは正解データとして、上の9つの値+ブロックの本文をTSVで記述した下記のようなファイルを作成しました。

正解データ

評価はかなり適当です。欲しいと思ったブロックになんとなく1を振ってます。

上記のデータを変換して、下記のようなLIBLINEARが扱える形のデータを生成します。

LIBLINEAR用データ

このファイルをtrainしてモデルを生成します。

下記は生成されたモデルを利用して、テストデータとは別の文書に対してpredictを実行した結果です。文字が灰色になってるところが除外対象と判定されたブロック。

かごめかごめ   アポロ計画   秘密戦隊ゴレンジャー   Java   藤子不二雄

適当に正解データを作った割に、ちゃんと文章っぽいところだけ抽出してくれてます。こりゃ便利だ。

応用すればWebの本文抽出とかにも使えるんだろうなぁ。

あとがき

なんとなくですがLIBLINEARの使い方が分かった気がします。SVMに関する知識がないので適切な使い方はまだ選択できそうにありませんが。

LIBLINEARは形態素解析器のKyTeaでも使われている自然言語処理と相性の良い子。Java版も存在し、ライセンスはBSD系で、JARファイルのサイズは52KB。ということは将来的にはKyTea的なLucene用形態素解析器が出るんじゃないかなぁと思っていたりします。