集合知プログラミング 3.3をperl化してみた(はてダ用)
http://d.hatena.ne.jp/rin1024/20090420/1240222617
http://d.hatena.ne.jp/rin1024/20090421/1240317936
ここら辺を、はてダのデータ元にクラスタリングできるように修正してみた。
■ 集合知プログラミング 3.3をperl化してみた(形態素解析+単語数カウント)の方
はてダRSSの記事ごとに取得して、その記事の中での単語の数をカウントして配列で返すように修正。
#!/usr/bin/perl package FeedParser; use LWP::UserAgent; use XML::Simple; sub new { return bless {}, shift; } sub parse { my $self = shift; my $url = shift; my $ua = LWP::UserAgent->new; my $feed = XMLin($ua->simple_request( HTTP::Request->new('GET', $url) )->content); return $feed; } 1; package main; use utf8; use strict; use warnings; use Dumpvalue; use MeCab; my $mecab = MeCab::Tagger->new; my $parser = FeedParser->new; sub getWordCounts { my $url = shift; my @lines; my $id = 1; # parse xml data my $documents = $parser->parse($url); # analysis entry data foreach my $entry(@{$documents->{item}}) { my $summary; if ($entry->{summary}) { $summary = $entry->{summary}; } elsif($entry->{description}) { $summary = $entry->{description}; } else { $summary = $entry->{content}; } # title %{$lines[$id]} = (); $lines[$id]->{'blog_title'} = $entry->{title}; # extract attributes my $node = getWords($summary); for (;$node;$node = $node->{next}) { next unless defined $node->{surface}; my $word = $node->{surface}; my($hinsi, $yomi) = (split( /,/, $node->{feature}))[0,7]; next if defined $yomi && $yomi eq '*'; # add column name if (!defined($lines[0]->{$word}) && $word ne 'blog_title') { $lines[0]->{$word} = 'true'; } # counter unless (defined $lines[$id]->{$word}) { $lines[$id]->{$word} = 0; } $lines[$id]->{$word}++; } $id++; } return \@lines; } sub getWords { my $content = shift; # triming html tags. $content =~ s/\<(.*?)\>//g; # lower case $content = lc($content); # return results. return $mecab->parseToNode($content); } # do execute my($lines) = getWordCounts('http://d.hatena.ne.jp/rin1024/rss'); # show columns my $wc = shift @$lines; print "blog_title", "\t"; foreach my $key(keys(%$wc)) { print $key, "\t"; } print "\n"; foreach my $line(@$lines) { print $line->{'blog_title'}, "\t"; foreach my $key(keys(%$wc)) { my $num = defined $line->{$key} ? $line->{$key} : 0; print $num, "\t"; } print "\n"; } 1;
■ 集合知プログラミング 3.3をperl化してみた(階層化クラスタリング)の方
読み込むテキストを↑のスクリプトで生成したのに変えたくらい。
#!/usr/bin/perl use strict; use Dumpvalue; package Clusters; # this subroutean is get first line that means row names, # and, othe line's first column is each column name. # those data insert big list. # * rownames and colnames useful index keys. sub readfile { my($self, $filename) = @_; # get file data open my $file, '<', $filename; # first line is column titles my @colnames = split('\t', <$file>); my @lines = <$file>; close $file; # set data my @rownames = (); my @data = (); foreach my $line(@lines) { my @p = split('\t', $line); # each line's first column is colum name unshift(@rownames, shift(@p)); # other column is this line's data unshift(@data, \@p); } return \@rownames, \@colnames, \@data; } sub hcluster { # $rows: array reference # $distance: subroutean reference my($self, $rows, $distance) = @_; my $currentclustid = -1; my %distances = (); # Clusters are lines first. my @clust; map { push(@clust, Bicluster->new(vec => $rows->[$_], id => $_)); } (0..$#$rows); while ($#clust > 0) { my @lowestpair = (0,1); my $closest = $distance->($clust[0]->{vec}, $clust[1]->{vec}); # 全ての組をループし、もっとも距離の近い組を探す foreach my $i(0..$#clust) { foreach my $j($i+1..$#clust){ # 距離をキャッシュしてあればそれを使う if (!defined($distances{$clust[$i]->{id}}{$clust[$j]->{id}})) { $distances{$clust[$i]->{id}}{$clust[$j]->{id}} = $distance->($clust[$i]->{vec}, $clust[$j]->{vec}); } my $d = $distances{$clust[$i]->{id}}{$clust[$j]->{id}}; if ($d < $closest) { $closest = $d; @lowestpair = ($i, $j); } } } # 二つのクラスタの平均を計算する my @mergevec = (); foreach my $i(0..$#{$clust[0]->{vec}}) { push(@mergevec, ($clust[$lowestpair[0]]->{vec}->[$i] + $clust[$lowestpair[1]]->{vec}->[$i]) / 2.0); } # 新たなクラスタを作る my $newcluster = Bicluster->new( id => $currentclustid, vec => \@mergevec, left => $clust[$lowestpair[0]], right => $clust[$lowestpair[1]], distance => $closest, ); # 元のセットではないクラスタのIDは負にする $currentclustid = -1; splice(@clust, $lowestpair[1], 1); splice(@clust, $lowestpair[0], 1); push(@clust, $newcluster); } return $clust[0]; } 1; # 階層的なツリーを表現するのに使うこれらのすべてのプロパティを持つBiclusterというクラス package Bicluster; sub new { my($self, %attr) = @_; return bless { id => $attr{id}, vec => $attr{vec}, left => $attr{left}, right => $attr{right}, distance => $attr{distance}, }, $self; } 1; package main; my($blognames, $words, $data) = Clusters->readfile('hated.txt'); my $start = time; my $clust = Clusters->hcluster($data, \&pearson); my $end = time; printclust($clust, $blognames, 0); #Dumpvalue->new->dumpValue($cluster); sub pearson { my($v1, $v2) = @_; my($sum1, $sum2, $sum1Sq, $sum2Sq, $pSum) = (0, 0, 0, 0, 0); map { $sum1 += $_; $sum1Sq += $_ ** 2; } @$v1; map { $sum2 += $_; $sum2Sq += $_ ** 2; } @$v2; map { $pSum += $v1->[$_] * $v2->[$_]; } 0..$#$v1; my $num = $pSum - ($sum1 * $sum2 / scalar(@$v1)); my $den = sqrt(($sum1Sq - $sum1 ** 2 / scalar(@$v1)) * ($sum2Sq - $sum2 ** 2 / scalar(@$v1))); if ($den == 0) { return 0; } return 1.0 - $num / $den; } sub printclust { my($clust, $labels, $n) = @_; # 階層化のレイアウトにするためにインデントする foreach my $i(0..$n) { print " "; } if ($clust->{id} < 0) { # 負のidはこれが枝である事を示している print '-', "\n"; } else { # 正のidはこれが終端だという事を示している if ($labels == undef) { print $clust->{id}, "\n"; } else { print $labels->[$clust->{id}], "\n"; } } # 右と左の枝を表示 if ($clust->{left}) { printclust($clust->{left}, $labels, $n + 1); } if ($clust->{right}) { printclust($clust->{right}, $labels, $n + 1); } } 1;
■ はてダRSSを元に生成されたテキストデータ
blog_title shibuya / けど 違う でも newfe my で 水曜 ね 間違っ 人 且つ もんもん ボタン たら 度 分から request 総数 mixi する ハード カンファレンス newdatarequest 名 面倒 交通 マイミク 面白 方法 続い $ もの っと 群 面白く ー lwp 相手 承諾 つくら 突っ edition 直接 一 realvnc 初 詳しい た 。 割る { 知ら 今回 ゼミ に って イク perl ユーザー まし bless ) 表示 データ 室 めんどくさい } com 途中 押さ bin かも = #!/ 列 さ 一部 死ね 火曜 大学 http 思っ : ぼけ 会社 テキストファイル できる professi … shift pm ( デスク ない www まぁ ■ メール add セットアップ てる 送っ 全然 だ 系 なんだか usr です :// 被っ タイトル カウント とかし ?) 接続 vnc xmlin 流れ うだうだ 僕 言わ opensocial 閲覧 入っ ($ アシスタント か // 目 リモート み url 聴か 研究 トップ 工業 これ feedparser 訪問 とか () ん 関係 ・ simple 立っ て なっ もしか の function parse pc クラスタリング その後 も ダメ var professional だけ home real ブログ ログイン から さすが 費 のに _ package アプリカンファ xp ! コミュニティ ua 作っ jpa self 悔しい キーワード ので そう :: 出力 xml なー 者 new 読み込む {}, が 抽出 ます 近似 単語 やっぱり 一覧 来る とりあえず し 昨日 -> (); 違っ 階層 重複 と 木曜 useragent 、 は 化 use . 大杉 説明 な 若干 ; れ を ちょっと でき feed 一行 同じ 結果 return sub 取得 双方 側 [Perl]集合知プログラミング 3.3をperl化してみた(階層化クラスタリング) 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 2 0 0 0 1 1 0 0 0 0 4 3 1 0 0 0 0 0 1 0 0 2 0 1 0 2 0 1 0 0 0 0 0 [雑記]今週って 1 0 0 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 3 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 1 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 2 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 [Perl]集合知プログラミング 3.3をperl化してみた(形態素解析+単語数カウント) 0 2 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 4 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0 1 0 0 0 0 4 0 1 0 0 3 0 1 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 2 0 0 0 2 0 0 0 0 0 7 0 0 0 0 1 0 0 0 1 2 0 0 0 [雑記]研究室が意外と面白そうだった。 0 0 0 0 1 0 0 1 0 0 0 2 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 1 1 3 3 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 2 0 1 0 0 0 1 0 0 1 1 1 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 0 0 1 4 0 0 3 0 0 1 0 2 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 3 4 0 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 [雑記][JavaScript]はじめてのmixiアプリ? 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 3 1 1 0 0 0 0 3 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 0 0 1 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 0 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 1 0 0 0 0 1 4 0 0 0 0 0 1 2 0 0 2 2 0 0 0 0 0 0 0 0 1 2 0 0 0 0 1 0 0 0 0 1 2 [雑記][JavaScript]mixiアプリカンファレンスに落選したのでやっつけでアプリ作ろうとした(途中) 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 2 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 2 0 0 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 2 0 1 0 0 1 0 1 1 0 0 0 0 2 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 3 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 1 0 0 [雑記]Windows XP Home Editionで簡単リモート接続 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 1 0 0 0 1 0 2 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 1 0 0 0 0 2 0 0 0 1 0 0 4 0 0 1 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 3 0 0 4 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
■ 実行結果
[yuki@sorauta 3]$ perl clusters_hatena.pl - [Perl]集合知プログラミング 3.3をperl化してみた(形態素解析+単語数カウント) - [雑記]今週って - [雑記]Windows XP Home Editionで簡単リモート接続 - [雑記]研究室が意外と面白そうだった。 - [Perl]集合知プログラミング 3.3をperl化してみた(階層化クラスタリング) - [雑記][JavaScript]mixiアプリカンファレンスに落選したのでやっつけでアプリ作ろうとした(途中) [雑記][JavaScript]はじめてのmixiアプリ?
・・・どうにも何かがおかしい気がしてならない。
せめて集合値の記事のクラスタリングくらい通らないかなー。
甘い考えでした。
今から原因調査する予定。