nekoneko_genで20newsgroupを試してみた
文書分類では、20newsgroupsというデータセットがよく使われるようなので、英語テキストの対応をしながら試してみました。
http://people.csail.mit.edu/jrennie/20Newsgroups/
これは20種類のニュースグループに投稿された約2万件のドキュメントを含むデータセットです(学習用が1.1万件、確認用が7.5千件だった)。
ニュースグループというのは、メーリングリストで2ちゃんねるをやっている感じのものだと思います。
20種類の板に投稿されたレスをどの板の投稿か判定するマシンを学習する感じ。
(注意: ここに書かれている作業用のコードはRuby1.9系でしか動きません)
最新のnekoneko_genにアップデート
まず
gem update nekoneko_gen
とアップデートします。
これを書いている時点の最新は0.4.0です。
入っていない場合は、
gem install nekoneko_gen
でインストールされます。
データの準備
サイトを見ると何種類かありますけど、20news-bydate.tar.gz を使います。
% wget http://people.csail.mit.edu/jrennie/20Newsgroups/20news-bydate.tar.gz % tar -xzvf 20news-bydate.tar.gz % ls 20news-bydate-test 20news-bydate-train
train用とtest用に分かれているらしいので、trainで学習して、testで確認します。
構造を見よう。
% ls 20news-bydate-train alt.atheism comp.os.ms-windows.misc comp.sys.mac.hardware misc.forsale rec.motorcycles rec.sport.hockey sci.electronics sci.space talk.politics.guns talk.politics.misc comp.graphics comp.sys.ibm.pc.hardware comp.windows.x rec.autos rec.sport.baseball sci.crypt sci.med soc.religion.christian talk.politics.mideast talk.religion.misc % ls 20news-bydate-train/comp.os.ms-windows.misc 10000 9141 9159 9450 9468 9486 9506
20news-bydate-trainと20news-bydate-testの下に各カテゴリのディレクトリがあって、各カテゴリのディレクトリにドキュメントがファイルに分かれて入っているようです。
nekoneko_genは、1ファイル1カテゴリ1行1データの入力フォーマットなので、まずこんなスクリプトで変換します。
# coding: utf-8 # 20news-conv.rb require 'fileutils' require 'kconv' src = ARGV.shift dest = ARGV.shift unless (src && dest) warn "20news-conv.rb srcdir destdir\n" exit(-1) end FileUtils.mkdir_p(dest) data = Hash.new # 元データの各ファイルについて Dir.glob("#{src}/*/*").each do |file| if (File.file?(file)) # root/category/nに分解 root, category, n = file.split('/')[-3 .. -1] if (root && category && n) data[category] ||= [] # ファイルの内容を改行をスペースに置き換えて(1行にして)カテゴリのデータに追加 data[category] << NKF::nkf("-w", File.read(file)).gsub(/[\r\n]+/, ' ') end end end # 出力側で data.each do |k,v| # カテゴリ名.txtのファイルにデータを行単位で吐く path = File.join(dest, "#{k}.txt") File.open(path, "w") do |f| f.write v.join("\n") end end
train、testというディレクトリに変換。
% ruby 20news-conv.rb 20news-bydate-train train % ruby 20news-conv.rb 20news-bydate-test test % % ls test alt.atheism.txt comp.sys.ibm.pc.hardware.txt misc.forsale.txt rec.sport.baseball.txt sci.electronics.txt soc.religion.christian.txt talk.politics.misc.txt comp.graphics.txt comp.sys.mac.hardware.txt rec.autos.txt rec.sport.hockey.txt sci.med.txt talk.politics.guns.txt talk.religion.misc.txt comp.os.ms-windows.misc.txt comp.windows.x.txt rec.motorcycles.txt sci.crypt.txt sci.space.txt talk.politics.mideast.txt % head alt.atheism.txt
できてる。
学習
1コマンドです。ここまでの作業のことは忘れましょう。分類器の名前はnews20にしました。
trainの下を全部指定します。
% nekoneko_gen -n news20 train/*
ちょっと時間かかります。
% nekoneko_gen -n news20 train/* loading train/alt.atheism.txt... 11.2039s loading train/comp.graphics.txt... 10.0659s loading train/comp.os.ms-windows.misc.txt... 24.7611s loading train/comp.sys.ibm.pc.hardware.txt... 9.1767s loading train/comp.sys.mac.hardware.txt... 8.3413s loading train/comp.windows.x.txt... 13.9806s loading train/misc.forsale.txt... 6.8255s loading train/rec.autos.txt... 9.9041s loading train/rec.motorcycles.txt... 9.4798s loading train/rec.sport.baseball.txt... 9.9481s loading train/rec.sport.hockey.txt... 14.2056s loading train/sci.crypt.txt... 19.5707s loading train/sci.electronics.txt... 9.6204s loading train/sci.med.txt... 13.6632s loading train/sci.space.txt... 14.4867s loading train/soc.religion.christian.txt... 16.4918s loading train/talk.politics.guns.txt... 16.2433s loading train/talk.politics.mideast.txt... 21.8133s loading train/talk.politics.misc.txt... 16.2976s loading train/talk.religion.misc.txt... 10.4111s step 0... 0.953548, 58.1906s step 1... 0.970537, 47.1082s step 2... 0.980550, 41.9248s step 3... 0.985889, 37.6781s step 4... 0.989483, 35.0408s step 5... 0.991824, 33.8357s step 6... 0.993727, 30.1385s step 7... 0.995139, 29.5926s step 8... 0.996107, 29.3976s step 9... 0.997182, 27.9107s step 10... 0.997546, 27.1800s step 11... 0.998004, 26.4783s step 12... 0.998581, 26.7023s step 13... 0.998985, 25.9511s step 14... 0.999145, 24.7697s step 15... 0.999324, 24.7991s step 16... 0.999430, 24.8879s step 17... 0.999569, 24.7246s step 18... 0.999622, 25.2175s step 19... 0.999615, 23.5225s ALT_ATHEISM : 153334 features COMP_GRAPHICS : 153334 features COMP_OS_MS_WINDOWS_MISC : 153334 features COMP_SYS_IBM_PC_HARDWARE : 153334 features COMP_SYS_MAC_HARDWARE : 153334 features COMP_WINDOWS_X : 153334 features MISC_FORSALE : 153334 features REC_AUTOS : 153334 features REC_MOTORCYCLES : 153334 features REC_SPORT_BASEBALL : 153334 features REC_SPORT_HOCKEY : 153334 features SCI_CRYPT : 153334 features SCI_ELECTRONICS : 153334 features SCI_MED : 153334 features SCI_SPACE : 153334 features SOC_RELIGION_CHRISTIAN : 153334 features TALK_POLITICS_GUNS : 153334 features TALK_POLITICS_MIDEAST : 153334 features TALK_POLITICS_MISC : 153334 features TALK_RELIGION_MISC : 153334 features done nyan!
終わったらnews20.rbというRubyのライブラリが生成されています。
% ls -la news20.rb -rw-r--r-- 1 ore users 66599221 2012-06-02 17:10 news20.rb
60MB以上あります。デカい。
確認
20カテゴリもあって前回のスクリプトで1カテゴリずつ見るのはきついので、一気に確認するスクリプトを書きました。
# coding: utf-8 # test.rb # 分類器を読み込む require './news20' # ファイル名をnekoneko_genが返すラベル名に変換する関数 def label_name(file) File.basename(file, ".txt").gsub(/[\.\-]/, "_").upcase end count = 0 correct = 0 # 指定された各ファイルについて ARGV.each do |file| # ファイル名からラベル名を得る name = label_name(file) # ラベル名から正解ラベル(定数)に変換 # (News20::LABELSにラベル番号順のラベル名があるので添え字位置を探す) correct_label = News20::LABELS.each_with_index.select{|v,i| v == name}.flatten.pop file_count = 0 file_correct = 0 # ファイルの各行データについて File.read(file).lines do |l| # 予測 label = News20.predict(l) # ラベルが一致していたら if (label == correct_label) # 正解!! file_correct += 1 end # データ数 file_count += 1 end correct += file_correct count += file_count # ファイルの内での正解率を表示 printf("%26s: %f\n", name, file_correct.to_f / file_count.to_f) end # 全体の正解率を表示 printf("\nAccuracy: %f\n", correct.to_f / count.to_f)
testの下を全部指定します。
% ruby test.rb test/* ALT_ATHEISM: 0.789969 COMP_GRAPHICS: 0.825193 COMP_OS_MS_WINDOWS_MISC: 0.753807 COMP_SYS_IBM_PC_HARDWARE: 0.778061 COMP_SYS_MAC_HARDWARE: 0.867532 COMP_WINDOWS_X: 0.815190 MISC_FORSALE: 0.902564 REC_AUTOS: 0.916667 REC_MOTORCYCLES: 0.969849 REC_SPORT_BASEBALL: 0.957179 REC_SPORT_HOCKEY: 0.984962 SCI_CRYPT: 0.952020 SCI_ELECTRONICS: 0.778626 SCI_MED: 0.881313 SCI_SPACE: 0.936548 SOC_RELIGION_CHRISTIAN: 0.937186 TALK_POLITICS_GUNS: 0.934066 TALK_POLITICS_MIDEAST: 0.914894 TALK_POLITICS_MISC: 0.616129 TALK_RELIGION_MISC: 0.677291 Accuracy: 0.866171
86.6%でした。