scalaでテキスト分類してみた
Scala勉強会第143回 SPECIAL DAY ハッカソン in 歌舞伎座に遊びに行くことにしたので、その前にscalaの練習がてらnakを使ってみた。
nakとは?
ScalaNLPの仲間で、機械学習ライブラリ。 sbtで、
libraryDependencies ++= Seq( "org.scalanlp" % "breeze_2.10" % "0.7", "org.scalanlp" % "breeze-natives_2.10" % "0.7", "org.scalanlp" % "nak" % "1.2.1" )
すればbreezeと一緒に入る。
テキスト分類
ここのExample通りにやれば、テキストを分類できる。 今回はこのExampleを使って、"なでしこ"と"ひまわり"のソースコードを分類してみた。 なお、今回用いた"なでしこ"と"ひまわり"はどちらも日本語プログラミング言語*1で、wikiを見ると、
"ひまわり"は、
ひまわりはスクリプト型プログラミング言語の一つ。動作可能なOSは、Microsoft Windows 98/Me/2000/XP。
とある。 Hello Worldはそれぞれ、
「Welcome to Nadesiko.」と表示。
「ひまわりへようこそ」と、表示。
というかんじらしい。python2系と3系みたいなかんじだろうか。
結果
分類した結果は以下。
-------------------------------------------------------------------------------- Confusion matrix. Columns give predicted counts. Rows give gold counts. -------------------------------------------------------------------------------- 5 1 | 6 himawari 2 4 | 6 nadeshiko ---------------- 7 5 himawari nadeshiko -------------------------------------------------------------------------------- 75.00 Overall accuracy -------------------------------------------------------------------------------- P R F 71.43 83.33 76.92 himawari 80.00 66.67 72.73 nadeshiko ................................... 75.71 75.00 74.83 Average
サンプル少ないけど、F値を見ると判定できてる感がある。とりあえず、日本語が入っていても分類できそうなかんじなので、いろいろ応用が効きそう。
ソース
なお、ソースはこんなかんじ。(stopwordsの使い方わからん...)
package nak.example import nak.data._ import nak.NakContext._ import nak.NakContext.trainClassifier import nak.liblinear.LiblinearConfig import nak.util.ConfusionMatrix import java.io.File object analyze { def main(args: Array[String]) { classifyFile("/xxxx/") } def classifyFile(path:String) = { val groupsDir = new File(path) implicit val isoCodec = scala.io.Codec("ISO-8859-1") val stopwords = Set("は","の","から","に","を","まで","へ","が") val trainDir = new File(groupsDir, "train") val trainingExamples = fromLabeledDirs(trainDir).toList val config = LiblinearConfig(cost=5.0) val featurizer = new BowFeaturizer(stopwords) // 分類器の作成 val classifier = trainClassifier(config, featurizer, trainingExamples) val evalDir = new File(groupsDir, "test") val maxLabelNews = maxLabel(classifier.labels) _ // テストデータと比較 val comparisons = for (ex <- fromLabeledDirs(evalDir).toList) yield (ex.label, maxLabelNews(classifier.evalRaw(ex.features)), ex.features) val (goldLabels, predictions, inputs) = comparisons.unzip3 // 整形して出力 println(ConfusionMatrix(goldLabels, predictions, inputs)) }
面白そうなので、もう少しいじってみようと思う。
*1:なんか畳語っぽい