Feature forest モデル

English version

ここでは,構文解析の際に曖昧性解消をする確率モデルの一つ feature forest モデルの 推定について説明します.

feature forest モデルは,文に対してその derivation の確率を与えるモデルです. 文をs,その derivation をd とすると, p(d|s) を求めます. Enju の確率モデルは最大エントロピーモデルになっているので, モデルの推定では素性の最適な重みを計算することになります (詳しくは確率モデルを参照して下さい). そのために最大エントロピーモデル推定器 Amis と mayz の Amis 用ツール forestmakeramisfilter を利用しています.

具体的には次のような手順で推定が行われます.

  1. forestmaker により確率イベントをファイルに出力する
  2. amisfilter により確率イベントにマスクをかけて素性を取り出し, Amis 形式のデータファイルを作る
  3. Amis により素性の最適な重みを計算する

確率イベントとは,以下のように // で区切られたフィールドを持つ文字列です.

S_fin//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//play//VB//[npVPnp]_lxm_10//2//1//m//root
最後のフィールドはこのイベントのカテゴリ を表しています. その他のフィールドはイベントの特徴を表す記号です. forestmaker は 文と対応する derivation の特徴を表す確率イベントを feature forest 形式でファイルに出力します.

amisfilter では,上のような確率イベントに対して そのカテゴリにしたがってマスクをかけます. マスクではどのフィールドを組み合わせて素性を作るかが指定されています. 例えば上の文字列に,(0, 0, 1, 1, 0, 0, 0, 0, 0, 0)というマスクをかけると, 次のような素性が得られます.

_//_//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root
amisfilter はこのようにイベントから素性を取り出し, Amis 形式のデータファイルを生成します. 最後に,Amis によって素性の最適な重みが計算されます.

以下各ステップについて説明します.

確率イベントをファイルに出力する

ここでは forestmaker を 使って,確率イベントをファイルに出力する過程を説明します.

forestmaker モデル名 文法モジュール derivbank イベントファイル
モデル名確率モデルの名前(構文解析の時にも使います)
文法モジュール文法およびイベント抽出 predicate が実装されている lilfes module
derivbank文法獲得で得た derivbank (lildb 形式)
イベントファイル確率イベントを出力するファイル (テキスト形式または gz/bz による圧縮形式)

forestmaker が出力する確率イベントファイルには, 一文の derivation forest を表す確率イベントが feature forest 形式で記されています. derivation forest とは,構文解析後のチャートのように ある文に対して可能な derivation を重ね合わせたものです. 例えば次の図は "Mary runs" という文に対して, 全体として NP となる derivation と S となる derivation の2個がある場合の チャートを簡単に表しています.

チャートの例

"Mary" に対応する NNP ノードが二つの derivation に共有されています. このようなチャートを feature forest 形式で表すと次のようになります (実際には一行で出力されます).

{ node0 
  ( NProot NP//runs//NNS//root    
    { node1 
      ( NPbinary MOD//NNS//runs//NNS//NNP//mary//NNP//binary
        { node2
          ( NNPterm NNP//mary//NNP//term ) }
        { node3
          ( NNSterm NNS//runs//NNS//term ) } ) } )
  ( Sroot S//runs//VBZ//root
    { node4 
      ( Sbinary SUBJ//VBZ//runs//VBZ//NNP//mary//NNP//binary
        $node2
        { node5
          ( VBZterm VBZ//runs//VBZ//term ) } ) } ) }

{ node0 ( NProot ... ) ( Sroot ...) } という構造が, チャートの最上部に 2 種類のノード (NP, S) があることを表します. つまり ( NProot ...) で NP ノードを root とする derivation を, ( Sroot ...) で Sノードを root とする derivation を表し, それらを { } で囲むことで,どちらかが正しい derivation であると示しています. また,共有されるノードは下から 2 行目のように参照を使って表します. つまり $node2 と書くことで { node2 ...} と同じノードであることを表しています.

forestmaker では, derivbank 中の各文の derivation forest を作るため, 入力の文法を用いて構文解析をします. そして結果のチャート上の構文木の各ノードに対して確率イベントを出力します.

  1. 入力の derivbank の derivation から正解の構文木をつくる. 構文木の末端ノードになる語彙項目は,derivation の末端ノードから fm_correct_lexical_entry/2 によって得たものを用いる.
  2. derivation から fm_derivation_to_word_lattice/2 によって,元の文に対する word lattice をつくる.
  3. 上で作った word lattice を入力として構文解析を行いチャートを得る. 構文解析では up と同じ文法のインターフェースが使われる. ただし lexical_entry/2 のみは, かわりに fm_lexical_entry/2 が使われる.
  4. 正解の構文木の確率イベントを観測事象として出力する. 具体的には構文木の各ノードに対し以下のインターフェースにより, カテゴリ名と特徴フィールドの記号を得る. 得られた記号とカテゴリ名をつなげて確率イベントを出力する.
  5. チャート上の全ての構文木を feature forest 形式で出力する. 構文木の各ノードでは,4. と同様にしてカテゴリ名と特徴フィールドの記号を得て, 確率イベントを出力する.
構文木のノードから確率イベントを取り出すインターフェースには, 素性の値 (integer または float) を指定できる形式もあります. 詳しくは forestmaker のマニュアル を参照して下さい. Enju の場合,derivbank からチャートを作るインターフェースは "devel/forestmake.lil" で実装されています. 実装の特徴は次のようになっています. これらは例えば次のように実装されます.
fm_correct_lexical_entry(TERM_WORD\$Word & LEXENTRY_SIGN\$Sign, $LexName) :-
    lookup_lexicon($Word, $TempNameList),
    member($TempName, $TempNameList),
    lookup_template($TempName, $LexEntry),
    equivalent($LexEntry, $Sign),
    !,
    $LexName = LEX_WORD\$Word & LEX_TEMPLATE\$TempName.

fm_derivation_to_word_lattice(derivation_internal & DERIV_DTRS\$Dtrs, $WordLattice) :-
    fm_derivation_to_word_lattice_dtrs($Dtrs, $WordLattice).
fm_derivation_to_word_lattice(derivation_terminal & $Term & TERM_WORD\$Word,
			      [left_position\$LPos & right_position\$RPos & word\$LexEntry]) :-
    $LexEntry = $Term,
    $Word = POSITION\$LPos,
    $RPos is $LPos + 1.

fm_lexical_entry(TERM_WORD\$Word & LEXENTRY_SIGN\$Sign, $LexName) :-
    lookup_lexicon($Word, $TempNameList1),
    check_coverage($TempNameList1, $Sign, $TempName1),
    findall($Lex,
	    (member($TN, $TempNameList1),
	     $Lex = LEX_WORD\$Word & LEX_TEMPLATE\$TN),
	    $LexList1),
    restrict_templates($LexList1, $LexList2),
    (memberchk(LEX_TEMPLATE\$TempName1, $LexList2) ->
     $LexList3 = $LexList2 ;
     $LexList3 = [LEX_WORD\$Word & LEX_TEMPLATE\$TempName1|$LexList2]),
    member(LEX_TEMPLATE\$TempName, $LexList3),
    $LexName = LEX_WORD\$Word & LEX_TEMPLATE\$TempName.
構文木の各ノードからカテゴリ名と特徴を表す記号を取り出すインターフェースは, "grammar/forestevent.lil" で実装されています. これらは例えば次のように指定されます.
extract_root_event("hpsg-forest", "root", $Sign, $Event) :-
    encode_sign($Sign, $Event, []).

extract_terminal_event("hpsg-forest", "term", _, $Sign, _, $Event) :-
    encode_sign($Sign, $Event, []).

extract_unary_event("hpsg-forest", "sem", _, _, _, $Inactives, 
                    [$Surface, $POS, $Temp,$ArgSurf, 
		    $ArgPOS, $ArgTemp,
		    $Feature, $Dist]) :-
    member($Ind & PRED\(LEX_WORD\(SURFACE\$Surface &
				  POS\$POS &
				  POSITION\$Position) &
			LEX_TEMPLATE\LEXEME_NAME\$Temp),
	   $Inactives),
    extract_argument($Ind, $Feature,
		     LEX_WORD\(SURFACE\$ArgSurf & POS\$ArgPOS &
			       POSITION\$ArgPosition) &
		     LEX_TEMPLATE\LEXEME_NAME\$ArgTemp),
    arg_distance($Position, $ArgPosition, $Dist).
    extract_hpsg_sem_event($Inactives, $Event).

forestmaker が出力する確率イベントファイルは次のようになっています.

event_2
1        S_fin//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//
play//VB//[npVPnp]_lxm_10//2//1//m//root plays//VBZ//[npVPnp]_lxm_1
0//haag//NNP//[dtNP]_lxm_2//ARG1//1//sem plays//VBZ//[npVPnp]_lxm_1
0//elianti//NNP//[dtNP]_lxm_2//ARG2//1//sem SUBJ//1//1//m//m//NNP//
VBZ//VP//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//play//V
B//[npVPnp]_lxm_10//1//1//m//NP//haag//NNP//[dtNP]_lxm_2//haag//NNP
//[dtNP]_lxm_2//1//0//m//bin ms-period-//NNP//[dtNP]_lxm_2//haag//N
NP//[dtNP]_lxm_2//MODIFY//1//sem LMOD//1//2//m//m//NNP//NNP//N_adj/
/ms-period-//NNP//[dtNP]_lxm_2-noun_adjective_rule//ms-period-//NNP
//[dtNP]_lxm_2//0//0//m//NX//haag//NNP//[dtNP]_lxm_2//haag//NNP//[d
tNP]_lxm_2//0//0//m//bin N_adj//ms-period-//NNP//[dtNP]_lxm_2-noun_
adjective_rule//ms-period-//NNP//[dtNP]_lxm_2//0//0//m//term NX//ha
ag//NNP//[dtNP]_lxm_2//haag//NNP//[dtNP]_lxm_2//0//0//m//term COMP/
/1//2//m//m//VBZ//NNP//VX//plays//VBZ//[npVPnp]_lxm_10-singular3rd_
verb_rule//play//VB//[npVPnp]_lxm_10//0//1//m//NP//elianti//NNP//[d
tNP]_lxm_2//elianti//NNP//[dtNP]_lxm_2//0//0//m//bin VX//plays//VBZ
//[npVPnp]_lxm_10-singular3rd_verb_rule//play//VB//[npVPnp]_lxm_10/
/0//1//m//term NX//elianti//NNP//[dtNP]_lxm_2//elianti//NNP//[dtNP]
_lxm_2//0//0//m//term
{ _ ( root31 S_fin//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_ru
le//play//VB//[npVPnp]_lxm_10//2//1//m//root { node31 ( b31_0 plays
//VBZ//[npVPnp]_lxm_10//haag//NNP//[dtNP]_lxm_2//ARG1//1//sem plays
//VBZ//[npVPnp]_lxm_10//elianti//NNP//[NP]_23//ARG2//1//sem SUBJ//1
//1//m//m//NNP//VBZ//VP//plays//VBZ//[npVPnp]_lxm_10-singular3rd_ve
rb_rule//play//VB//[npVPnp]_lxm_10//1//1//m//NP//haag//NNP//[dtNP]_
lxm_2//haag//NNP//[dtNP]_lxm_2//1//0//m//bin { node18 ( u18_0 { nod
e17 ( b17_0 ms-period-//NNP//[dtNP]_lxm_2//haag//NNP//[dtNP]_lxm_2//
MODIFY//1//sem LMOD//1//2//m//m//NNP//NNP//N_adj//ms-period-//NNP//[
dtNP]_lxm_2-noun_adjective_rule//ms-period-//NNP//[dtNP]_lxm_2//0//0
//m//NX//haag//NNP//[dtNP]_lxm_2//haag//NNP//[dtNP]_lxm_2//0//0//m//
bin { node0 ( term0_0 N_adj//ms-period-//NNP//[dtNP]_lxm_2-noun_adje
ctive_rule//ms-period-//NNP//[dtNP]_lxm_2//0//0//m//term ) } { node3
 (term3_0 NX//haag//NNP//[dtNP]_lxm_2//haag//NNP//[dtNP]_lxm_2//0//0
//m//term ) }) } ) } { node28 ( b28_0 COMP//1//2//m//m//VBZ//NNP//VX
//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//play//VB//[npVP
np]_lxm_10//0//1//m//NP//elianti//NNP//[NP]_23//elianti//NNP//[NP]_2
3//0//0//m//bin { node5 ( term5_0 VX//plays//VBZ//[npVPnp]_lxm_10-si
ngular3rd_verb_rule//play//VB//[npVPnp]_lxm_10//0//1//m//term ) } { 
node14 ( term14_0 NP//elianti//NNP//[NP]_23//elianti//NNP//[NP]_23//
0//0//m//term ) } ) } ) ( b31_1 plays//VBZ//[npVPnp]_lxm_10//haag//N
NP//[dtNP]_lxm_2//ARG1//1//sem plays//VBZ//[npVPnp]_lxm_10//elianti/
/NNP//[dtNP]_lxm_2//ARG2//1//sem SUBJ//1//1//m//m//NNP//VBZ//VP//pla
ys//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//play//VB//[npVPnp]_l
xm_10//1//1//m//NP//haag//NNP//[dtNP]_lxm_2//haag//NNP//[dtNP]_lxm_2
//1//0//m//bin $node18 { node29 ( b29_0 COMP//1//2//m//m//VBZ//NNP//
VX//plays//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//play//VB//[np
VPnp]_lxm_10//0//1//m//NP//elianti//NNP//[dtNP]_lxm_2//elianti//NNP/
/[dtNP]_lxm_2//0//0//m//bin $node5 { node16 ( u16_0 { node9 ( term9_
0 NX//elianti//NNP//[dtNP]_lxm_2//elianti//NNP//[dtNP]_lxm_2//0//0//
m//term ) } ) ( u16_1 $node9 ) } ) } ) } ) (root32 NP//ms-period-//N
NP//[dtNP]_lxm_2//ms-period-//NNP//[dtNP]_lxm_2//2//1//m//root { nod
e32 ( b32_0 elianti//NNP//np[dtNP]_382//ms-period-//NNP//[dtNP]_lxm_
2//MODIFY//2//sem RMOD//2//1//m//m//VBZ//NNP//NP//elianti//NNP//np[d
tNP]_382//elianti//NNP//np[dtNP]_382//0//0//m//NP//ms-period-//NNP//
[dtNP]_lxm_2//ms-period-//NNP//[dtNP]_lxm_2//2//1//m//bin { node27 (
 u27_0 { node22 ( b22_0 plays//VBZ//[npVPnp]_lxm_10//haag//NNP//[dtN
P]_lxm_2//ARG1//1//sem plays//VBZ//[npVPnp]_lxm_10//ms-period-//NNP/
/[dtNP]_lxm_2//ARG2//2//sem REL//2//2//m//m//NNP//NNP//S_fin//plays/
/VBZ//[npVPnp]_lxm_10-wh_move_rule-singular3rd_verb_rule//play//VB//
[npVPnp]_lxm_10//1//1//m//NX//ms-period-//NNP//[dtNP]_lxm_2//ms-peri
od-//NNP//[dtNP]_lxm_2//0//0//m//bin { node1 ( term1_0 NX//ms-period
-//NNP//[dtNP]_lxm_2//ms-period-//NNP//[dtNP]_lxm_2//0//0//m//term )
 } { node21 ( u21_0 EMPTY_FILLER//S_fin//plays//VBZ//[npVPnp]_lxm_10
-wh_move_rule-singular3rd_verb_rule//play//VB//[npVPnp]_lxm_10//1//1
//m//unary { node20 ( b20_0 SUBJ//1//2//m//m//NNP//VBZ//VP//plays//V
BZ//[npVPnp]_lxm_10-wh_move_rule-singular3rd_verb_rule//play//VB//[n
pVPnp]_lxm_10//0//1//m//NP//haag//NNP//[dtNP]_lxm_2//haag//NNP//[dtN
P]_lxm_2//0//0//m//bin { node4 ( u4_0 $node3 ) ( u4_1 $node3 ) } { n
ode8 ( term8_0 VP//plays//VBZ//[npVPnp]_lxm_10-wh_move_rule-singular
3rd_verb_rule//play//VB//[npVPnp]_lxm_10//0//1//m//term ) } ) } ) } 
) } ) } { node15 ( u15_0 { node13 ( term13_0 NX//elianti//NNP//np[dt
NP]_382//elianti//NNP//np[dtNP]_382//0//0//m//term ) } ) ( u15_1 $no
de13 ) } ) } ) }

event_3
......
event_2 は "Ms. Haag plays Elianti." という文に対する確率イベントの 出力です.

マスクをかけて素性を取り出す

ここでは amisfilter を使って, 上のステップで出力された確率イベントにマスクをかけ, 素性を取り出し,Amis 形式のデータファイルを出力します. この部分は Unigram モデルの推定の場合と同様です. ただし,feature forest 形式を保ったまま素性を取り出すため, 出力されるイベントファイルは次のようになります.

event1
1 S//_//_//root _//_//VBZ//root SUBJ//VBZ//_//_//NNP//_//_//binary
SUBJ//_//_//VBZ//_//_//NNP//binary _//mary//NNP//term 
_//runs//VBZ//term
{ node0 
  ( NProot NP//_//_//root _//_//NNS//root    
    { node1 
      ( NPbinary MOD//NNS//_//_//NNP//_//_//binary
                 MOD//_//_//NNS//_//_//NNP//binary
        { node2
          ( NNPterm _//mary//NNP//term ) }
        { node3
          ( NNSterm _//runs//NNS//term ) } ) } )
  ( Sroot S//_//_//root _//_//VBZ//root
    { node4 
      ( Sbinary SUBJ//VBZ//_//_//NNP//_//_//binary
                SUBJ//_//_//VBZ//_//_//NNP//binary
        $node2
        { node5 ( VBZterm _//runs//VBZ//term ) } ) } ) }

モデルファイルは Unigram モデルの場合と同様です.

Enju の場合,feature_mask/3 は "grammar/synmask.lil", "grammar/semmask.lil" で実装されています. "grammar/synmodel.lil"の場合, カテゴリ "root" に対するマスクには次のようなものが含まれます.

SymbolSurfacePOSTempNameBaseBasePOSLexemeSpanNumClauseNumComma
mask 1×××××××××
mask 2×××××××××
mask 3××××××××
mask 4×××××××××
これらは次のように実装されます.
feature_mask("hpsg-forest", "root", [0,  0, 0, 1,  0, 0, 0,  0, 0, 0]).
feature_mask("hpsg-forest", "root", [0,  0, 1, 0,  0, 0, 0,  0, 0, 0]).
feature_mask("hpsg-forest", "root", [0,  0, 1, 1,  0, 0, 0,  0, 0, 0]).
feature_mask("hpsg-forest", "root", [1,  0, 0, 0,  0, 0, 0,  0, 0, 0]).

上のようなマスクを上のステップで示した確率イベントファイルの例に適用すると, 次のような Amis 形式のイベントファイルが得られます.

event_2
1       _//_//_//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//
_//_//root _//_//VBZ//_//_//_//_//_//_//_//root _//_//VBZ//[npVPnp]_
lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root S_fin//_//_//_/
/_//_//_//_//_//_//root SUBJ//1//_//m//m//_//_//_//_//_//[npVPnp]_lx
m_10-singular3rd_verb_rule//_//_//_//_//_//m//_//_//_//[dtNP]_lxm_2/
/_//_//_//_//_//m//bin SUBJ//1//_//m//m//_//_//_//_//VBZ//_//_//_//_
......
{ _ ( root31 _//_//_//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_
//_//_//_//root _//_//VBZ//_//_//_//_//_//_//_//root _//_//VBZ//[npV
Pnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root S_fin//_//
_//_//_//_//_//_//_//_//root { node31 ( b31_0 SUBJ//1//_//m//m//_//_
//_//_//_//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//m//
......

event_3
......
出力される Amis 形式のモデルファイルには,採用された素性と その重みの初期値が出力されています.
_//_//_//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root 1.0
_//_//VBZ//_//_//_//_//_//_//_//root 1.0
_//_//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root 1.0
......

素性の最適な重みを計算する

上のステップで得られた Amis 形式のモデルファイルとイベントファイルから Amis を使って 素性の最適な重みを計算します. 出力ファイルにはモデルファイルと同じ形式で,計算された素性の重みが示されています.

_//_//_//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root 7.309690e-01
_//_//VBZ//_//_//_//_//_//_//_//root 1.639833e+00
_//_//VBZ//[npVPnp]_lxm_10-singular3rd_verb_rule//_//_//_//_//_//_//root 7.309690e-01
......

Enju 開発者用マニュアル Enju ホームページ 辻井研究室
MIYAO Yusuke (yusuke@is.s.u-tokyo.ac.jp)