前回の
Trie木――自然言語処理で使用する代表的なデータ構造
自然言語処理、
Trie木は接頭辞木とも呼ばれる順序付き木構造の一種で、

Trie木の特徴として、
- 格納されているキーの検索が高速
- 共通する接頭辞がまとめられることによる圧縮効果
- 共通する接頭辞を持つキーの列挙が可能
などがあり、
Trie木を表現する実装には、
ダブル配列
ダブル配列はBaseとCheckの2つの配列によってノード間の遷移を表現します。ダブル配列は検索が高速で、
s:現在の状態番号
t:次の状態番号
c:検索する文字に対応する整数
t = Base[s] + c
このとき、
Perlでダブル配列を利用する場合は、
LOUDS-Trie
Trie 木の別の実装としてLOUDS -Trieがあります。LOUDS
PerlでLOUDS -Trieを利用する場合は、
自然言語テキスト解析の基本
本節では、
テキスト解析の流れ
日本語テキスト解析を行う流れは、

形態素解析
形態素解析とは、
形態素解析は後続の処理である係り受け解析のためではなく、
形態素解析のしくみ
ここでは、
- ① 単語の生起コスト
(単語の出現確率)、 品詞などの情報が格納されている単語辞書を用意する - ② 単語辞書を利用して、
入力文に含まれる単語候補を列挙する - ③ 列挙した単語を文頭から文末まで並べて、
組み合わせた構造 (Lattice構造) を作成する (図3) - ④ Lattice構造の頂点
(図3の各ボックス) を通るコストとして、 単語の生起コスト (単語の出現確率が高いほど低コスト) を設定する - ⑤ Lattice構造の辺
(図3の各矢印) を通るコストとして、 連接コスト (品詞の隣接確率が高いほど低コスト) を設定する - ⑥ 文頭から文末までの経路で最もコストの低い経路を探索する
- ⑦ 探索した最もコストの低い単語列
(図3の太字の列) を出力する

実際の形態素解析器ではこれに加えて、
Text::Mecabで形態素解析
次にPerlで形態素解析を行う方法について説明します。ここでは広く利用されている形態素解析器であるMeCabのPerlバインディングであるText::MeCabの使用方法を説明します。なお、
以下は、
use strict;
use warnings;
use utf8;
use Encode;
use Text::MeCab;
use Data::Dumper::AutoEncode;
my $parser = Text::MeCab->new(rcfile=> './mecabrc');
my $encoding = Encode::find_encoding('utf8');
my $input = " 彼女は大学生だ";
my @result;
for (
my $node = $parser->parse($text);
$node;
$node = $node->next
) {
next if $node->stat =~ /[23]/; (1)
my $surface = $encoding->decode($node->surface); (2)
my $feature = $encoding->decode($node->feature);
my @feature = split ',', $feature;
push @result, { surface => $surface,
pos => $feature[0],
pron => $feature[7] };
}
print eDumper(\@result);
次は、
#!perl -w
use strict;
use warnings;
use utf8;
use constant MECABRC => './mecabrc';
use Encode;
use Text::MeCab;
use Lingua::JA::Regular::Unicode qw/katakana2hiragana/;
if(@ARGV != 1){
print <<USAGE;
USAGE: ./add_rubytag.pl INPUT_TEXT
USAGE
exit -1;
}
run(@ARGV);
exit 0;
sub run {
my $input = shift;
my $parser = Text::MeCab->new(
rcfile=> MECABRC,
);
my $encoding = Encode::find_encoding('utf8');
my $result = q{};
for my $text (split /(\s+)/, $input) {
foreach (
my $node = $parser->parse($text);
$node;
$node = $node->next
) {
next if $node->stat =~ /[23]/;
my $surface
= $encoding->decode($node->surface);
my $feature
= $encoding->decode($node->feature);
my $read = (split /,/, $feature)[7];
if($read ne q{} && $surface ne $read) {
$result
.= add_ruby_tag($surface, $read);
}else {
$result .= $surface;
}
}
}
print $encoding->encode($result), "\n";
}
sub add_ruby_tag {
my ($surface, $read) = @_;
my $read_hiragana = katakana2hiragana($read);
if($surface ne $read_hiragana){
return "<ruby>" . $surface. "<rt>"
. $read_hiragana . "</ruby>";
} else {
return $surface;
}
}
係り受け解析
係り受け解析は形態素解析の結果を受けて、
係り受け解析のしくみ
係り受け解析の手法としては、
- Shift-Reduce
- 全域木
- チャンキングの段階適用
などがありますが、
- ① 機械学習によって作成されたチャンクモデルに基づいて文をチャンクという単位に分割する
- ② 文末以外のすべてのチャンクで、
直後のチャンクに係るかどうかを推定する。係る場合は直後のチャンクを親 (係り元) とする - ③ すでに係り先となったチャンクを削除し、
チャンクが1つになった場合は終了し、 それ以外は残ったチャンクを対象として②の処理に戻る

CaboChaで構文解析
Perlで係り受け解析をする場合は、
以下は、
use strict;
use utf8;
use Encode;
use Text::MeCab;
use CaboCha;
my $parser = Text::MeCab->new(rcfile=> './mecabrc');
my $encoding = Encode::find_encoding('utf8');
my $input = " 彼女は東京にある大学に通っています";
my @result;
for my $text (split /(\s+)/, $input) {
for (
my $node = $parser->parse($text);
$node;
$node = $node->next
) {
next if $node->stat =~ /[23]/;
my $surface = $encoding->decode($node->surface);
my $feature = $encoding->decode($node->feature);
push @result, "${surface}\t${feature}";
}
}
my $cabocha = CaboCha::Parser->new("-I1");
my $tree = $cabocha->parse(join("\n", @result));
my $chunk_number = 0;
for (my $i = 0; $i < $tree->chunk_size; ++$i) {
my $chunk = $tree->chunk($i);
print sprintf("chunk %d is following chunk %d",
chunk_number++, $chunk->{link}), "\n";
for(my $j = 0; $j < $chunk->{token_size}; ++$j){
my $token = $tree->token($chunk->{token_pos} + $j);
print "\t" . $token->{surface}
. " : " . $token->{feature}, "\n";
}
}
意味解析
意味解析とは、
意味解析の手法として研究されているのが格文法を用いた手法です。
格文法
格文法とは、
格 | 意味 |
---|---|
動作主格 | 動作を引き起こすもの |
対象格 | 動作が作用する対象となるもの |
場所格 | 動作が起こる場所や位置を表すもの |
時間格 | 動作が起こる時間を表すもの |
源泉格 | 移動における起点を表すもの |
目標格 | 移動における終点を表すもの |
道具格 | 動作を起こさせるもの |
経験者 | 格心理現象を体験するもの |
格解析
文の格構造を決定する処理を、
- 選択制限に基づく手法
- 用例に基づく手法
選択制限に基づく手法は、
用例に基づく手法は、
日本語用の格解析ツールとしては、
<続きの