遅い→起動時

http://d.hatena.ne.jp/pmint/

ゼロから作る単語辞書 (0)

文章間の共通点を集めて、日本語の文章から単語抽出。
diffで得た共通点とその出現数を元にして、多数の文章に現れる文字列ほど単語として使える文字列ということにしてみる。

  1. テキストを2つ用意
  2. diff
  3. 共通点を記録
  4. 同じ共通点が見つかるたびに出現数+1
  5. 出現数を参考に共通点を評価
  6. 評価の高い共通点を「単語」と称して出力
コード(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 @unmodified;
        my $store = sub {
            $worddict{join '', @unmodified}++;
            @unmodified = ();
        };
        
        foreach my $elem (@$sdiff){
            given ($elem->[0]){
                when ('u'){
                    die unless $elem->[1] eq $elem->[2];
                    push @unmodified, $elem->[1];
                }
                default {
                    $store->() if (@unmodified);
                }
            }
        }
        $store->() if (@unmodified);
    }
    
    $sentencedict{$sentence} = 0;
}
結果

このコードに手近にあった文章リストをかけると…

#: word, score
1: 忍たま, 1782272
2: 中心, 866761
3: 忍たま乱太郎, 108045
4: す。, 35721
5: 五年生, 30258
6: です。, 20808
7: 年生, 13456
8: サークル, 8748
9: ます。, 8712
10: です, 8100
11: たま, 7744
12: たま乱太郎, 7056
13: ほのぼの, 6348
14: 乱太郎, 4802
15: 五年, 3136
16: 落第忍者乱太郎, 2646
17: ギャグ, 2450
18: 三郎, 2116
19: 中心で, 2048
20: サークルです。, 1944
21: 中心です, 1728
22: 中心に, 1682
23: 鉢屋三郎×不破雷蔵, 1568
24: ます, 1521
25: 忍たま , 1323
26: 漫画, 1296
27: 受け, 1296
28: 中心です。, 1156
29: 落乱, 729
30: 中心。, 648
31: オールキャラ, 605
32: 年生中心, 588
33: 竹谷, 576
34: 六年, 529
35: 食満, 441
36: サークルです, 320
37: 鉢雷, 289
38: 善法寺伊作, 256
39: 五年生中心, 196
40: ています。, 196
41: タソガレドキ, 180
42: 小説, 169
43: ています, 147
44: して, 144
45: サークルで, 144
46: 生中心, 128
47: もあり, 128
48: 中心サークル, 125
49: を中心に, 108
50: 新刊, 100
51: など, 100
52: 活動しています, 96
53: こへ, 81
54: ×食満留三郎, 80
55: ります。, 75

……(続く)……

2012-10-12.txt


…などといった出力になる。
全くの無駄ではないけど、もう一つ別の方法が必要みたい。


それとデータ量が区切り位置の精度を上げるので、速さは必要か。

利用価値

これは日本語のすべてを対象にするよりも、固有名詞を抽出したい。
で、真面目なコーパスには不得意なスラングを、何かライフログ的なもののタグ候補としてリスト表示するとか、
2つのテキストの類似度を文体ではなく話題で判定するとか。