「1文あたり最長の1単語までしか検出しないようにしたら精度上がるんじゃないかな!?」と思って試してみた
d:id:pmint:20121012:p1の続き。
コード(Perl)
use utf8; use strict; use feature qw/switch/; use Encode; use Algorithm::Diff qw/sdiff/; my @in = qw{ ※ここに文章を書く ここに文章を書く ここに文章を書く ここに文章を書く }; my %worddict; my %sentencedict; my $c; foreach (@in){ print STDERR "\r", ++$c, '/'.@in; learn($_); } print STDERR " done.\n\n"; { # 評価 my %score; foreach my $k (keys %worddict){ $score{$k} = ($worddict{$k} ** 2) * (length($k) - 1); } # 出力 my $c; print "#: word, score\n"; foreach my $k (sort { $score{$b} <=> $score{$a} } keys %score){ print ++$c, ': ', encode('shiftjis', $k), ", $score{$k}\n"; } } sub learn { my($sentence) = @_; die unless not ref $sentence; foreach my $sentence2 (keys %sentencedict){ # diff my $sdiff = sdiff([split //, $sentence], [split //, $sentence2]); my @words; my @unmodified; my $push = sub { push @words, join('', @unmodified); @unmodified = (); }; foreach my $elem (@$sdiff){ given ($elem->[0]){ when ('u'){ die unless $elem->[1] eq $elem->[2]; push @unmodified, $elem->[1]; } default { $push->() if (@unmodified); } } } $push->() if (@unmodified); { # store my($longest_word) = sort { length $b <=> length $a } @words; $worddict{$longest_word}++; } } $sentencedict{$sentence} = 0; }
結果
#: word, score 1: 忍たま, 1482642 2: 中心, 229441 3: 忍たま乱太郎, 92480 4: サークル, 8112 5: です。, 7442 6: 五年生, 6962 7: たま乱太郎, 6724 8: ほのぼの, 4800 9: たま, 4356 10: す。, 2916 11: 落第忍者乱太郎, 2646 12: 年生, 2209 13: 乱太郎, 2048 14: サークルです。, 1944 15: です, 1849 16: 中心です, 1728 17: ます。, 1682 18: 鉢屋三郎×不破雷蔵, 1568 19: 忍たま , 1323 20: 中心です。, 900 21: 三郎, 841 22: 中心に, 722 23: ギャグ, 722 24: オールキャラ, 605 25: 年生中心, 432 26: 中心で, 392 27: 中心。, 392 28: 漫画, 324 29: サークルです, 320 30: 落乱, 289 31: 食満, 196 32: 五年生中心, 196 33: ています, 147 34: 五年, 144 35: サークルで, 144 36: ています。, 144 37: タソガレドキ, 125 38: 六年, 121 39: 活動しています, 96 40: 竹谷, 81 41: ×食満留三郎, 80 42: てます。, 75 43: を中心に, 75 44: 食満留三郎, 64 45: こへ, 64 46: 鉢雷, 64 47: で活動しています, 63 48: 心です, 50 49: ります。, 48 50: 、五年生, 48 51: もあります。, 45 52: 善法寺伊作, 36 53: 小説, 36 54: もあります, 36 55: 雷蔵, 36 ……(続く)……
…あんま変わってねえ('A`)
問題点
diffのアルゴリズム上、同じ文字が複数あるととにかく先に出現するもの同士を対応付けようとする。
入力文1: 落第忍者乱太郎/忍たま乱太郎 入力文2: 忍たま乱太郎 ↓ [対応付け] 落第忍者乱太郎/忍たま乱太郎 忍 たま乱太郎 [こうなって欲しい] 落第忍者乱太郎/忍たま乱太郎 忍たま乱太郎
上記の「たま乱太郎」なんかがその結果で「落第忍者乱太郎」の後に「忍たま乱太郎」があると「忍」の対応付けがおかしくなってしまう。
「早く出現した者勝ち」ではなく、「共通部分が連続するような対応付け」ができないと「たま乱太郎」は無くならない。「忍たま乱太郎」のスコアも加算されない。
あとは遅いので入力できるデータ量も限られること。今のところ入力された文から2つ取り出す組み合わせを全てdiffにかけているので、uni-gram→文の辞書を作れば見込みのない文の組み合わせを省けそう。実際は文末の「。」や「です」「ます」の「す」があるからほぼ省かれないんだけど。