入力にテキスト(文章)を与えると、それに対する平均情報量(エントロピー)を計算するだけの Perl スクリプトです。
各文字(または指定により任意のトークン)の確率(p)を求めて下記の式で計算するだけ[1]。
コマンドラインオプション:
- "-k NUM" : TSVのときに使うカラムを指定。指定なしだと全て。
- "-l" : 1行ごとに平均情報量を計算。指定なしだと全行まとめて。
- "-s STRING" : テキスト分割用のセパレータを指定。指定なしだと文字単位になる。
■コード (aventro.pl)
■実行例
http://www.infonet.co.jp/ueyama/ip/binary/entropy.html
[2] 日本語ツイートの情報量は、世界で2番目に少ないらしい (TEXT/YUBASCRIPT)
http://blog.yubais.net/3.html
各文字(または指定により任意のトークン)の確率(p)を求めて下記の式で計算するだけ[1]。
コマンドラインオプション:
- "-k NUM" : TSVのときに使うカラムを指定。指定なしだと全て。
- "-l" : 1行ごとに平均情報量を計算。指定なしだと全行まとめて。
- "-s STRING" : テキスト分割用のセパレータを指定。指定なしだと文字単位になる。
■コード (aventro.pl)
#!/usr/bin/env perl use strict; use warnings; use List::Util qw(sum); use Getopt::Long; use utf8; use open ":utf8"; binmode STDIN, ":utf8"; binmode STDOUT, ":utf8"; my $key_at_str = 0; # key=POS : process only POS-th column (origin 1) my $sep = ""; # token separator my $line_mode = 0; # process each-line GetOptions( "key=s" => \$key_at_str, "sep=s" => \$sep, "line" => \$line_mode, ); my %freq; while (<>) { chomp; $_ = (split(/\t/, $_))[$key_at_str-1] if $key_at_str; next if /^\s*$/; my @c = split(/$sep/, $_); $freq{$_}++ for @c; if ($line_mode) { printf "%.8f\n", calc_entro(\%freq); %freq = (); } } printf "%.8f\n", calc_entro(\%freq) if not $line_mode; sub calc_entro { my ($r) = @_; my $sum = sum(values %$r); my $H = -1 * sum(map {my $p = $r->{$_}/$sum; $p * log($p)/log(2)} keys %$r); return $H; }
■実行例
% cat test-1.txt 六本木から渋谷へ行くには恵比寿経由かな 今日は高校で国語のテストです バナナとリンゴ あはははは ああああ % ./aventro.pl test-1.txt 4.93880341 % ./aventro.pl -l test-1.txt 4.14266436 3.66449778 2.52164064 0.72192809 0.00000000
% cat test-2.tsv 1 六本木,から,渋谷,へ,行く,に,は,恵比寿,経由,で,山手線,で,行く 2 今日,は,国語,の,テスト,は,ない 3 バナナ,と,リンゴ 4 あはははは % ./aventro.pl -k 2 -s "," test-2.tsv 4.22017552 % ./aventro.pl -k 2 -s "," -l test-2.tsv 3.39274741 2.52164064 1.58496250 0.00000000
参考
[1] 平均情報量/エントロピーhttp://www.infonet.co.jp/ueyama/ip/binary/entropy.html
[2] 日本語ツイートの情報量は、世界で2番目に少ないらしい (TEXT/YUBASCRIPT)
http://blog.yubais.net/3.html
この記事に言及しているこのブログ内の記事