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ってどっち使えばいいのかわからないし英語読めないので辛いし英語も勉強しないとヤバいのではってなってる

Haskellを触って見る続き

とりあえずさしあたっての目標に前のエントリに書いたようにラボユース成果物(haru2036/laboyouth · GitHub)をHaskellに移植することを設定したので、とりあえずモデルの生成部分からやっていこうと思ってます。まあいきなりtrigramの数え上げやったら死ぬと思ったので、さしあたりunigramの数え上げからやっていこうと思ってます。
そんなこんなでとりあえず一つの単語に付いて何回出現するかを調べる関数を作ったのですが、なんかよくわからんことに。

countUnigram :: String -> [String] -> Int

countUnigram key items = length $ takeWhile (==key) items

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

こんなコードを書いて実行すると

2

とか出てきました。ひとつ足りなくね?と思って検索対象(一つ目の引数)を"ab"にしたところ0と……じゃあ存在しない場合どうするのよと思って"cc"をしても0が帰ってきます、どういうこっちゃ。takeWhileがそういう感じなのかそれとも……

(たぶん)つづきます

    • 追記--

ありがたいことにTwitterですぐツッコミをもらったので。


とのことでtakeWhileをfilterに置き換えたらうまくいきました。
当初参考にしていたページ
Haskell のリスト操作 : tnomuraのブログ
にもtakeWhileとfilter両方乗ってたけどうっかりfilterを見落として書いてしまってたみたいで。
そこをもう一度見たら

条件に合う要素をリストの先頭から取り出す。条件が合わなくなったところで処理は終了する。
Hugs> takeWhile (<4) [1,2,3,4,5]

てて書いてありました。さいしょのa2つの次にbaが入ってたのでそこで終了しちゃってたみたいな。
ありがとうございます!

つづきました