自然言語の重複データを検出したかったのです。
CPANだとText::Levenshtein、Text::WagnerFischer、Text::Brewあたり。
でも遅いよ。
1対1でしか比較できないんで、重複してる可能性のあるデータが3件以上だと扱いに困る。というか、あきらめた。
Rubyだと標準でPermutationが入ったから楽な気がする。まあCPAN漁ればすぐ見つかるけど。
でも処理量が可及的速やかに増大するのでちょっと悩むところ。無視をしても明らかに遅いのに。
事前にURL消したりHTMLタグ消したり改行文字と空白文字消すとかしといたほうがよさげ。
編集距離出して、全体の何%が編集されたか出して、それを閾値にして、という。
めどい。
なんか魔法の関数はないんですかね。
結論:自然言語を使うのをあきらめたい。
こんな感じか。なんつーかコードに締まりがないが。
use strict; use warnings; use utf8; use Encode qw(decode encode); use Text::WagnerFischer qw(); use DBI; my $http_pat = qr/s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+/; sub db_connect { return DBI->connect('DBI:mysql:foo:bar', 'foo', 'bar') or die "can't connect"; } sub getdata { my $id = shift; my $dbh = db_connect(); my $sth = $dbh->prepare("select id, content from data"); my $rv = $sth->execute(); my %x = (); while (my @data = $sth->fetchrow_array()) { $x{$data[0]} = decode("eucjp", $data[1]); } $sth->finish; $dbh->disconnect; return %x; } sub strip { my $x = shift; $x = strip_html($x) if $x; $x = strip_ex_url($x) if $x; $x = strip_cr($x)if $x; return $x; } sub strip_html { my $x = shift; $x =~ s/<.+?>//sg; return $x; } sub strip_ex_url { my $x = shift; my $ret = ''; for my $y (split /\n/, $x) { if (my @http = $y =~ m/$http_pat/g) { $ret .= $http[0] . "\n"; } else { $ret .= $y ."\n"; } } return $ret; } sub strip_cr { my $x = shift; $x =~ s/[\n ]//g; return $x; } my %data = getdata(); #DBから読んでくる my %group = (); # 言及しているURLでグルーピング while (my ($key, $value) = each %data) { if (my($http,) = ($value =~ m/$http_pat/g)) { $group{$http} = [] unless exists $group{$http}; push @{$group{$http}}, $key; } } my $threshold = 0.2; while (my($key, $value) = each %group) { if (@$value == 2) { # 似ている可能性がある記事が2個のときだけ比較 my $x1 = $data{$value->[0]}; my $x2 = $data{$value->[1]}; my $distance = Text::WagnerFischer::distance($x1, $x2); if ($distance / length($x1) > $threshold && $distance / length($x2) > $threshold) { print "$value->[0] resemble $value->[1]\n"; } } }
とりあえず気付いたのは、単語の言い換えにものすごく弱い。文字コード・エンコード・文字セット・文字集合の類とか、エンコードと符号化、Canonとキヤノン、Linuxとリナックスとか。ドラッグアンドドロップとDnDとか。
編集距離では普通の人とルー大柴は比較できないということだな。
これで何をするかと言うと、こういう画面があって(左ツリー右テキスト)、左でアイテムをクリックするとその内容が右に出て、重複してるなーと思ったら削除とかやってたんだけど、微妙な差のが多数あったので、カッとなってある程度自動で取捨選択したくなったんよ。少なくとも件数は減ったよ。気付いたけど、割合出すとこ間違ってたよ……。直したよ……。