HaskellとMeCabで長門(その3) : Complement Naive Bayesもやってみた

結局やろうやろうおもいつつ全然やってなかったの続き。

今回は学習時の文書量に差があるときに効果を発揮するというComplement Naive Bayesを実装してみました。

どんなの

調べると、
新はてなブックマークでも使われてるComplement Naive Bayesを解説するよ - 射撃しつつ前転
をみつけました。

  1. そのクラスに属さない文書を使って学習
  2. そのクラスに属さない確率を計算
  3. その確率が一番低いクラスに分類

という、ほぼすべてをひっくり返した方法らしいです。これにより、学習時に文書量の多かったクラスにたくさんの単語が含まれていることにより、全体的な確率にばらつきが出てしまうことが防げるらしいです。

というわけで既存の分類器をあまりいじらずに出来ました。

どうだったの

学習元の文章自体少ないのですが、

と、かなり量がバラけています。
これは効果が期待できるのかな、と思ったけど殆ど変わりませんでした。具体的には以下から。
一応前回と同じ文章を使っています。上に表示されている結果はこれまでの普通のナイーブベイズで、下がComplement Naive Bayesです。
f:id:haru2036:20140120210025p:plain

f:id:haru2036:20140120210042p:plain

f:id:haru2036:20140120210054p:plain

f:id:haru2036:20140120210107p:plain

結局元から判別が難しいと思っていた艦これと戦艦はやっぱり無理でした。そして、長門有希に関しても"戦艦"の1語が入っていたために艦これと勘違いされています……これテーマ間違ったな。

まとめ

そもそも戦艦長門長門有希の時点でも結構テーマとしてもアレだったけどそれに人間でも紛らわしい艦これを突っ込んでしまったがためにかなりグダグダに。一応他のことにも使えるからいいか……

ソースはgithubにあります。実装もめっちゃグダグダですが……
haru2036/nagato · GitHub

次は何をしよう……

HaskellとMeCabで長門(その2)

精度改善のために

とりあえずMeCabの出力を使って品詞が名詞である単語のみをフィルタした状態で訓練するように修正しました。

結果

まず全エントリの3つの文を。
f:id:haru2036:20140111020759p:plain
f:id:haru2036:20140111020807p:plain
f:id:haru2036:20140111020812p:plain

結果としては残念なことに全部艦これになってる……

考察

長門有希の文章に関しては、「戦艦と間違われやすそうなやつ」の「戦艦」の1語の影響で、他の2つのクラスの尤度が上がってしまったことが原因だと思います。
ふつうの戦艦に関しては、そもそもが艦これの方の説明文と同じような単語がたくさん出てくるのでそもそも判別が難しいのではないかと。

まとめ

実を言うと他の文章に関してもそれなりに試したものの、ちゃんとデータをとってなかったので暇な時にいろいろ試してみようと思ってます。
ただ、個人的な感触(含プラシーボ)としては、何故か長門有希に間違われまくっていた文章が正常に艦これだったり戦艦だったりになるようにはなったイメージです。

ちょっと残念だったこと

HaskellはMaybeとかそこら辺の"失敗を明示的に表現する"(個人的なイメージ、間違ってたらおしえて)型があるにも関わらずList操作関連のheadやら!!やらで空リストだったりそのインデックスが対象のListになかったりするとExceptionが発生するの、非常に残念だと思いました。(もっといい方法あるかもしれないけどそのせいでわざわざif使ってチェックしてしまった)

HaskellとMecabで長門に関してのテキストをを判別してみた

前々からちょこちょこやっていたのがやっと一応の完成を見ました。

なにこれ

戦艦長門長門有希と戦艦長門(艦これ)についての文章を判別することを目的にナイーブベイズな分類器をHaskell+MeCabで実装したやつです。

中身

言語処理のための機械学習入門 (自然言語処理シリーズ)

言語処理のための機械学習入門 (自然言語処理シリーズ)

この本読みながら実装しました。一応この本で言う117ページとかそこら辺の多項モデルでMAP推定な感じです

動作

Windowsコマンドプロンプト文字化けしたので外部ファイルから読み込むようになりましたけど……
一応全部学習用のデータとは別のテキストを放り込みました。
f:id:haru2036:20140104212307p:plain
(艦これの長門)
f:id:haru2036:20140104212316p:plain
(長門有希)
f:id:haru2036:20140104212319p:plain
(戦艦長門、結果が間違って長門有希になってるけど)

まとめ

なんか最後の戦艦長門だけ何故か艦これじゃなくて長門有希に間違われてるけど他にもいろいろ放り込んだ分にはあらかたイケてる印象、これほんとに全部のアイテムを対象にやっちゃってるけど正規化とかしたらもっといい感じになりそう

追記:
リポジトリ
haru2036/nagato · GitHub

進捗どうですか

この記事は 進捗 Advent Calendar の16日目の記事です。

全体の進捗 → すすんだりもどったり

一歩進んで二歩下がる、という状況ですね、詳細は次から。

体調 → 予想がつかない

まあ波があります。いろいろ周りに迷惑かけてしまったなあと思うこともしばしばでした。

プログラム書いたり → そこそこ?

僕は去年一年間サイボウズ・ラボユース(実は9日めのuchanさんと同期)で自然言語処理について(それまで何も知らなかったものでさわりだけになってしまいましたが)勉強させてもらったのですが先の体調などで今年はあまりガリガリやれなかったなあと思っています。最近はHaskellClojureなどの関数型言語を触っていて、とりあえずラボユースの成果物をHaskellに移植するのを目標にやっています。自然言語処理関係の学習をそっちの言語でももっと進められたら嬉しいなとか。あ、昨日すごいH本とどきました。

趣味 → それなり

まあプログラム書くこと自体も趣味なのですが、それ以外の趣味について。
DTMとか色々やってるのはだらだら続けててあんまり上達しないなあ、と。
ドール/神姫沼的には着実に進んでます。キャッキャウフフ楽しい!!!!!!L('ω')┘三└('ω')」

学業 → ダメです

進捗(進級)ダメです。体調が悪くて休みがちになってしまった影響で今は休学中なのですが、来年復学してからこそ進級したい……

人生 → いろいろ足りない

進捗ダメです。いろいろやりたいことは大量に貯まっていくもののそれを処理する精神的/時間的/金銭的リソースがなくて止まってます。勉強も趣味も両方のリソースが足りるようにしたい……

これから?

これからどうしましょう、やりたいことはあるのでリソースを有効に使いつつやってくのがいいんでしょうか。

明日は @keiji_ariyama さんです。進捗どうですか?

なんかClojureも触りだした

( ^o^)なんか最近関数型はやってる!
( ˘⊖˘) 。o(待てよ?関数型って一体何だ?)
|Twitter|┗(☋` )┓三
( ◠‿◠ )☛ClojureというLisp方言があってな
関数型って何か理解したいならHaskellもいいよ!☚( ◠‿◠ )
( ◠‿◠ )☛▂▅▇█▓▒░(((((( ◠‿◠ ))))))░▒▓█▇▅▂☚( ◠‿◠ )
           うわああああああ

結果的にこうなりました。俺氏在籍中大学の箱P氏(@If_I_were_boxp)にClojure布教されたほうが先立ったのに後になってしまい申し訳ない……

というわけで箱P氏のTwitterクライアントであるGrimoireをいじりつつHaskellもなんか触りつつとりあえず当分過ごそうと思います。

Haskell触ってみる(2)

というわけで結構ヤバいのではと思いつつ触ってます。

正直言って寝起きなので変なこと書きまくってるかもしれない。
リポジトリはここでやってるのでツッコミをいただけるとありがたかったり。
haru2036/learnHaskell · GitHub
なんとかそれぞれの要素に対しての出現頻度を数えることができるようになりました。
ただなんか実行結果がfromListって関数が帰ってきてるようにしか見えないのでなんか違う感があったりする。

ソース:

import Data.List
import Data.HashMap.Lazy

searchAndCountWords :: String -> [String] -> Int
getUnigramFrequency :: [String] -> HashMap String Int

getUnigramFrequency sList = fromList [(a, searchAndCountWords a sList) | a <- nub sList]

searchAndCountWords key items = length $ Data.List.filter (==key) items

main = return $ getUnigramFrequency ["a", "a", "ba", "bb", "ab", "a"]

実行結果:

fromList [("bb",1),("ba",1),("ab",1),("a",3)]

HashMap使うためにはパッケージ追加でインストールしないといけないのねとか。
あと、Data.HashMap.LazyとData.HashMap.Strictってどっち使えばいいのかわからないし英語読めないので辛いし英語も勉強しないとヤバいのではってなってる