パーセプトロンを実装してみた
実装力を磨くためと学習器への理解を深めるために、パーセプトロンを実装してみた。3時間ぐらいかかった。今のレベルはSVMの赤本に行く前ぐらいのレベル。
コードは以下にある。以下で参考にしたチュートリアルの擬似コードをそのまま実装した。
https://github.com/akkikiki/nlp_tutorial/blob/master/train_perceptron.py
以下のチュートリアルを参考にした。詳しい事はこちらに書いてあるが、概要を述べてみる。
パーセプトロンアルゴリズムと文書分類
ちなみに、自分は昨年の春ぐらいにPRML4章(パーセプトロン含む)を輪読会で発表したのだが、完全に忘れていたうえ、読んだ時も機械学習の全体像(識別関数、生成モデル、識別モデルから成る)が掴めていなかったので、いきなりPRMLを読むのはオススメしない。
今PRML4.1.7節を見たら「すごい、わかりやすい!」と思うけど、直前のフィッシャーの識別関数あたりで全体力を消費して、命からがら、パーセプトロンを読んだ覚えがあるので、全然わからなかった。
以下パーセプトロンの概要である。
オンライン学習器である
すなわち、一つの学習事例に対して、重みを更新していく
更新式は
ηの値は「更新時にどのくらいの大きさで、重みを更新するか」である。ちなみにパーセプトロンは収束定理があり、対象データが線形分離可能ならば、どんな学習率でも収束が保証されているため*1、学習率は大抵1である。自分のコード(チュートリアル)でもそうした。
識別結果yは-1か1である
この制限により、学習データと比較した時に識別結果が間違っていた場合、重みが識別結果の符号に引っ張られる。イメージとしてはPRML、図4.7a(http://research.microsoft.com/en-us/um/people/cmbishop/PRML/prmlfigs-jpg/Figure4.7a.jpg)である。黒い矢印がwで赤い矢印で、緑色の丸に囲まれた点が、誤って識別されたため、点(赤いベクトル)の方へ境界を引っ張る。
識別関数である
echizen_tmさんのブログを読んでいて、気付いた。確率ないのは面倒でなくイイネ!
以下雑記
http://gihyo.jp/dev/serial/01/machine-learning/0017はnumpyを使ってパーセプトロンを実装しているので、今度やってみる。
- 最大マージン化
- カーネル関数
をパーセプトロンに導入した学習器である。Sequential Minimal Optimization(SMO)等により高次元のデータに対しても学習が早い、とかの特徴がある。
自分の実装で気を付けるべき、と思った点も述べてみる。
- 疑似コードから書くこと
- 全体像(大枠)を書き、詳しい処理は適当な関数の名前を付けて、後で詳細を書く。
当たり前のことだけど、複雑なアルゴリズムほど脳内だけでは処理仕切れなくなる。そして、つまずき、実装を諦める、と言った場合が自分の経験上多い。
疑似コードを書いておくと「ここ何を処理したいんだっけ?」と詰まった場合でも、確認して前に進める。