go言語で書いた (gist)。集合の要素は前もってソートしておいて、比較回数を減らしている。
概要 mafというツールが便利そうだったのでメモ。 評価のために必要なめんどくさい処理が簡略化されそうな気がする。 実験結果の管理などがヘタなので、mafを使ってちょっとでもうまくなりたい。 まだ調べ始めたばかりなので、以降で出てくるコードよりももっとうまい書き方があると思う。
今回は色々とパラメータを変えて学習した分類器を評価する例で進める。
使ってみた まず、wafとmafとダウンロードする。
$cd /path/to/project/ $wget https://github.com/pfi/maf/raw/master/waf $wget https://github.com/pfi/maf/raw/master/maf.py $chmod +x waf 以下の様な wscript を作成。
#!/usr/bin/python import re import json import numpy as np import maf import maflib.util def configure(conf): pass @maflib.util.rule def jsonize(task): """ Calculate accuracy from a format as below: Recall[-1]: 0.932965 (21934/23510) Prec[-1]: 0.849562 (21934/25818) -- Recall[+1]: 0.478378 (3562/7446) Prec[+1]: 0.693266 (3562/5138) """ out = task.parameter with open(task.inputs[0].abspath(), 'r') as f: num = 0 num_trues = 0 for line in f: if line.
概要 日本語の文書を単純な方法で分類器を学習するところまでの一連の処理をGoでやってみる。 分類器は何でも良いのだけど、先日書いたAdaGrad+RDAを使う。
ラベルが付いた日本語のデータがあるという前提で、以下の流れで進める。
文書を文に分割する。今回は「。」で区切る。 文を形態素解析して名詞や動詞(表層形)を取り出し、文書をある単語を含む、含まないの二値で表現した素性ベクトルに変換する。 訓練データを使って分類器を学習して、できたモデルの中身を見てみる。 データ 下記URLから得られるテキストの一部を使って、ラベルをそれぞれ、「スポーツ」、「政治」、「Go言語」とラベルを付与し、第一カラムをラベル、第二カラムを文書としたCSVに保存しておく。
本田圭佑:セリエA日本人4人目マルチ!惨敗ブラジル戦憂さ晴らし 観劇収支ズレどう説明、公私混同疑いも…小渕氏 古いプログラミング言語がなくならない理由 $cat data.csv スポーツ,ACミランFW本田圭佑(28)が19日のアウェー、ベローナ戦で... 政治,渕経済産業相が関連する政治団体の資金処理問題で、最も不透明と指摘されて... Go言語,編集者とこの本を5000部売れたらなという話をしたのをなんとなく覚えている。... …以降は省略している。
ソースコード mecab.go (gist) text.go (gist) 動かしてみる $./text data.csv > data $cat data スポーツ 2:1.000000 スルー:1.000000 本田:1.000000 セリエA:1.000000 アルゼンチン:1.000000... 政治 円:1.000000 なる:1.000000 者:1.000000 向け:1.000000 会:1.000000 収支:1.000000... Go言語 処理:1.000000 ため:1.000000 Go:1.000000 編集:1.000000 5000:1.000000... …以降は省略している。これで、dataファイルに素性ベクトルが書き込まれる。 次に分類器を学習する。
$./adagrad -f data -m learn -w model できあがったモデルの中身を見てみる。
$cat model|grep "^スポーツ"|sort -k3 -nr|head スポーツ カルロス・テベス 0.
論文はこちら。
Adaptive Subgradient Methods for Online Learning and Stochastic Optimization
ソースコードはこちら。 多値分類問題にも対応できるようにした。二値分類問題と比べてヒンジ損失が少し変わる(ので重みの更新も二値分類の場合とと少し違う)。
データを次のように作成。
$perl -MList::Util=shuffle -e 'print shuffle(<>)' < ../data/news20.binary > news $head -15000 news > news.train $tail -4996 news > news.test 例えばこのデータは素性の値が0.04くらいなので、その平均を取ると0.01よりも小さくなるため、式(24)中の右辺の第三項が0になり、ほとんどすべての重みが0になってしまう。 正則化項の重み(c)をもう少し小さくしてやると、次の結果になった(本当は論文のように交差検定をして決めてやったほうが良いけど、人手でチューニング)。
$./adagrad -f news.train -m learn -w model -l 1 -c 0.01 $./adagrad -f news.test -m test -w model -l 1 -c 0.01 Recall[-1]: 0.011142 (28/2513) Prec[-1]: 0.848485 (28/33) -- Recall[+1]: 0.997986 (2478/2483) Prec[+1]: 0.499295 (2478/4963) -- Acc: 0.
論文はこちら。
Online Passive-Aggressive Algorithms
ソースコードはこちら。 下の関数でおこなわれている重みの更新以外はほとんどパーセプトロンと一緒です。
func (p *PassiveAggressive) Update(X map[string]float64, y string, sign float64) Weight { loss := math.Max(0, 1-sign*Dot(X, p.weight[y])) // tau := loss / Norm(X) // PA tau := loss / (Norm(X) + 1 / (2 * p.C)) // PA-II if _, ok := p.weight[y]; ok == false { p.weight[y] = map[string]float64{} } for f, _ := range X { if _, ok := p.weight[y][f]; ok { p.
流行りに乗り遅れてGo言語始めました。ので、試しにパーセプトロンを書いてみました。 ソースコードはこちら。
素性ベクトルのフォーマットは<数値>:<数値> である必要はなくて、<文字列>:<数値> でも読み込めるようにしました。 また、ラベルの値も数値である必要はなくて、例えば以下のように「food」とか、「sports」というラベルも扱えるようにしています。 多値分類もできます。
sports soccer:1 baseball:1 food beef:1 pork:1 今回はLIBSVM Data: Classification, Regression, and Multi-labelで公開されている二値分類用データを使って動かしてみました。
$go build $./perceptron -f=../data/a1a -m=learn -w=model -l=10 $./perceptron -f=../data/a1a.t -m=test -w=model Acc: 0.8257203773097299 -fオプションで素性ベクトルのファイルを指定して、-mオプションで学習(learn)、テスト(test)のどちらかを指定して-lオプションでループ回数(デフォルトは10)を指定して、-wオプションで学習結果を保存するファイルを指定します。 テストする時は、-mオプションでtestを指定して、-fオプションでテストデータを指定してやれば予測します。-vオプションをつけると、各事例に対する予測ラベルを出力します。
このデータは、
$grep "^+1" ../data/a1a.t|wc -l 7446 $grep "^-1" ../data/a1a.t|wc -l 23510 とラベルの偏りがあり、すべての事例のラベルを-1と答えたらaccuracyは0.76程度なので、一応学習できているようです。
confusion matrixを書く元気は残っていなかったのでaccuracyしか出力しません・・・。 出力するようにしました。 (2014/09/17追記)
「高速文字列解析の世界」を一旦通読したので、実際に手を動かしてみた。 Induced Sortingは効率的に接尾辞配列を構築するアルゴリズム。 詳細はこの本を始め、下の参考にあるエントリなどが個人的に参考になった。
GitHubにコードを上げた (sais.py)。
参考 Suffix Array を作る - SA-IS の実装 https://github.com/beam2d/sara SA-IS: SuffixArray線形構築 実装時にはやはり元の論文を読まないとよくわからなかった。
Two Efficient Algorithms for Linear Time Suffix Array Construction