この段階では,変形した構文木から辞書 (lexicon) とテンプレートデータベースを抽出します. 辞書というのは, 単語情報 ('word' 型) から語彙項目テンプレートの名前 ('lex_entry' 型) へのマッピングを集めたものです. テンプレートデータベースというのは, 語彙項目テンプレートの名前から語彙項目テンプレートの素性構造 ('hpsg_word' 型) へのマッピングを集めたものです.
抽出処理は,2段階に分かれています. 前半では, 変形された構文木から HPSG などの文法に沿った導出木を作り, 導出木の葉ノードの素性構造から辞書とテンプレートデータベースをつくります. 後半では, 抽出した辞書とテンプレートデータベースに, 頻度の低い項目を消したり,未知語の項目を作ったりといった精製処理を行い, 最終的な辞書とテンプレートデータベースをつくります. これらの処理において, 導出木は "mayz/derivtypes.lil" で定義された型で表現されています.
ここでは,変形した構文木から目的の文法による導出木を作り, 辞書とテンプレートデータベースを抽出する過程について説明します. この過程は,mayz の lexextract ツールを利用し、下記のコマンドによって行われます. (lexextract ツールについて詳しくは, mayz のマニュアルも参照してください.)
lexextract 文法獲得モジュール treebank derivbank 辞書 テンプレートデータベース lexbank | |
文法獲得モジュール | 逆方向のスキーマと語彙規則(後述)などが定義された lilfes ファイル |
treebank | 入力の構文木データベース (lildb 形式) |
derivbank | 導出木を出力するデータベース (lildb 形式) |
辞書 | 辞書を出力するデータベース (lildb 形式) |
テンプレートデータベース | 語彙項目テンプレートを出力するデータベース (lildb 形式) |
lexbank | 導出木の葉ノードを出力するデータベース (lildb 形式) |
Enju の文法開の場合, 文法獲得モジュールは "enju-devel/lexextract.lil" です. 入力 treebank の構文木は, 前段階のコーパスの変形で得られたもの(例)になります. それらの構文木から HPSG による導出木(例)が作られ, 辞書の抽出に使われます.
lexextract ツールはまず, 入力された構文木をもとにして目的文法による導出木を作ります. 具体的には,はじめに導出木の根ノードをつくり, もとの構文木の形に合わせて逆方向のスキーマを適用して,親ノードから娘ノードを作っていきます. 最後に,葉ノードに導出木の葉ノードとして満たすべき制約をかけ, 導出木の完成となります. 導出木の根ノードや葉ノードの制約はインターフェース述語 root_constraints/1, lexical_constraints/2 でそれぞれ指定できます. 逆方向のスキーマは, インターフェース述語 inverse_schema_binary/4, inverse_schema_unary/3 で指定します. まとめると,導出木は以下の手順で作られます.
Enju 文法の場合,導出木のノードや逆方向スキーマに次のような制約を指定しています.
root_constraints($Sign) :- $Sign = (SYNSEM\(LOCAL\CAT\(HEAD\MOD\[] & VAL\(SUBJ\[] & COMPS\[] & SPR\hpsg_synsem_exp_nil & SPEC\[] & CONJ\[])))). inverse_schema_binary(subj_head_schema, $Mother, $Left, $Right) :- $Left = (SYNSEM\($LeftSynsem & LOCAL\CAT\(HEAD\MOD\[] & VAL\(SUBJ\[] & COMPS\[] & SPR\[] & SPEC\[] & CONJ\[])))), $Subj = $LeftSynsem, $Right = (SYNSEM\(LOCAL\CAT\(HEAD\$Head & VAL\(SUBJ\[$Subj] & COMPS\[] & SPR\[] & SPEC\$Spec & CONJ\[])))), $Mother = (SYNSEM\(LOCAL\CAT\(HEAD\$Head & VAL\(SUBJ\[] & COMPS\[] & SPR\[] & SPEC\$Spec & CONJ\[])))). lexical_constraints(SURFACE\$Surface, SYNSEM\LOCAL\CAT\HEAD\AUX\hpsg_copula_be) :- auxiliary_be($Surface).
lexextract ツールは次に, 導出木の葉ノードから,辞書とテンプレートデータベースを作ります. 葉ノードの単語情報からは辞書のキーが,葉ノードの sign からは語彙項目テンプレートが得られます. ここでは, 語彙項目テンプレートをそのまま登録するのではなく, 語彙項目テンプレートの元となる「語彙素テンプレート」という素性構造を作って登録することもできます. 語彙項目テンプレートから語彙素テンプレートを作る方法, つまり逆方向の語彙規則はインターフェース述語 reduce_lexical_template/5 で指定します. 他にも辞書のキーの作り方などを,インターフェース述語 lexeme_name/4,lexical_entry_template/3, lexicon_key/2 で指定できます. これらの述語を用いて,以下のように抽出作業が行われます.
Enju の文法開発では,上記インターフェース述語で 次のような指定をしています.
これらの制約はたとえば次のように指定されます.
正確な実装は "enju-devel/lextemplate.lil","enju-devel/invlexrule.lil" を見てください.
lexical_entry_template($WordInfo, $Sign, $Template) :-
make_semantics($WordInfo, $Sign, $LexName1, $Cont1),
...
abstract_lexical_template($Template).
abstract_lexical_template($Template):-
$Template = (SYNSEM\(LOCAL\CAT\(HEAD\($Head & MOD\$Mod) &
VAL\(SUBJ\$Subj &
COMPS\$Comps &
SPR\$Spr &
SPEC\$Spec &
CONJ\$Conj)) &
NONLOCAL\INHER\(REL\$Rel &
SLASH\$Slash &
F_REL\$FRel))),
abstract_mod($Mod, $Head),
abstract_subj_list($Subj, $Template),
abstract_comp_list($Comps, $Template),
...
abstract_head($Head).
abstract_subj($Synsem, SYNSEM\LOCAL\CAT\HEAD\$Head) :-
restriction($Synsem, [NONLOCAL\]),
restriction($Synsem, [LOCAL\, CAT\, HEAD\, POSTHEAD\]),
restriction($Synsem, [LOCAL\, CAT\, HEAD\, AGR\]),
restriction($Synsem, [LOCAL\, CAT\, HEAD\, AUX\]),
...
generalize_subj_head($Synsem, $Head).
reduce_lexical_template($WordInfo, $LexEntry, $Key, $Lexeme, $Rules) :-
get_sign($LexEntry, $Sign),
get_lexeme($WordInfo, $LexEntry, $BaseWordInfo, $Lexeme1, [], $Rules1),
canonical_copy($Lexeme1, $Lexeme),
$Rules = $Rules1,
$BaseWordInfo = (BASE\$Base & POS\$POS),
$Key = (BASE\$Base & POS\$POS).
get_lexeme($WordInfo, $InTemplate, $NewWordInfo, $NewTemplate,
$InRules, $NewRules) :-
($InRules = [$Rule1|_] ->
upper_rule($Rule1, $Rule); true),
inverse_rule_lex($Rule, $WordInfo, $InTemplate, $WordInfo1, $Template1),
get_lexeme($WordInfo1, $Template1, $NewWordInfo, $NewTemplate,
[$Rule|$InRules], $NewRules).
辞書とテンプレートデータベースの精製
ここでは,抽出された辞書とテンプレートデータベースを精製する過程について説明します. この過程は,mayz の lexrefine ツールを利用し、下記のコマンドによって行われます. (lexrefine ツールについて詳しくは, mayz のマニュアルも参照してください.)
lexrefine ルールモジュール 元辞書 元テンプレートデータベース 新辞書 新テンプレートデータベース | |
ルールモジュール | 語彙規則が定義されたモジュール |
元辞書 | 入力の辞書 |
元テンプレートデータベース | 入力のテンプレートデータベース |
新辞書 | 精製された出力辞書 |
新テンプレートデータベース | 精製された出力テンプレートデータベース |
lexrefine ツールでは, まず出現回数の少ないテンプレートを削除したりしてテンプレートベータベースを精製します. 次にテンプレートデータベースの精製による変化に辞書を追随させます. また未知語に対応するため,未知語エントリを辞書に作ります. Enju の文法開発の場合, ルールモジュールは "enju-devel/lexrule.lil" を使っています.
Enju の場合の語彙規則については,
語彙規則のページを参照してください.
語彙規則の指定はたとえば次のようになります.
正確な実装については,"enju-devel/lexrule.lil" を参照してください.
expand_lexical_template($InTempName, $InTemplate, $Count, $LexRules, $NewTemplate) :-
get_variable('*template_expand_threshold*', $Thres),
($Count > $Thres ->
ordered_lexical_rules($LexRules),
apply_ordered_lexical_rules(_, $InTemplate, $LexRules, _, $Template1),
get_sign($Template1, $NewTemplate);
$LexRules = [],
get_sign($InTemplate, $NewTemplate)).
Enju の場合,辞書のキーは BASE 素性と POS 素性が特定されている 'word' 型です.
インターフェース述語 expand_lexicon/3 で作る語彙項目のキーは
元テンプレートのキーの POS 素性の値を変えた 'word' 型になります.
新しいキーの POS 素性は,新しいテンプレートを作った語彙規則で決められます.
例えば,
動詞の語彙素テンプレートから3人称現在単数形のテンプレートを作るルールが適用された場合,
語彙項目のキーの POS 素性は "VBZ" となります.
expand_lexicon($InKey, $NewTempName, $NewKey) :-
$InKey = BASE\$Base & POS\$BasePOS,
$NewTempName = LEXICAL_RULES\$Rules,
rules_to_inflection($BasePOS, $Rules, $POSList),
member($NewPOS, $POSList),
$NewKey = BASE\$Base & POS\$NewPOS.
lexrefine は次に,未知語のためのエントリを辞書に追加します. つまり,頻度が閾値以下の単語を未知語とみなして新たなエントリを作ります. 新たなエントリのキーを作る方法は, インターフェース述語 unknown_word_key/2 で指定します. 具体的な処理は次のようになります.
Enju の場合,未知語のキーは POS 素性のみ特定されている 'word' 型です.
インターフェース述語 unknown_word_key/2 では,
未知語のキーとして元のキーの POS 素性と同じ値をもつ 'word' 型を返します.
unknown_word_key(POS\$POS, POS\$POS).