岩崎のホームページへ戻る


自然言語処理入門


0. 入力処理(欧文のリスと形式への変換、大文字・小文字の処理、宿約形の扱いなど)
1. 簡単な文脈自由文法とDCG(いわゆる基本文型の導入と主格関係代名詞の処理)
2. 文の構造表示のための技法
3. 文法素性による文脈自由文法の補強(性、数、格、人称、時制、動詞形態、選択制限)
4. 文法規則と語彙データの切り離しによる辞書の整理と語彙登録の簡素化
5. 動詞句にかかわる文法素性(助動詞の導入、決定疑問文、進行形、完了形、to不定詞)
6. Gap素性の導入(補足疑問文と主格以外の関係代名詞など一見移動しているかにみえる 要素の扱い)
7. 文法の拡張(左再帰規則と無限ループ、前置詞句・形容詞句の処理、その他の特殊構文)
8. 翻訳の際の諸問題(日本語用言の活用・語尾の処理、量詞の扱いなど )


入力処理

(1)欧文入力処理 
通常の欧文形式で入力した文をPrologで処理するリスト形式になおすread_sent/1を定義してみよう。

?-read_sent(X).
It is a pen.
X=['It',is,a,pen]

ステップ1:考え方 
 機械は、入力文字をただ単にアスキーコードに変えて処理しているに過ぎない。 
It□is□a□pen.→73 116 32 105 115 32 97 32 112 101 110 46  
しかし人間は、文は単語から単語は文かできている(=階層構造をなしている)ことを
直感的に理解している。したがって、アスキーコードの連鎖を文として認識させるため
には、1)どうやって単語が作られていくのか、2)いつ単語が終わるのか、3)いつ
文が終わるのかについての情報を機械に教えてやらねばならない。具体的には、どの文
字を読み込んだときがそれにあたるのだろうか? 

区別すべき文字の種類
通常の文字:単語を作る
空白/改行:その前で単語が終る
ピリオド  :その前で単語が終り、かつそれが文の終わりでもある


ステップ2:読み込み文字をアスキーコードに変える
 今から作るread_sent/1の中では、まず画面から読み込んだ文字を機械で処理するア
スキーコードに直さなければならない。それには組み込み関数get0/1を、まず使う必要がある。
 
?- get0(U).
(入力待ちの状態になるので a の文字を入力してリターンキーを打つと)
U = 97



ステップ3:処理関数にはどんな引き数が必要か
 文字が集まって単語を作り、単語が集まって、文を作るという階層構造があるので、
get0/1によって読み込まれたアスキーコードを利用して実際に文を作っていく関数に
は、
1)読み込んだアスキーコードを入力引き数にとって区別すべき文字の種類につい
    て判断するところ、
2)作成中の単語を蓄えるところ、
3)作成中の文を蓄えるところ、
4)最終的に完成した文を返すところの計4つの引き数が必要になるだろう。

ステップ4:作業の流れ
It□is□a□pen.  →   73 116 32  105 115  32  97 32 112 101 110  46 
           初期状態
コードを受け    C      73 116 32  105 115  32  97 32 112 101 110  46 
継ぐところ

単語を作る   []       73  73 []  105 105  []  97 [] 112 112 112  []       
ところ                   116         115                101 101
                                                            110
文を作る     []              It   It  It  It  It It              []
ところ                                    is  is is
                                                  a               
最終結果を    X        X   X  X    X   X   X   X  X   X   X   X  X=[It,is,a,pen]
帰すところ

初期状態  :単語作成スタック、文作成スタックともからである。
通常の文字 :単語作成スタック内のコード群末にその文字のコードをつけ足す。
空白(32)     :単語作成スタックの中のコード群を単語(文字)に変え、文作成スタック
               内の単語群の末につけ足す。その結果単語作成スタックの中は、からにな        
               る。  
ピリオド(46) :単語作成スタックの中のコード群を単語(文字)に変え、文作成スタック
               内の単語群の末につけ足し文を完成する。さらに、その完成した文全体を
               最終結果を返すところに移す。

%%%%%%%%%%%% 文読み込みプログラム(修正無し) %%%%%%%%%%%%%%%
Dread_sent(X) :-   get0(C),readin(C,[],[],X),!.
Ereadin(46,WC,S,X) :- !,
      name(W,WC),append(S,[W],X).
Freadin(32,WC,S,X) :- !,   
      name(W,WC),append(S,[W],NS),
      get0(NC),readin(NC,[],NS,X).
Greadin(13,WC,S,X) :- !,nl,
      name(W,WC),append(S,[W],NS),
      get0(NC),readin(NC,[],NS,X).
Hreadin(C,WC,S,X) :-       
      append(WC,[C],NWC),
      get0(NC),readin(NC,NWC,S,X).

Dread_sent/1はトップレベル関数。まずget0/1で一文字読んで、それを実際に処理する
   関数read_in/4に送る。なお、read_in/4の引き数は、前から、1)判断のための文字
   コードを受継ぐところ、2)単語を作るところ、3)文を作るところ、4)最終結果を
   返すところに相当する。
Eコード46は、ピリオド。したがって、それまでreadin/3の第2引き数に蓄えられてい
  たコ ードリストを組込み述語name/2で単語に変え、できた単語をそれまで第3引き数
  に蓄えられていた単語リストの末に組込み述語append/3で連結し文を完成する。完成し  
  た文を第4引き数に返し、終了する。これが終了条件。
Fコード32は、空白。したがって、それまでreadin/3の第2引き数に蓄えられていたコ
   ードリストを組込み述語name/2で単語に変え、できた単語をそれまで第3引き数に蓄
   えられていた単語リストの末に組込み述語append/3で連結する。コードリストを蓄え
   ていた第2引き数は初期状態すなわち空リストに戻す。第4引き数は変化しない。この
   新しい条件のもとに再度get0/1で文字コードリストを読み、readin/3を再帰的に繰り
   返す。
Gコード13は改行キー。Aと同じ処理をし、組込み述語nl/0でラインフィードする。
Hここで処理するのは、それ以外の読み込み文字すなわちアルファベットである。読んだ  
  文字のコードを組込み関数append/3でそれまでに読まれて、第2引き数に蓄えられたコ
  ードリス付け加える。第3、第4引き数は変化しない。この新しい条件のもとに再度
  get0/1で文字コードリストを読み、readin/3を再帰的に繰り返す

%%%%%%%%%%%% 文読み込みプログラムwith 行内修正 %%%%%%%%%%%%%% 
Dread_sent(X) :-   get0(C),readin(C,[],[],X),!.
Ereadin(46,WC,S,X) :- !,
      name(W,WC),append(S,[W],X).
Freadin(32,WC,S,X) :- !,   
      name(W,WC),append(S,[W],NS),
      get0(NC),readin(NC,[],NS,X).
Greadin(13,WC,S,X) :- !,nl,
      name(W,WC),append(S,[W],NS),
      get0(NC),readin(NC,[],NS,X).
Ireadin(8,[],S,X) :- !,
     put(32),put(8),append(OS,[L],S),name(L,WC),
     get0(NC),readin(NC,WC,OS,X).
Jreadin(8,WC,S,X) :- !,
     put(32),put(8),append(OWC,[_],WC),
     get0(NC),readin(NC,OWC,S,X).
Hreadin(C,WC,S,X) :-       
      append(WC,[C],NWC),
      get0(NC),readin(NC,NWC,S,X).

D−Hは上に同じ。 IはFの作業のちょうど逆で、空白を打っていったん単語が完成したものを再び形成状態に戻す作業である。
put(32) と put(8) の作業は、画面上のカーソル位置を元に戻すためのものである註1。 JはHの作業のちょうど逆であり、単語を作っている途中で文字を一つ戻って消す場合である。 註1:put/1は、アスキーコードを入れるとその文字を画面に打つ組込み関数である。
(2)大文字小文字の処理
ヨーロッパ言語の表記法では原則として文頭は大文字で始まる。そのため、たとえばIs he a student ? と He is a student. の二文を比較してわかるように、同じ単語 is と he が一方では大文字で一方は小文字で始まる形で使われることがよく起こる。しかし機械上では文字はアスキーコードで処理されているため、このままではたとえば isとIsは同じ単語であると認識されない。このため、どちらかに統一してやる必要がある。一番簡単なのは、すべての単語を小文字で登録し、大文字で始まる語が現れた場合は、それを小文字に直すことである。そこで、リストの要素の中の大文字で始まる単語を小文字に直す以下のような関数 letter_check/2 を定義してみよう。
?-letter_chek([*Is*,he,a,student],X).
X=[is,he,a,student]

考え方:
まずリストの中から最初の文字を取り出し、それを一度アスキーコードにばらして、その最初のコードが大文字のコードであれば、それを小文字のコードに変換し、そうでなければそのままにすれば良い。これをリスト処理の手法で、再帰的に繰り返せば良い。終了条件は、リストが空になったときである。
文字をコードにばらす:組込み述語name/2を使う。
?-name(*He*,X).
X=[72,101]

大文字小文字の変換:アスキーコード は、大文字A−Z:65−90、小文字a−z:97−122.。したがって、大文字のコードに32を足せば、小文字コードに変換できる。
リストを再帰処理:入力引き数を[H|T]とおいて、一つ短いのはできたと見なす。

%%%%%%%%%%%%% 大文字の小文字への切り替え %%%%%%%%%%%%%%%%     
letter_check([H|T],[H1|TR]) :-
     name(H,[N|Nn]),
     N>=65,N=<90,!,
     N1 is N + 32,
     name(H1,[N1|Nn]),
     letter_check(T,TR).
letter_check([H|T],[H|TR]) :- !,
     letter_check(T,TR).
letter_check([],[]) :- !.

(3)短縮形処理
I*mHe*s You*re等のいわゆる短縮形も入力処理の際の問題点の一つである。辞書には、i,you,he,am,are,is 等の単語は登録されているが、短縮形自体は一つの単語でも、ましてや句などの構成素ですらないので、辞書に登録することは、できない。かといって、それをひとつづつ規則化すると繁雑で、大して意味の無い規則が増えてしまう。そこで、短縮形は、分析に入る前にあらかじめ短縮されない形に直してやる。そのためには以下のような関数、contraction/2が必要となる。
?-contraction([*you**re*, my, friend],X).
X=[you,are, my, friend]

考え方:
まずリストの中から最初の文字を取り出し、それが、短縮形として登録されているかどうか調べる。登録されていれば、それが、どう分解されるか調べ、短縮形を分解された形(以下分解形と呼ぶ)に戻す。もし短縮形でなければそのままにすれば良い。これをリスト処理の手法で、再帰的に繰り返せば良い。終了条件は、リストが空になったときである。
短縮形の登録の際に問題となるのは、短縮形と分解形の間にある関連をどうつけるかである。一つのやり方は、それぞれ別々に、しかし同じ順序で登録しておき、問題となる形が、短縮形リストの何番目にあるかを調べ、その同じ順番の所に登録してある分解形を取り出すという方法である。
ある要素がリストの何番目にあるかを調べる関数:nth_member/3
?-nth_member([a,b,c,d,e,f,g,h,i,j,k,l], X,g).
X=7

リストのn番目にある要素を取り出す関数:nth_pick_up/3
?-nth_pick_up([a,b,c,d,e,f,g,h,i,j,k,l],7,X).
X=g

%%%%%%%%%%%%%%%% 短縮形の処理 %%%%%%%%%%%%%%%%%%%%%
contraction([],[]):-!.
contraction([H|T],[H1,H2|TR]):-
     contraction_list1(L1),     
     nth_member(L1,N,H),!,
     contraction_list2(L2),
     nth_pick_up(L2,N,[H1,H2]),
     contraction(T,TR).
contraction([H|T],[H|TR]):-
     contraction(T,TR).

% 短縮形の登録(順番に注意)

contraction_list1(['i''m','i''ve','he''s','you''re','she''s','isn''t',
'aren''t','it''s','i''ll','he''ll','she''ll']).
% 短縮形を分解したもの(順番に注意)
contraction_list2([[i,am],[i,have],[he,is],[you,are],[she,is],[is,not],
[are,not],[it,is],[i,will],[he,will],[she,will]]).

% リストの何番目に含まれているか調べる
nth_member([H|T],1,H):-!.
nth_member([X|T],N1,H):-!,
     nth_member(T,N,H),
     N1 is N +1.
% リストのn番目の要素を取り出す
nth_pick_up([],_,[]).
nth_pick_up([X|T],1,X):-!.
nth_pick_up([_|T],N,X):-!,
     N1 is N -1,
     nth_pick_up(T,N1,X).

(4)入力処理のトップレベル関数

最後に以上の3つの関数を補助関数として呼び出すトップレベル関数in_put/1を定義する。
in_put(X):-
     read_sent(S1),
     letter_check(S1,S2),
     contraction(S2,X).

自然言語処理その1

文脈自由文法(context free grammar)
有限の規則で、人間の(理論的には)無限の言語生成能力を説明するモデルの代表例として句構造規則によって文法を記述しようとする句構造文法がある。
句構造文法には、様々な数学的な特徴が知られているが、その中でも左辺にたった一つの非終端記号を持ちそれを右辺に展開するいわゆる文脈自由文法には、生成された文がその文法から作られたものであるかどうかを(つまり、その文の文法構造を)有限時間内に判断するアルゴリズムが知られている。ここでは、たとえば、 Every boy who reads a book writes a program. 等の文を分析または生成することのできる単純な文脈自由文法をPrologで表現してみよう。 なお、使用する略号の意味は以下のとおりである。

s:文、np:名詞句、vp:動詞句、optrel:オプショナルな関係文、
iv:自動詞、tv:名詞句を1つしか取らない他動詞、dtv:名詞句を2つ取る他動詞、
pn:代名詞または固有名詞、n:普通名詞、relp:関係代名詞、det:冠詞類
文法1
%%% RULES %%%  
s --> np,vp.              ....................(1)
np --> pn.               ....................(2)       
np --> det,n,optrel.       ....................(3)
vp --> iv.                ....................(4)         
vp --> tv,np.             ....................(5)      
vp --> dtv,np,np.         ....................(6)   
optrel --> relp,vp.        ....................(7)    
optrel --> [].             ....................(8) 
     
%%% LEXICON %%%
pn-->[pochi].            ....................(9)
pn-->[taro].             ....................(10)      
pn-->[hanako].          ....................(11)
pn-->[i].                ....................(12)

n-->[book].              ....................(13)
n-->[program].          ....................(14)
n-->[boy].               ....................(15)
n-->[girl].               ....................(16)
det-->[a].               ....................(17)
det-->[every].           ....................(18)
det-->[the].             ....................(19)

iv --> [walks].           ....................(20)
iv --> [walk].            ....................(21)

tv --> [writes].          ....................(22)
tv --> [write].           ....................(23)
tv --> [reads].           ....................(24)
tv --> [read].            ....................(25)

dtv --> [gives].          ....................(26)
dtv --> [give].           ....................(27)

relp --> [that].          ....................(28)
relp --> [who].          ....................(29)
relp --> [which].        ....................(30)


-->というオペレータで前件と後件をつなぐこの表記は、句構造規則そのまま表現できるのでわかりやすいが、Prologのシステム内部では、通常のPrologの表記に変換され解釈されている。たとえば規則(1) s-->np,vp.は s(A,C):-np(A,B),vp(B,C).に変換される。なお、ここで、使われている二つの引き数は、一つのリストを2つの変数で表す差分リストである。したがって、規則(1)は、「 A-Cで表されたsの連鎖は、A-Bで表されたnpの連鎖とB-Cで表されたvpの連鎖に書き換えられる」ことを意味し、リストを連結するappend/3の機能が組込まれている。
以下、上記の文法がいかにしてEvery boy who reads a book writes a program.という文を生成するかを示す。右端の数字は、書換えの際適用された規則の番号である。
s --> np,vp.              
s --> det,n,optrel,vp.                                     (3)
s --> Every,n,optrel,vp.                                   (18)
s --> Every,boy ,optrel,vp.                                 (15)
s --> Every,boy, relp,vp ,vp.                                (7)
s --> Every,boy, who,vp ,vp.                                (29)
s --> Every,boy, who,tv,np ,vp.                              (5)
s --> Every,boy, who,reads,np ,vp.                           (24)
s --> Every,boy, who,reads,det,n,optrel ,vp.                  (3)
s --> Every,boy, who,reads,a,n,optrel ,vp.                    (17)
s --> Every,boy, who,reads,a,book,optrel ,vp.                  (13)
s --> Every,boy, who,reads,a,book,[ ],vp.                        (8)
s --> Every,boy, who,reads,a,book,[ ],tv,np.                      (5)
s --> Every,boy, who,reads,a,book,[ ],writes,np.                  (22)
s --> Every,boy, who,reads,a,book,[ ],writes,det,n,optrel          (3)
s --> Every,boy, who,reads,a,book,[ ],writes,a,n,optrel           (17)
s --> Every,boy, who,reads,a,book,[ ],writes,a,program,optrel     (14)
s --> Every,boy, who,reads,a,book,[ ],writes,a,program,[ ].           (8)

この例が示すように、この文法は、左側書き換えで、しかも深さ優先探索のトップダウン解析である。

自然言語処理その2

構文解析樹の表示
文法1のprogramはEvery,boy, who,reads,a,book,[ ],writes,a,program,[ ].のような文字列を文として生成あるいは分析することができたが、実際には、その結果だけが示されるだけで、その作業過程を明示することはできない。この作業過程すなわち文の構造を表示する引き数を加え、文法1を拡張してみよう。
さしあたり取り出したい構造は、下記のような構文解析樹であるが、データとしては、この構造樹に等価の構造リストを作ることにする。このリストは、適当な表示用プログラムと併用すればいつでも実際の構造樹に変換できる。
構造樹1:
                           S
          |----------------|-----------------|
          NP                                 VP 
     |----|---------|                   |----|-----|
    DET   N        REL                  TV         NP
     |    |    |----|----|              |    |-----|-----|
  every  boy that        VP          writes DET    N    REL
                    |----|----|              |     |     |
                    TV        NP             a  program  e
                    |    |----|---|
                  reads DET   N  REL
                         |    |   |
                         a   book e

一般に部分木は、その木のラベルである母節点とその母節点に支配される1つ以上の娘の部分木からなっている。したがって、母節点を第一引き数とし、娘達の構造を2つ目以降の引き数として左から順にならべたリストによって構造木の持つ構造を表現することができる。
構造樹1のイタリック体で示された部分木の部分に着目し、この部分がどのような構造リストに対応しているかを示すと以下のようになる。
        VP                                  [vp,A,B]
    |----|-----|                                A=[tv,writes]
    TV         NP                               B=[C,D,E]
         |-----|-----|   ==>                       C=[det,a]
 writes DET    N    REL                            D=[n,program
         |     |     |                             E=[rel,e]          
         a  program  e       [VP,[TV,writes],[NP,[DET,a],[N,program],[REL,e]]]     

ここで大事なのは、この構造リストの生成が、規則に1対1に対応していることである。一般に品詞を具体的な語に展開する規則φ--> [word].が適応されるときに同時に[φ,word]という構造が作られなければならない。そのため、一般に語彙項目を生成する規則φ--> [word].は以下のように改変される。
φ([φ,word])--> [word].

これに対し、一般に文法範疇だけからなる規則α-->β,γ,δ...の場合は、右辺の項のそれぞれがβ(S1),γ(S2),δ(S3)...のように構造の引き数Snを受継ぐとすると左辺のαの構造は、[α,S1,S2,S3,...]となるので、規則α-->β,γ,δ...は以下のように改変される。
α([α,S1,S2,S3,...])--> β(S1),γ(S2),δ(S3)...

以下の文法2は、文法1に構造の引き数を付け加えたものである。変数の対応関係を直感的に分かりやすくするためここでは、該当する範疇を大文字化して使っており、またラベルも引用符つきで大文字にしている。
文法2
%%% RULES %%%  
s([*S*,NP,VP]) --> np(NP),vp(VP).                        ....................(1)
np([*NP*,PN]) --> pn(PN).                                ....................(2)       
np([*NP*,DET,N,REL]) --> det(DET),n(N),optrel(REL).     ....................(3)
vp([*VP*,IV]) --> iv(IV).                                  ....................(4)         
vp([*VP,TV,NP]) --> tv(TV),np(NP).                       ....................(5)      
vp([*VP*,DTV,NP1,NP2]) --> dtv(DTV),np(NP1),np(NP2).   ....................(6)   
optrel([*REL*,RELP,VP]) --> relp(RELP),vp(VP).           ....................(7)    
optrel([*REL*,[]]) --> [].                                   ....................(8)      

%%% LEXICON %%%
pn([*PN*,pochi])-->[pochi].                                ....................(9)
pn([*PN*,taro])-->[taro].                                 ....................(10)      
pn([*PN*,hanako])-->[hanako].                           ....................(11)
pn([*PN*,i])-->[i].                                       ....................(12)

n([*N*,book]) -->[book].                                  ....................(13)
n([*N*,program]) -->[program].                           ....................(14)
n([*N*,boy]) -->[boy].                                    ....................(15)
n([*N*,girl]) -->[girl].                                    ....................(16)

det([*DET*,a])-->[a].                                     ....................(17)
det([*DET*,every])-->[every].                             ....................(18)
det([*DET*,the])-->[the].                                 ....................(19)
iv([*IV*,walks]) --> [walks].                               ....................(20)
iv([*IV*,walk]) --> [walk].                                 ....................(21)

tv([*TV*,writes]) --> [writes].                              ....................(22)
tv([*TV*,write]) --> [write].                                ....................(23)
tv([*TV*,reads]) --> [reads].                               ....................(24)
tv([*TV*,read]) --> [read].                                 ....................(25)

dtv([*DTV*,gives]) --> [gives].                             ....................(26)
dtv([*DTV*,give]) --> [give].                               ....................(27)
 
relp([*RELP*,that])--> [that].                              ....................(28)
relp([*RELP*,who]) --> [who].                             ....................(29)
relp([*RELP*,which]) --> [which].                          ....................(30)

自然言語処理その3

文脈自由文法の補強(文法素性+文脈自由文法)
文法2は、英語の文を生成する文法としては、まだ制限が余りにゆるすぎる。その結果、たとえば、以下のような非文法的な文が産み出される。
a) *Every boy read a book.
b) *The girl likes I.
c) *Every boy which reads a book write a program.

これらはそれぞれ主語と動詞の一致(agreement)、他動詞の格支配、関係代名詞と先行詞の一致の問題であり、それには、性・数・格の情報やある名詞がhuman等の特定の意味指標を持っているかの情報が関係する。これらの文法的な情報を文脈自由文法に付け加え、Prologのユニフィケーション(単一化)機能を利用してそれらの情報がお互いに許容しあう規則の適用のみを許可することによって、文脈自由文法を補強することができる。上記a)-c)の文を排除するためにさしあたり必要な文法素性は、以下の3つである。

性(Gender):masculine,feminine,neuter
数(Number):plural,singluar
格(Case)  :nominative,accusative
人称(Person):1,2,3
その他      :+human,-human

これらの素性をそれぞれ以下の略号で表すことにする。
組成項目     略号             値
   性         Gen        mas,fem,neu
   数         Num         plur,sing
   格         Case          nom,acc
  人称        Pers           1,2,3
  人間        Hum         +hum,-hum

これらの素性とその値の登録の仕方であるが、必要とされる素性の数が増大することに対応するため、まず、登録素性全体をリストの形でまとめることにする。(この引き数の順序はいったんこうと決めたらプログラム全体の中で一貫させておかなければならない。忘れると困るのでプログラム上にメモしておいたほうがいい。(例: 文法素性の登録順序は[性,数,格,人称,人間]です))この素性リストは、第1引き数として直接入力しても良い(実際その方が効率も良い)が、ここではプログラムを見やすくするため、第1引き数にはGF等の変数だけを入れ、その実際の値は、書換え規則の後に定義することにする。書換え規則の部分と区別するため、この部分は、半角の波括弧({})で囲む。以上の手順で文法2の規則(12)と(14)を書き換えると以下のようになる。なお、ここでは、不要な変数は、無記名変数(半角の下線)のままにしてある。

pn(GF,[*PN*,i])  -->  [i],{ GF=[_,sing,nom,1,+hum]}.              ......(12)
n(GF, [*N*,program])  -->  [program],{ GF=[n,sing,_,3,-hum]}.   ......(14)

この素性リストを使えば非文a)-c)が排除できることを以下に示す。

s(GF1,[*S*,NP,VP])  -->  np(GF1,NP), vp(GF2,VP),
           {GF1=[_,Num,nom,Pers,Hum],
            GF2=[_,Num,_,Pers,Hum]}.                       .......(1)

非文a)で問題となった主語と動詞間での数と人称の一致は、双方が同じ引き数NumとPersとを共有しあうことによって保証される。なお、主語が主格であることはnpの素性リストGF1の第3引き数であるnomによって示され、動詞による主語の意味的な選択制限は、Humという引き数の素性によって示される。
vp(GF1,[*VP,TV,NP])  -->  tv(GF1,TV),np(GF2, NP),
           {GF2=[_,_,acc,_,_]}.                               .......(5)      

非文b)で問題となった他動詞の目的語が目的格であることは、規則(5)の右辺にあるnp素性リストGF2の第3引き数accによって示されている。他動詞の素性はそのまま動詞句に受継がれる。
optrel(GF1, [*REL*,RELP,VP])  -->  relp(GF2, RELP), vp(GF3, VP),
          {GF1=[_,Num,_,3,Hum],
           GF2=[_,Num,nom,3,Hum],
           GF3=[_,Num,_,3,Hum]}.           ..........(7)    

非文c)で問題となった関係代名詞の意味的な選択制限は、規則(7)の素性リストの第4引き数Humの一致によって示される。なお、主格関係代名詞と動詞句の間には、主語・動詞間と同じ一致が必要となる。関係代名詞の素性は、そのまま関係文の素性に受継がれる。
これらの素性を付け加えて、文法2を補強したものが文法3である。
文法3
%%% RULES %%%  
s(GF1,[*S*,NP,VP])  -->  np(GF1,NP), vp(GF2,VP),
                {GF1=[_,Num,nom,Pers,Hum],
                GF2=[_,Num,_,Pers,Hum]}.                    ........(1)
np(GF,[*NP*,PN]) --> pn(GF,N).                                 ........(2)       
np(GF,[*NP*,DET,N,REL]) --> 
                det(GF,DET),n(GF,N),optrel(GF,REL).          ........(3)
vp(GF,[*VP*,IV]) --> iv(GF,IV).                                  ........(4)         
vp(GF1,[*VP,TV,NP])  -->  tv(GF1,TV),np(GF2, NP),
                {GF2=[_,_,acc,_,_]}.                            ........(5)      
vp(GF1,[*VP*,DTV,NP1,NP2]) -->
                dtv(GF1,DTV),np(GF2,NP1),np(GF3,NP2),
                {GF2=[_,_,acc,_,_],GF3=[_,_,acc,_,_]}.            ........(6)
optrel(GF1, [*REL*,RELP,VP])  -->  relp(GF2, RELP), vp(GF3, VP),
                {GF1=[_,Num,_,3,Hum],
                GF2=[_,Num,nom,3,Hum],
                GF3=[_,Num,_,3,Hum]}.                       ........(7)    
optrel(GF,[*REL*,[]]) --> [].                                      ........(8)      
  
%%% LEXICON %%%
pn(GF,[*PN*,pochi])-->[pochi], { GF=[n,sing,_,3,-hum]}.            ........(9)
pn(GF,[*PN*,taro])-->[taro] ,{ GF=[m,sing,_,3,+hum]}.            ........(10)      
pn(GF,[*PN*,hanako])-->[hanako], { GF=[f,sing,_,3,+hum]}.      .........(11)
pn(GF,[*PN*,i])  -->  [i],{ GF=[_,sing,nom,1,+hum]}.            .........(12)

n(GF, [*N*,book])  -->  [book],{ GF=[n,sing,_,3,-hum]}.          ........(13)
n(GF, [*N*,program])  -->  [program],{ GF=[n,sing,_,3,-hum]}.    .......(14)
n(GF, [*N*,boy])  -->  [boy],{ GF=[m,sing,_,3,+hum]}.            .......(15)
n(GF, [*N*,girl])  -->  [girl],{ GF=[f,sing,_,3,+hum]}.             .......(16)

det(GF,[*DET*,a])-->[a], { GF=[_,sing,_,3,_]}.                     .......(17)
det(GF,[*DET*,every])-->[every], { GF=[_,_,_,3,_]}.                .......(18)
det(GF,[*DET*,the])-->[the], { GF=[_,_,_,3,_]}.                    .......(19)

iv(GF,[*IV*,walks]) --> [walks] , { GF=[_,sing,_,3,_]}.              .......(20)
iv(GF,[*IV*,walk]) --> [walk],
                { GF=[_,Num,_,Pers,_],not_sg3(GF)}.            .......(21)

tv(GF,[*TV*,writes]) --> [writes] , { GF=[_,sing,_,3,_]}.              .......(22)
tv(GF,[*TV*,write]) --> [write],
                { GF=[_,Num,_,Pers,_],not_sg3(GF)}.             .......(23)
tv(GF,[*TV*,reads]) --> [reads] , { GF=[_,sing,_,3,_]}.                .......(24)
tv(GF,[*TV*,read]) --> [read], 
                { GF=[_,Num,_,Pers,_],not_sg3(GF)}.              ......(25)

dtv(GF,[*DTV*,gives]) --> [gives] , { GF=[_,sing,_,3,_]}.               ......(26)
dtv(GF,[*DTV*,give]) --> [give],
                { GF=[_,Num,_,Pers,_],not_sg3(GF)}.              ......(27)

relp(GF,[*RELP*,that])--> [that], { GF=[_,_,_,3,_]}.                  ......(28)
relp(GF,[*RELP*,who]) --> [who], { GF=[_,_,_,3,+hum]}.             ......(29)
relp(GF,[*RELP*,which]) --> [which], { GF=[_,_,_,3,-hum]}.          ......(30)
% 3人称単数ではないことの確認
not_sg3([_,sing,_,1|_]).           % 1人称単数 
not_sg3([_,sing,_,2|_]).           % 2人称単数
not_sg3([_,plur|_]).              % 複数

自然言語処理その4

辞書の記述を簡略化する手法
文法3の辞書項目の記述を見ると、同じ品詞に関して言えば、くり返しが多い。たとえば、普通名詞bookとboyの辞書情報である規則(13)と(15)では、下線部以外は、すべて同じ情報である。
n(GF, [*N*,book])  -->  [book],{ GF=[n,sing,_,3,-hum]}.     ........(13)
n(GF, [*N*,boy])  -->  [boy],{ GF=[m,sing,_,3,+hum]}.         .......(15)

ここでは、こうした辞書項目の冗長性を改善し、辞書項目の記述を簡略化する方法について考える。辞書に単語を登録する際必要となるのは、登録単語の語形およびその単語の持つ文法素性である。

文法素性リストのパターン化と参照番号の付与
まず文法素性についてであるが、その多くは単語の品詞が決まることによって自動的に決まり、全体としても一定のパターンに納まるのが普通である。たとえば、普通名詞の場合Caseが未定であることおよびPersonが3であることは、品詞から自動的にわかる。問題になるのは、NumberとGenderとHumanについての情報だけである。したがって、この部分の可能な組み合わせから必要となる普通名詞の文法素性のパターンをあらかじめ、以下のfeature/2のような関数名で登録しておけば、そのどのパターンになるかという情報だけを辞書登録の際に与えてやるだけで、必要な文法素性リストを取り出すことができる。
%%% 普通名詞の素性パターン
feature(1,[[n,sing,_,3,-hum],[_,plur,_,3,-hum]]).         % 例:book,books
feature(2,[[m,sing,_,3,+hum],[_,plur,_,3,+hum]]).        % 例:boy,boys
feature(3,[[f,sing,_,3,+hum],[_,plur,_,3,+hum]]).         % 例:girl,girls
feature(4,[[_,sing,_,3,+hum],[_,plur,_,3,+hum]]).        % 例:child,children

ここで、feature/2の第1引き数は、素性パターンにアクセスするための整理番号であり、第2引き数のリストにはそれぞれ、単数形と複数形の素性が入っている。単語登録の際に単数形と複数形を一緒に登録するほうが、都合良いので、素性リストfeature/2でも一つの関数で単数形と複数形の両方の素性にアクセスできるようにしてある。

2)Preterminal RuleとLexiconの分離
素性パターンの分離登録によって、実際に辞書に登録する普通名詞のデータは以下のようになる。登録項目は、登録単語の語形そのものとその単語の文法素性リストを参照するための番号に限られる。
% 普通名詞の辞書データ
n([book,books],1).
n([program,programs],1).
n([boy,boys],2).
n([girl,girls],3).
n([child,children],4).

辞書のスリム化の最後のステップは、この情報から、規則(13)や(15)と同じような辞書レベルの書換え規則をどのようにして作るかということである。さきほど下線で示したように、これら辞書レベルの規則では、登録単語の部分と文法素性の部分をそれぞれ変数で置き換えてやれば、規則自体を一般化することが可能である。言い換えると、たとえば、規則(13)には、1)語形(Word)がbookであり文法素性(GF)が[n,sing,_,3,-hum]であるという情報の他に、2)それらの情報が、n(GF, [*N*,Word]) --> [Word],{ ........ }.という一般形で表現される条件を満たさなければいけないという情報を含んでいる 。ここでこの後者の情報を個々の辞書レベル情報から切り離し、 Preterminal Ruleとして独立させてやれば、辞書レベルで書換規則を繰り返す必要はなくなる。以下は、普通名詞のPreterminal Ruleの例である。はじめの規則が単数形、2つ目が複数形の単語の分析・生成に必要となる。
n(GF,['N',Word])-->[Word], {n([Word,_],N),feature(N,[GF,_])}.
n(GF,['N',Word])-->[Word], {n([_,Word],N),feature(N,[_,GF])}.

以上の原則の本に、文法3の辞書部分を改善したものが、以下の文法4である。(登録単語数は若干増えている)。
文法4(部分)
%%%%%%%%%% PRETERMINAL RULE & LEXIKON %%%%%%%%%%
%%% 素性パターンの登録
% 普通名詞&固有名詞
feature(1,[[n,sing,_,3,-hum],[_,plur,_,3,-hum]]).         % 例:book,books
feature(2,[[m,sing,_,3,+hum],[_,plur,_,3,+hum]]).       % 例:boy,boys
feature(3,[[f,sing,_,3,+hum],[_,plur,_,3,+hum]]).        % 例:girl,girls
feature(4,[[_,sing,_,3,+hum],[_,plur,_,3,+hum]]).        % 例:child,children
% 人称代名詞
feature(5,[[n,sing,nom,3,-hum],[_,plur,nom,3,-hum]]).    % 例:it,they
feature(6,[[n,sing,acc,3,-hum],[_,plur,acc,3,-hum]]).      % 例:it,them
feature(7,[[m,sing,nom,3,+hum],[_,plur,nom,3,+hum]]).  % 例:he,they
feature(8,[[m,sing,acc,3,+hum],[_,plur,acc,3,+hum]]).     % 例:him,them
feature(9,[[f,sing,nom,3,+hum],[_,plur,nom,3,+hum]]).    % 例:she,they
feature(10,[[f,sing,acc,3,+hum],[_,plur,acc,3,+hum]]).     % 例:her,them
feature(11,[[_,sing,_,2,_],[_,plur,_,2,_]]).                 % 例:you,you
feature(12,[[_,sing,nom,1,+hum],[_,plur,nom,1,+hum]]).  % 例:I,we
feature(13,[[_,sing,acc,1,+hum],[_,plur,acc,1,+hum]]).    % 例:me,us
% 冠詞&所有格&関代
feature(14,[_,sing,_,3,_]).                          % 例:a,every
feature(15,[_,_,_,3,_]).                             % 例:the,my,that
feature(16,[_,_,_,3,+hum]).                         % 例:who
feature(17,[_,_,_,3,-hum]).                         % 例:which
feature(18,[_,_,acc,3,+hum]).                       % 例:whom
% 動詞
feature(19,[[_,sing,_,3,+hum],[_,Num,_,Pers,+hum]]).    % 例:reads,read
feature(20,[[_,sing,_,3,_],[_,Num,_,Pers,_]]).             % 例:walks,walk

%%% PRETERMINAL RULE & LEXIKON %%%
% 代名詞&固有名詞
pn(GF,['PN',Word])-->[Word], {pn([Word,_],N),feature(N,[GF,_])}.
pn(GF,['PN',Word])-->[Word], {pn([_,Word],N),feature(N,[_,GF])}.

pn([japan,'-'],1).
pn([pochi,'-'],1).
pn([taro,'-'],2).
pn([hanako,'-'],3).
pn([it,they],5).
pn([it,them],6).
pn([he,they],7).
pn([him,them],8).
pn([she,'-'],9).      % she の pl形 they は he の pl 形と同じ。登録不要
pn([her,'-'],10).     % her の pl形 them は him の pl 形と同じ。登録不要
pn([you,you],11).
pn([i,we],12).
pn([me,us],13).

% 普通名詞
n(GF,['N',Word])-->[Word], {n([Word,_],N),feature(N,[GF,_])}.
n(GF,['N',Word])-->[Word], {n([_,Word],N),feature(N,[_,GF])}.

n([book,books],1).
n([pen,pens],1).
n([dog,dogs],1).
n([program,programs],1).
n([boy,boys],2).
n([girl,girls],3).
n([child,children],4).
n([parent,parents],4).

% 冠詞&所有格
det(GF,['DET',Word])-->[Word], {det(Word,N),feature(N,GF)}.

det(a,14).
det(every,14).
det(the,15).
det(my,15).
det(you,15).
det(her,15).
det(his,15).
det(its,15).
det(their,15).
det(our,15).

% 自動詞
iv(GF,['IV',Word]) --> [Word] , {iv([Word,_],N),feature(N,[GF,_])}.
iv(GF,['IV',Word]) --> [Word] , {iv([_,Word],N),feature(N,[_,GF]),not_sg3(GF)}.
iv([walks,walk],20).
iv([sleeps,sleep],20).

% 目的語を1つ取る他動詞
tv(GF,['TV',Word]) --> [Word] , {tv([Word,_],N),feature(N,[GF,_])}.
tv(GF,['TV',Word])--> [Word] , {tv([_,Word],N),feature(N,[_,GF]),not_sg3(GF)}.

tv([likes,like],20).
tv([reads,read],19).
tv([writes,write],19).

% 目的語を2つ取る他動詞
dtv(GF,['DTV',Word]) --> [Word] , {dtv([Word,_],N),feature(N,[GF,_])}.
dtv(GF,['DTV',Word])-->[Word] ,
                      {dtv([_,Word],N),feature(N,[_,GF]),not_sg3(GF)}.
dtv([gives,give],20).
dtv([sends,send],20).

% 関係代名詞
relp(GF,['RELP',Word])--> [Word], {relp(Word,N),feature(N,GF)}.
relp(that,15).
relp(who,16).
relp(which,17).
relp(whom,18).

3)意味素性の扱い
文法3や文法4では省略したが、素性Human(人間であることを示す)の値を単純に+hum,-humとするのには、若干の問題がある。というのは、ここでは、この素性は、関係代名詞のwhoとwhichの使い分けを示す純粋な文法素性として使っているだけでなく。たとえば、文法3の規則(1)でのように、動詞の選択制限素性(すなわち意味素性)としても使っているからである。意味素性という観点からは、±による単純な2値素性ではなく、たとえば、read,writeのような高度な知的活動を前提にする動詞や、like,goのように、主体が生命体であることを前提にする動詞や、fall,flyのように具対物を主語として要求する動詞等を考慮しhuman,animate,concrete等の段階的で内包関係にある素性が必要となる。(時間の関係でここでは問題点を指摘するだけに留める。)
4)登録単語の一覧表示
登録単語数が増えるにしたがい、登録単語が一目でわかるようなリストアップの述語があると便利である。以下のlist_up_words/0は、組込み述語のwriteとfailを使った、fail loop により、n/2,pn/2,iv/2,tv/2,dtv/2,det/2,relp/2の値がある限り、すべての第1引き数ないしはその一部を画面上に表示していく。最後の関数は、この関数をyesで終了させるためのものである。
%%% 登録単語の一覧表示 %%%
list_up_words:- nl,
     write('%%% 主要登録単語一  覧 *),nl,nl,
     write(' *** 普通名詞:'), n([Noun,_],_),write(Noun),write(','),fail.

list_up_words:- nl,
     write(' *** 固有名詞&代名詞:'),
     pn([PN1,PN2],_),write_data(PN1),write_data(PN2),fail.
write_data('-'):-!.
write_data(DATA):-write(DATA),write(',').

list_up_words:- nl,
     write(' *** 自動詞:'), iv([_,Verb],_),write(Verb),write(','),fail.
list_up_words:- nl,
     write(' *** 他動詞:'),tv([_,Verb],_),write(Verb),write(','),fail.
list_up_words:- 
     dtv([_,Verb],_),write(Verb),write(','),fail.

list_up_words:- nl,
     write(' *** 冠詞&所有格:'), det(Det,_),write(Det),write(','),fail.

list_up_words:- nl,
     write(' *** 関係代名詞:'), relp(Rel,_),write(Rel),write(','),fail.

list_up_words.

自然言語処理その5

助動詞の導入
1)動詞形態に関する素性
英語の文には助動詞を使ったものが多い。特に疑問文や否定文などでは、 doなどの助動詞(auxiliary)が必要となる。ここでは、以下のような助動詞を含んだ文を受け付けるように文法4を拡張することを考える。
a)The boy must have read the book.
b)He was writing the program.
c)I*ll give you the book.

助動詞において、まず問題となるのは、助動詞が、一定の時制や形態(以後これらを総称して動詞形態と呼ぶ)を持った動詞を要求することである。たとえば、進行形を作る助動詞beは動詞の現在分詞(いわゆるing形)を要求するのに対し、完了形を作る助動詞haveは過去分詞を必要とする。またcan,will等の様相の助動詞(modal auxiliary)は動詞の原形を要求する。しかもこれらの助動詞自体が、また、特定の動詞形態や活用形を持ち、上記の例文a)のhaveのように別の助動詞の中に埋めこまれる場合もある。ただし、3人称単数形である等の活用形に関する情報はすでに人称や数に関する素性によって区別できる ので、ここで新たに導入する必要があるのは、動詞形態に関する素性に限られる。
なお、下の表で、略号で表されている値は、それぞれ現在(present tense)、過去(past tense)、過去分詞(past participle) 、現在分詞(present participle)および原形(infinitive)の5つである。
素性項目        略号                     値
動詞形態       VFORM              pres,past,pp,ppr,inf

動詞の場合動詞形態に関する素性はこれだけで良いが、問題は、助動詞である。というのは、既に述べたように、助動詞の場合どのような動詞形態を要求するかという情報と、自らがどのような動詞形態であるかという情報の2つを一つの素性で表す必要があるからである。こうした2重の関係を表現するために数学の乗除計算の一般式(例:a=a/b・b)になぞらえた表現がよく利用される。この方式の長所は、要求する動詞形態をスラッシュの右側すなわち分母として取り、自らの動詞形態をスラッシュの左側すなわち分子にすれば、要求された動詞形態が現れたときに、分子すなわち自らの動詞形態だけを計算(すなわち約分)の結果として残すことができる点である。以下にその例をあげる。
       vp        =       auxiliay          ・    verb 1          例
      過去       =     過去/現在分詞       ・  現在分詞   were  reading
      現在       =       現在/原形         ・    原形       can  read 

この方式で表すと助動詞の動詞形態素性は以下のようになる。
素性項目        略号                     値
動詞形態       VFORM    pres/pp,past/pp,pp/pp,ppr/pp,inf/pp
                        pres/ppr,past/ppr,pp/ppr,ppr/ppr,inf/ppr
                        pres/inf,past/inf,pp/inf,ppr/inf,inf/inf

なお、このように文法的な関係を(理想的に)はたった2つの単純カテゴリーの擬似計算式で表す方式はカテゴリー文法の伝統に由来する。
2)活用形であるかどうかについての素性
動詞・助動詞に関してもう一つ重要になる素性は、それが活用形であるかどうかという情報である。一般に、助動詞は、人称や数や時制に関して活用した形でない動詞句を要求する。上の素性で言えば、スラッシュの右側に来ることができるのは、ppとpprとinfであって、これらはどれも人称、数、時制に関して何の限定も持たない 。それに対し、一般にnpがvpと結び付いてsができる際、そのvpのheadは、常に人称や数や時制に関して活用した形でなければならない。この条件を動詞に関するもう一つの素性として導入する。
素性項目        略号                     値
活用形1          FIN                  +fin,-fin

ここでは活用形と非活用形(いわゆる原形)の二つをそれぞれ±finで区別している。動詞形態と活用形の素性により、文法4がどのように変化するかを以下に見ていこう。

3)辞書レベルでの動詞・助動詞の扱い
まず動詞の辞書データでは、登録しやすいように5つの語形を列挙することにする。語形の登録順は、3人称単数現在形,現在形,過去形,過去分詞,現在分詞である。なお、原形は、現在形と同じなので語形としては特別に登録する必要はなく、素性のレベルでのみ区別してやれば良い。

tv([reads,read,read,read,reading],19).

動詞の辞書データが変更されたことに伴い、素性参照番号19によって参照される素性feature/2の第2引き数の素性リストの要素の数も、2から6に増える。素性リストの要素は、前から順に3人称単数現在形,現在形,過去形,過去分詞,現在分詞,原形の6つである。
% 一般動詞の素性:3人称単数現在,現在,過去,過去分詞,現在分詞,原形
feature(19,[[_,sing,_,3,+hum,pres,+fin],[_,_,_,_,+hum,pres,+fin],
           [_,_,_,_,+hum,past,+fin],[_,_,_,_,+hum,pp,-fin],
           [_,_,_,_,+hum,ppr,-fin],[_,_,_,_,+hum,inf,-fin]]). 

この登録素性と辞書データから必要な単語レベルの規則を作るために、名詞を一つだけ取る他動詞のpreterminal ruleも次のように変更される。
tv(GF,['TV',Word]) --> [Word],{tv([Word,_,_,_,_],N),
     feature(N,[GF,_,_,_,_,_])}.                          % 3人称単数
tv(GF,['TV',Word]) --> [Word],{tv([_,Word,_,_,_],N),
     feature(N,[_,GF,_,_,_,_]),not_sg3(GF)}.              % 現在形
tv(GF,['TV',Word]) --> [Word],{tv([_,_,Word,_,_],N),
     feature(N,[_,_,GF,_,_,_])}.                          % 過去形
tv(GF,['TV',Word]) --> [Word],{tv([_,_,_,Word,_],N),
     feature(N,[_,_,_,GF,_,_])}.                          % 過去分詞
tv(GF,['TV',Word]) --> [Word],{tv([_,_,_,_,Word],N),
     feature(N,[_,_,_,_,GF,_])}.                          % 現在分詞
tv(GF,['TV',Word]) --> [Word],{tv([_,Word,_,_,_],N),
     feature(N,[_,_,_,_,_,GF])}.                          % 原形

助動詞の扱いは原則としては、動詞と変わらない。動詞との違いは、助動詞の種類によっては、いくつかの語形が欠落しているものがあることである。助動詞自身をそれが持つ語形の数をもとに分類すると以下の5つになる。
(1)現在形と過去形のみのもの
can,will,must,may,shall
(2)3人称現在形と現在形と過去形のみのもの
do
(3) 3人称単数現在形と現在形と過去形と現在分詞形と原形を持つもの
have
(4)be動詞型の語形を持つもの
copulaとしてのbe,進行形を導くbe
(5)1種類の語形しか持たないもの
to

以下には、(1)に属する助動詞canの辞書データと登録素性およびpreterminal ruleをあげる。canのタイプの助動詞(modal auxiliary)は、人称と数に関して、特別な指定を持たないが、それが分詞とは異なり、活用形であることは、素性リストの最後の要素である+finから読み取れる。
% can の辞書データ
aux([can,could],23).

% 助動詞can,will,must,may,shall の登録素性
feature(23,[[_,_,_,_,_,pres/inf,+fin],
           [_,_,_,_,_,past/inf,+fin]]).

% 助動詞can,will,must,may,shall のpreterminal rule
aux(GF,['AUX',PRES]) --> [PRES],{aux([PRES,_],N),
     feature(N,[GF,_])}.
aux(GF,['AUX',PAST]) --> [PAST],{aux([_,PAST],N),
     feature(N,[_,GF])}.

4)句構造規則上での動詞・助動詞の扱い
文法5(部分)
s([Tens|GF1],['S',NP,VP])  -->  np(GF1,NP), vp(GF2,VP),
                {GF1=[_,Num,nom,Pers,Hum],
                 GF2=[_,Num,_,Pers,Hum,Tens,+fin]}.

ここでの文法4との違いは、文が必ず一つの活用形を持つことが、vpの素性リストGF2の第7要素+finで示されていることである。これとは逆に、助動詞が下位のvpのheadとして常に非活用形を取ることは、下の規則で、下位のvpの文法素性GF3の第7要素が-finになっていることで示される。この規則の右辺と左辺に同じvpが来ていることからわかるようにこの規則は再帰的に適応され得るので、助動詞を複数持つ文も生成することができる。一方動詞形態に関する素性について言えば、auxの文法素性の第6要素であるTens/VFORMのスラッシュの左側がより上位のvpに受継がれることによって、 p.24で示したカテゴリー文法の考え方がプログラム上に移されている。
vp(GF1,['VP',AUX,VP]) --> aux(GF2,AUX),vp(GF3,VP),         
                {GF1=[_,Num,_,Pers,Hum,Tens,FIN],
                 GF2=[_,Num,_,Pers,Hum,Tens/VFORM,FIN],
                 GF3=[_,_,_,_,Hum,VFORM,-fin]}.

5)copulaとしてのbeの扱い

最後に、copula(=連結詞)としてのbe(いわゆるbe動詞)の扱いについて簡単に触れる。copulaとしてのbeは一般に動詞の一種と見なされているが、その文法的な特性(1.倒置によって疑問文を作る,2.notと共にそのまま否定文を作れる,3.そのまま付加疑問文を作れる等)からすると、むしろ助動詞と考えた方が都合がいい。その場合本動詞としては、音形の無い動詞を仮定する。またこの動詞の動詞形態についての素性として、先に仮定したVFORMの値 pres,past,pp,ppr,inf のほかに、音形の無い動詞をあらわすnoneを新たに導入する。 VFORM の値としてnoneを取る動詞を導入する規則をあげると以下のようになる。ここでこの動詞が音形を持たないことは、規則の右辺の左端の空リスト [ ] によって示されている。
 copulaとしてのbe動詞(助動詞)と共起する音形の無い動詞
v(GF,['V','[]']) --> [],{GF1=[_,_,_,_,_,none,_]}.

copulaとしての助動詞beは、noneを持った動詞を要求するので助動詞にも、noneを含む以下のような系列の動詞形態素性を加える必要がある。
copulaとしてのbe(助動詞)の動詞形態
素性項目        略号                     値
動詞形態       VFORM    pres/none,past/none,pp/none,ppr/none,inf/none

beと一般動詞のもう一つの大きな違いは、beがより多くの明示的な活用形を持つことである。beの場合、3人称単数現在だけでなく、1人称単数現在、1および3人称単数過去も新たに区別する必要がある。したがって登録素性のパターンやpreterminal ruleが増えるだけでなく、人称と数に一定のチェックを加える関数として、従来のnot_sg3/1に加え、新たにsg13/1とnot_sg13/1を加える必要が出てくる。この点は、現在進行形を導く助動詞のbeも copulaとしての助動詞 beも同じである。この2つのbeの処理のために必要となったプログラム(部分)をあげると以下のようになる。
% 助動詞beの辞書データ
aux([am,is,are,was,were,been,being,be],21). % copulaとしてのbe
aux([am,is,are,was,were,been,being,be],26). % 進行形を導くbe

% copula としての 助動詞be の素性リスト
% (1人称単数現在,3人称単数現在,現在,1・3人称単数過去,それ以外の過去,
% 過去分詞,現在分詞,原形)
feature(21,[[_,sing,_,1,_,pres/none,+fin],[_,sing,_,3,_,pres/none,+fin],
           [_,_,_,_,_,pres/none,+fin],
           [_,sing,_,_,_,past/none,+fin],[_,_,_,_,_,past/none,+fin],
           [_,_,_,_,_,pp/none,-fin],[_,_,_,_,_,ppr/none,-fin],
           [_,_,_,_,_,inf/none,-fin]]).                      % 例:am/is/are

% 進行形を導く助動詞beの素性リスト
feature(26,[[_,sing,_,1,_,pres/ppr,+fin],[_,sing,_,3,_,pres/ppr,+fin],
           [_,_,_,_,_,pres/ppr,+fin],
           [_,sing,_,_,_,past/ppr,+fin],[_,_,_,_,_,past/ppr,+fin],
           [_,_,_,_,_,pp/ppr,-fin],[_,_,_,_,_,ppr/ppr,-fin],
           [_,_,_,_,_,inf/ppr,-fin]]).                        % 例:am/is/are

% 助動詞 beの preterminal rule
aux(GF,['AUX',SG1]) --> [SG1],{aux([SG1,_,_,_,_,_,_,_],N),
     feature(N,[GF,_,_,_,_,_,_,_])}.
aux(GF,['AUX',SG3]) --> [SG3],{aux([_,SG3,_,_,_,_,_,_],N),
     feature(N,[_,GF,_,_,_,_,_,_])}.
aux(GF,['AUX',PRES]) --> [PRES],{aux([_,_,PRES,_,_,_,_,_],N),
     feature(N,[_,_,GF,_,_,_,_,_]),not_sg3(GF)}.
aux(GF,['AUX',PAST13]) --> [PAST13],{aux([_,_,_,PAST13,_,_,_,_],N),
     feature(N,[_,_,_,GF,_,_,_,_]),sg13(GF)}.
aux(GF,['AUX',PAST]) --> [PAST],{aux([_,_,_,_,PAST,_,_,_],N),
    feature(N,[_,_,_,_,GF,_,_,_]),not_sg13(GF)}.
aux(GF,['AUX',PP]) --> [PP],{aux([_,_,_,_,_,PP,_,_],N),
     feature(N,[_,_,_,_,_,GF,_,_])}.
aux(GF,['AUX',PPR]) --> [PPR],{aux([_,_,_,_,_,_,PPR,_],N),
     feature(N,[_,_,_,_,_,_,GF,_])}.
aux(GF,['AUX',INF]) --> [INF],{aux([_,_,_,_,_,_,_,INF],N),
     feature(N,[_,_,_,_,_,_,_,GF])}.

% cf.1・3人称単数でないことの確認のため:were
not_sg13([_,sing,_,2|_]).
not_sg13([_,plur|_]).
% cf.1・3人称単数であることの確認のため: was
sg13([_,sing,_,1|_]).
sg13([_,sing,_,3|_]).


自然言語処理その6

“移動しているように見える構成素”の処理
1)問題の所在
これまでは主格の関係代名詞を含む文だけを扱っていたが、それ以外の関係文の中には、一見すると、あたかも文の中の要素が、移動されているように見えるものがある。すなわち通常の文ならば本来あるべきところにその要素が無く、それが関係代名詞として文頭に移動されているようにみえるのである。変形文法では、これは、いわゆるwh移動と呼ばれ、移動した要素は、移動元に痕跡(trace、通常t と略す)を残すとされる。以下にその例をあげる(例1)。なお、例2は語順の比較のためにあげた平叙文の主文である。
例1:I know the girl whom he gave [ t ]the book.
例2:He gave the girl the book.

同じ様な現象は、主格以外の疑問詞を含む文の中にも見られる。
例3:Who do you like [t ] ?
例4:Do you like her ?

そもそもいわゆる変形生成文法が提唱されて来た背景にはこうした移動を伴う現象は、単なる句構造規則で表すことができないという前提があった。しかし移動という変形操作は非常に強力なものであり、これによってほとんどすべての現象が説明できるかわりに、文法規則に関する制限が緩くなり、ある与えられた文がその言語の文法から生成できるものかどうかを有限の時間内に判断することができない場合も生じることとなった。実際には、変形規則の適用には、大きな条件が課せられることになったが、それにしても、変形は、それを適用可能にする一定の条件を必要とし、したがって、手続きの順序に依存する弱点があった。それに対し、これまで見て来たような、素性によって制限された文脈自由文法の規則では、素性の一致は一致素性が突き合わされたときにはじめて起こり、その方向性や一致の順序にあらかじめ指定が無かった。規則に変形を導入するということは、効率という意味でも、理論的な一貫性という意味でも、構文解析上のアルゴリズムという意味でも大きな後退であり、機械処理上はできれば避けたいことである。以下には、一見移動にみえる現象をどのようにして、句構造規則の形で表現するかについて考える。
2)gapに関する素性
移動でないとする限りは、そこに何かがあると仮定することになる。上の例では、痕跡とされるところに見えない要素(gap)があると仮定する。gapは、本来そこにあるべき要素と同じ文法素性を持つことになり、見えない構成素(すなわち空リスト)を産み出す規則の中で導入される。なお、gapの品詞とその文法素性を一組のユニットとするgap素性は、独自の引き数によって規則の中で受継がれる。gap素性は、通常のリストの要素として表現してもよいが、ここでは、効率等の理由で、差分リストの要素の形で表すことにする。
NP-gapを導入する規則をあげると以下のようになる。

np([[gap(np),GF]|GAP]-GAP,GF,['NP/NP','φ']) --> [].

第1引き数のgap素性は差分リスト[[gap(np),GF]|GAP]-GAP で表されているが、実質的には[[gap(np),GF]]である。関数gap/1の引き数であるnpによってこのgapの品詞が表現され、GFが第2引き数にある文法素性GFと同じ変数であることによってこのnp使われる際の文法素性がgap素性の中で受継がれる。gapの構造は、節点として通常のNPではなくNP/NPが使われしかもそれがφを支配することによって示される。(註:構造の表記にスラッシュ(/)が使われることから、gap素性は、しばしばslash素性とも呼ばれる。)また、これが音形を持たない語であることは、右辺の空リスト[ ]によって表される。これに対し、たとえばnpをpnに展開するようなgapを含まない規則の場合は、gap素性は空リストGAP-GAPによって表される。

np(GAP-GAP,GF,['NP',PN]) --> pn(GF,PN).

gapがある限りそのgapを含む句はまだ完全ではない。文法的に完全な句になるためには、いずれかの時点でgapの持つ素性を満足する構成素が来なければならない。これは、たとえば関係代名詞や疑問詞とこれらの句が結合される句構造規則の中で実現される。以下にgapを含む文の例としてI read every book which he gave meの構造樹をあげる。
     S
 |---|----|
NP       VP
 |   |----|-----|
PN  TV         NP
 |   |    |-----|--------|
 i read  DET    N       REL
          |     |    |---|----|
        every book RELP     S/NP
                     |    |---|---|
                   which NP     VP/NP
                          |   |---|---|
                         PN  DTV NP NP/NP
                          |   |   |   |
                         he gave PN  φ
                                  |
                                 me

ここでは、gap(正確には、Np-gap)を含む構造を支配する節点には、それを導入する節点NP/NPと同様に/NPが付け加えられている。/NPは、gap素性が空リスト(を表す差分リスト)になった段階で、上の例で言えば S/NPが、RELPと結合してRELになった段階で消滅する。この部分の規則を上げると以下のようになる。
optrel(GAP-GAP,GF1, ['REL',RELP,S])-->
     relp(GF2, RELP), s([[gap(np),GF2]|GAP]-GAP,_, S),
                {GF1=[_,Num,_,3,Hum],
                 GF2=[_,Num,_,3,Hum]}.


上の例では、関係代名詞relpの文法素性GF2と、関係文sに受継がれたgap素性の中の文法素性GF2が同じ変数であることによって、関係代名詞が必要とされる条件を満たす(たとえばCaseやHumに関する素性に関して)ことが保証される。なお、最終結果としての関係文を含む名詞句全体から、gap情報が消えたことは、npの第1要素が空リストGAP-GAPになっていることによって示される。
なお、蛇足であるが、gapの最小単位は名詞句(NP)や前置詞句(PP)なので、gap素性の引き数を持つのは句レベルの規則だけであり、辞書やnontermianl ruleを変更する必要はない。
最後に、gapを含む構造を支配する節点に付加される/NP、/PP等を作り出す部分のプログラムの部分と、それが使われている箇所の一例として vp -> tv + npという文脈自由規則に対応するプログラムの部分をあげる。

%%% スラッシュカテゴリーのラベル作成用
% ラベル登録
slash_node(np,'S','S/NP').
slash_node(np,'VP','VP/NP').
slash_node(np,'NP','NP/NP').
slash_node(np,'PP','PP/NP').
slash_node(np,'AP','AP/NP').

slash_node(pp,'S','S/PP').
slash_node(pp,'VP','VP/PP').
slash_node(pp,'NP','NP/PP').
slash_node(pp,'PP','PP/PP').
slash_node(pp,'AP','AP/PP').

% ラベル作成用
make_slash_node(GAP-GAP,Node,Node):- !.
make_slash_node([[gap(NPorPP)|_]|_]-_,Node1,Node2):- 
     slash_node(NPorPP,Node1,Node2).

% vp -> tv + np
vp(GAP1-GAP2,GF1,[NodeVP,TV,NP]) --> tv(GF1,TV),np(GAP1-GAP2,GF2, NP),
                {GF2=[_,_,acc,_,_],make_slash_node(GAP1-GAP2,'VP',NodeVP)}.

3)yes-no疑問文の扱い
疑問詞を含む文を扱うためには、その前提としてまず簡単なyes-no疑問文を処理する規則を導入しなければならない。yes-no疑問文のために必要となる規則を単純な句構造規則で表すと以下のようになる。

s-> aux + np + vp

ここでauxは、+finの素性を、またvpは-finの素性をそれぞれ持つ。これらの条件を考慮してprologの規則に変換すると以下のようになる。
s(GAP1-GAP3,[Tens|GF1],['S',NP,VP])  --> aux(GF1,AUX),
                                         np(GAP1-GAP2,GF2,NP),
                                         vp(GAP2-GAP3,GF3,VP),
                { GF1=[_,Num,_,Pers,_,Tens/VFORM,+fin],
                 GF2=[_,Num,nom,Pers,Hum],
                 GF3=[_,_ ,_,Pers,Hum,VFORM,-fin]}.

4)補足疑問文の扱い
補足疑問文(さしあたり疑問詞代名詞を伴う疑問文)を導入するために必要となる規則を単純な句構造規則で表すと以下のようになる。

s-> qpn+s(with NP-gap)

ここでqpnは、疑問代名詞の略号である。右辺のsのなかのgap素性リストの持つ文法素性は、疑問詞の文法素性に一致する。もし主語のnpがギャップになっているときは、このgap素性を媒介にして、auxと主語のnpとの間での人称と数の一致(agreement)が実現される。以上の関係をprologの規則に変換すると以下のようになる。
s(GAP-GAP,GF2,['S',QPN,S])  --> qpn(GF1,QPN), 
                               s([[gap(np),GF1]|GAP]-GAP ,GF2,S).

なお、辞書の中にも、以下のように疑問代名詞を新たに登録してやる必要がある。なお、feature/3は、冠詞・所有格関係代名詞と共有できるので、新たに登録する必要はない。

% 疑問代名詞
%%% PRETERMINAL RULE %%%
qpn(GF,['QPN',QPN])-->[QPN], {qpn(QPN,N),feature(N,GF,_)}.

%%% LEXIKON %%%
qpn(who,16).
qpn(what,17). 
qpn(whom,18).

文法の拡大

1)形容詞の導入(名詞のadjunctや叙述的用法)
    a cute girl  (adjunct)                             She is cute.(叙述的用法)
2)副詞句や前置詞句の導入(名詞にかかるcomplementまたはadjunctとして)
    the destruction of Rom  (complement)             the girl with a telescope  (adjunct)
    the book here (adjunct)
3)副詞句や前置詞句の導入(動詞にかかる場合)
    I saw (a girl with a telescope).                     I saw (a girl) with a telescope.
4)前置詞を伴う関係代名詞、関係/疑問副詞、疑問形容詞の導入
     He will sell the house,in which he lives.
     He will sell the house,which he lives in.
     He will sell the house,where he lives.
     Where does he live?
     Which house do yo like?                          In which house does he live? etc.
5)名詞の所有格(possessive)と左再帰規則
    Ken*s book
6)その他の特殊構文
    He is easy to please.
    He tries to read the book.
    He seems to read the book.
    It seems that he reads the book.
    It is interesting to read the book. etc.
 

このページのはじめにジャンプ