最近の更新 (Recent Changes)

2014-01-01
2013-01-04
2012-12-22
2012-12-15
2012-12-09

Wikiガイド(Guide)

サイドバー (Side Bar)

← 先頭のページに戻る

デカルト言語による日本語の形態素解析 : 自然言語の読解(その2)

前の説明で示した形態素解析のプログラムを拡張して、より汎用的な文に対応できるようにします。

ちょっと長くなったのですが、以下に示します。

 


<その他 #s>
		(
		   "万一"	<is #k "万一"> 
		 | "少しも"	<is #k "万一"> 
		 | "何故なら"	<is #k "説明"> 
		 | "因みに"	<is #k "順接,説明"> 
		 | "より"	<is #k "比較"> 
		 | "よもや"	<is #k "万一"> 
		 | "ようやく"	<is #k "徐々"> 
		 | "もっとも"	<is #k "逆接,説明"> 
		 | "もしくは"	<is #k "順接,選択"> 
		 | "もし"	<is #k "条件"> 
		 | "もう"	<is #k "既知"> 
		 | "まるで"	<is #k "説明"> 
		 | "まだ"	<is #k "未定"> 
		 | "または"	<is #k "順接,選択"> 
		 | "また"	<is #k "順接,並立"> 
		 | "まさか"	<is #k "万一"> 
		 | "ならびに"	<is #k "順接,並立"> 
		 | "なぜなら"	<is #k "逆接,説明"> 
		 | "なぜ"	<is #k "理由"> 
		 | "なお"	<is #k "逆接,説明"> 
		 | "ないしは"	<is #k "順接,選択"> 
		 | "どうして"	<is #k "理由"> 
		 | "どうか"	<is #k "祈願"> 
		 | "ところで"	<is #k "逆接,転換"> 
		 | "ところが"	<is #k "逆接,一般"> 
		 | "というのは"	<is #k "逆接,説明"> 
		 | "でも"	<is #k "逆接,一般"> 
		 | "では"	<is #k "順接,条件"> 
		 | "ちょうど"	<is #k "説明"> 
		 | "ちなみに"	<is #k "逆接,説明"> 
		 | "だって"	<is #k "逆接,説明"> 
		 | "だったら"	<is #k "順接,条件"> 
		 | "だけど"	<is #k "逆接,一般"> 
		 | "だが"	<is #k "逆接,一般"> 
		 | "だから"	<is #k "順接,原因"> 
		 | "ただし"	<is #k "逆接,説明"> 
		 | "それはそうと"	<is #k "逆接,転換"> 
		 | "それはさておき"	<is #k "逆接,転換"> 
		 | "それにもかかわらず"	<is #k "逆接,理由"> 
		 | "それにしては"	<is #k "逆接,理由"> 
		 | "それに"	<is #k "順接,追加"> 
		 | "それなら"	<is #k "順接,条件"> 
		 | "それなのに"	<is #k "逆接,理由"> 
		 | "それとも"	<is #k "順接,選択"> 
		 | "それでも"	<is #k "逆接,条件"> 
		 | "それでは"	<is #k "順接,条件"> 
		 | "それで"	<is #k "順接,原因"> 
		 | "それぞれ"	<is #k "説明"> 
		 | "それじゃ"	<is #k "順接,条件"> 
		 | "それが"	<is #k "逆接,一般"> 
		 | "それから"	<is #k "順接,追加"> 
		 | "その結果"	<is #k "順接,原因"> 
		 | "そのまま"	<is #k "定"> 
		 | "そのまま"	<is #k "状況"> 
		 | "そのために"	<is #k "順接,原因"> 
		 | "そのため"	<is #k "順接,原因"> 
		 | "そのうえで"	<is #k "順接,追加"> 
		 | "そのうえ"	<is #k "順接,追加"> 
		 | "その"	<is #k "連体詞"> 
		 | "そして"	<is #k "順接,並立"> 
		 | "そこで"	<is #k "順接,条件"> 
		 | "そうか"	<is #k "閃き"> 
		 | "そういえば"	<is #k "逆接,転換"> 
		 | "ぜひ"	<is #k "誘致"> 
		 | "すると"	<is #k "順接,条件"> 
		 | "しっかり"	<is #k "確固"> 
		 | "したがって"	<is #k "順接,原因"> 
		 | "しかも"	<is #k "順接,追加"> 
		 | "しかし"	<is #k "逆接,一般"> 
		 | "さらに"	<is #k "追加"> 
		 | "さて"	<is #k "逆接,転換"> 
		 | "このまま"	<is #k "状況"> 
		 | "この"	<is #k "連体詞"> 
		 | "けれども"	<is #k "逆接,一般"> 
		 | "けれど"	<is #k "逆接,一般"> 
		 | "けっして"	<is #k "逆接"> 
		 | "きっと"	<is #k "推測"> 
		 | "かつてなく"	<is #k "初"> 
		 | "かつてない"	<is #k "初"> 
		 | "かつて"	<is #k "過去"> 
		 | "かつ"	<is #k "順接,並立"> 
		 | "およびに"	<is #k "順接,並立"> 
		 | "および"	<is #k "順接,並立"> 
		 | "おそらく"	<is #k "推測"> 
		 | "あるいは"	<is #k "順接,選択"> 
		 | "あのまま"	<is #k "状況"> 
		 | "あの"	<is #k "連体詞"> 
		 | "あと"	<is #k "追加"> 
		)
				<GETTOKEN #s>
		[
		    ","
		  | "、"
		  | ","
		  | <SPACE>
		]
				<print #k #s>
		;

<格 #k #x>
	<* #x> 

	(
		  "等を"	<is #k "例示,目的"> 
		| "等の"	<is #k "例示,所属"> 
		| "等にも"	<is #k "例示"> 
		| "等"		<is #k "例示"> 
		| "をして"	<is #k "対象,動作"> 
		| "を"		<is #k "対象"> 
		| "れ"		<is #k "動作"> 
		| "よりも"	<is #k "比較"> 
		| "より"	<is #k "開始点"> 
		| "ようにも"	<is #k "困難"> 
		| "ように"	<is #k "同様"> 
		| "や"		<is #k "並び"> 
		| "ものは"	<is #k "動作主"> 
		| "も"		<is #k "追加"> 
		| "までに"	<is #k "到達点"> 
		| "まで"	<is #k "到達点"> 
		| "ますが"	<is #k "逆接"> 
		| "まして"	<is #k "順接"> 
		| "ましたが"	<is #k "逆接"> 
		| "への"	<is #k "到達点"> 
		| "へ"		<is #k "到達点"> 
		| "は"		<is #k "動作主"> 
		| "のも"	<is #k "追加">
		| "のみが"	<is #k "限定">
		| "のみ"	<is #k "限定">
		| "のは"	<is #k "動作主">
		| "のために"	<is #k "理由"> 
		| "のため"	<is #k "理由"> 
		| "のとおり"	<is #k "説明"> 
		| "のことと"	<is #k "説明"> 
		| "の"		<is #k "所属"> 
		| "によれば"	<is #k "理由"> 
		| "によると"	<is #k "理由"> 
		| "による"	<is #k "理由"> 
		| "により"	<is #k "理由"> 
		| "によって"	<is #k "理由"> 
		| "にも"	<is #k "追加"> 
		| "には"	<is #k "限定"> 
		| "についても"	<is #k "理由"> 
		| "について"	<is #k "理由"> 
		| "に"		<is #k "目標"> 
		| "なら"	<is #k "条件"> 
		| "なので"	<is #k "理由"> 
		| "なのだ"	<is #k "理由"> 
		| "などを"	<is #k "例示,目的"> 
		| "などのための" <is #k "例示,理由"> 
		| "などの"	<is #k "例示,所属"> 
		| "などにも"	<is #k "例示"> 
		| "など"	<is #k "例示"> 
		| "ないが"	<is #k "逆接"> 
		| "な"		<is #k "状態"> 
		| "とも"	<is #k "追加"> 
		| "との"	<is #k "所属"> 
		| "とは"	<is #k "動作主"> 
		| "となる"	<is #k "状態"> 
		| "となり"	<is #k "状態"> 
		| "となっているとのこと"<is #k "状態"> 
		| "となっているとの"<is #k "状態"> 
		| "となっている"<is #k "状態"> 
		| "となって"	<is #k "状態"> 
		| "とする"	<is #k "立場"> 
		| "としては"	<is #k "立場"> 
		| "として"	<is #k "立場"> 
		| "とき"	<is #k "条件"> 
		| "ということですので"	<is #k "立場"> 
		| "ということです"	<is #k "立場"> 
		| "ということ"	<is #k "立場"> 
		| "という"	<is #k "立場"> 
		| "と"		<is #k "追加"> 
		| "でも"	<is #k "追加">
		| "ではなく"	<is #k "否定">
		| "では"	<is #k "限定">
		| "での"	<is #k "限定">
		| "ですが"	<is #k "逆接">
		| "でしたが"	<is #k "逆接">
		| "できるようにも"<is #k "条件">
		| "できるように"<is #k "条件">
		| "できるよう"	<is #k "条件">
		| "できると"	<is #k "動作">
		| "できる"	<is #k "動作">
		| "でき"	<is #k "動作">
		| "であり"	<is #k "説明">
		| "で"		<NOTNEXTSTR "す"><is #k "説明">
		| "ても"	<is #k "逆接"> 
		| "だけではなく" <is #k "追加">
		| "だけでなく"	<is #k "追加">
		| "だが"	<is #k "逆接">
		| "たら"	<is #k "動作"> 
		| "ため"	<is #k "理由"> 
		| "せ"		<is #k "動作"> 
		| "すれば"	<is #k "条件"> 
		| "することに"	<is #k "動作"> 
		| "するが"	<is #k "逆接"> 
		| "しよう"	<is #k "動作"> 
		| "しても"	<is #k "理由"> 
		| "しており"	<is #k "動作"> 
		| "している"	<is #k "動作"> 
		| "していた"	<is #k "動作"> 
		| "していくという" <is #k "動作"> 
		| "していく"	<is #k "動作"> 
		| "して"	<is #k "理由"> 
		| "したら"	<is #k "動作"> 
		| "したように"	<is #k "動作"> 
		| "したのに"	<is #k "動作"> 
		| "したので"	<is #k "動作"> 
		| "したが"	<is #k "逆接"> 
		| "した"	<is #k "動作"> 
		| "されては"	<is #k "動作"> 
		| "されて"	<is #k "動作"> 
		| "された"	<is #k "動作"> 
		| "ことも"	<is #k "追加"> 
		| "ことは"	<is #k "対象"> 
		| "いるが"	<is #k "逆説">
		| "があり"	<is #k "説明">
		| "が"		<is #k "動作主">
		| "からの"	<is #k "開始点"> 
		| "から"	<is #k "開始点"> 
		| "おり"	<is #k "動作"> 
		| "および"	<is #k "追加"> 
		| "る"		<NOTNEXTSTR "と"><is #k "動作"> 
		| "め"		<NOTNEXTSTR "る"><is #k "動作"> 
		| "ね"		<is #k "動作"> 
		| "て"		<is #k "動作"> 
		| "け"		<is #k "動作">
		| "え"		<is #k "動作"> 
		| "?"		<is #k "疑問"> 
		| "?"		<is #k "疑問"> 
		| "!"		<is #k "驚愕"> 
		| "!"		<is #k "驚愕"> 
		| <NEXTSTR ",">	<is #k "区切り"> 
		| <NEXTSTR "、"> <is #k "区切り"> 
		| <NEXTSTR ","> <is #k "区切り"> 
		| <NEXTSTR "("> <is #k "区切り"> 
	  	| <NEXTSTR "("> <is #k "区切り"> 
		| <NEXTSTR "「"> <is #k "区切り"> 
		| <NEXTSTR "『"> <is #k "区切り"> 
		| <NEXTSTR "["> <is #k "区切り"> 
		| <NEXTSTR "{"> <is #k "区切り"> 
		| <NEXTSTR ")"> <is #k "区切り"> 
		| <NEXTSTR ")">  <is #k "区切り"> 
		| <NEXTSTR "」"> <is #k "区切り"> 
		| <NEXTSTR "』"> <is #k "区切り"> 
		| <NEXTSTR "]"> <is #k "区切り"> 
		| <NEXTSTR "}"> <is #k "区切り"> 
		| <NEXTSTR '"'> <is #k "区切り"> 
		| <NEXTSTR "'"> <is #k "区切り"> 
		| <NEXTSTR "”"> <is #k "区切り"> 
		| <NEXTSTR "“"> <is #k "区切り"> 
	)
		
		<NOTNEXTSTR "。">
		<NOTNEXTSTR ".">

 		<GETTOKEN #g>
	(
		  <eq #g "を"> [ "," | "、" | ","]
		| ","
		| "、"
		| ","
		| <SPACE>
		| (
		    ::sys <rightstr #rc #x 1>
		    <NEXTCHAR #lc>  
		   (
			(  ::sys <syntax #rc <NONRANGE _ "あ" "ん">>
		    	 | ::sys <syntax #lc <NONRANGE _ "あ" "ん">>
			)
		   )		  
		   <noteq #lc "ぁ">
		   <noteq #lc "ぃ">
		   <noteq #lc "ぅ">
		   <noteq #lc "ぇ">
		   <noteq #lc "ぉ">
		   //<noteq #lc "っ">
		   <noteq #lc "ゃ">
		   <noteq #lc "ゅ">
		   <noteq #lc "ょ">

		   <noteq #rc "な">
		   <noteq #rc "で">
		 )
	)


	<print #k #x #g>
	;


	
<述語 #y #t>
	<* #y>
	(
	   "わ"
	 | "る"
	 | "らしかった"
	 | "らしい"
	 | "ようだった"
	 | "ようだ"
	 | "よ"
	 | "ゆ"
	 | "む"
	 | "ます"
	 | "ました"
	 | "まい"
	 | "ほしかった"
	 | "ほしい"
	 | "ふ"
	 | "の"
	 | "ね"
	 | "ぬ"
	 | "なる"
	 | "なった"
	 | "なかっただろう"
	 | "なかった"
	 | "なかった"
	 | "ないだろう"
	 | "ない"
	 | "ない"
	 | "な"
	 | "です"
	 | "でした"
	 | "できる"
	 | "できない"
	 | "である"
	 | "であった"
	 | "てみる"
	 | "てみた"
	 | "てある"
	 | "てあった"
	 | "つ"
	 | "だろう"
	 | "だった"
	 | "だ"
	 | "たかった"
	 | "たい"
	 | "た"
	 | "ぞ"
	 | "そうだった"
	 | "そうだ"
	 | "する"
	 | "す"
	 | "した"
	 | "される"
	 | "された"
	 | "さ"
	 | "ける"
	 | "けた"
	 | "ください"
	 | "く"
	 | "からだ"
	 | "か"
	 | "う"
	 | "いる"
	 | "いました"
	 | "いた"
	 | "い"
	 | "ある"
	 | "あった"
	 | "?"
	 | "?"
	 | "."
	 | "。"
	 | "..."
	 | "……"
	 | "…"
	 | <SPACE>
	 | <CR>
	)
		<GETTOKEN #t>
	(
		  "?"
		| "?"
		| "."
		| "。"
		| "..."
		| "……"
		| "…"
		| <SPACE>
		| <CR>
		| <EOF>
	)			<print "述語" #y #t><print>
	;

<括弧 #p>
	(
	    "("
	  | "("
	  | "「"
	  | "『"
	  | "["
	  | "{"
	  | "'"
	  | '"'
	  | "”"
	  | "“"
	)
	<GETTOKEN #g>
	<print "括弧" #g>
	;

<文>
	{
		(
		 <括弧 #p>
		|
		 <その他 #s>
		|
		 <格 #k #x>
		)
	}
	<述語 #y #t>
	;

<読み込み>
	{ 
		::sys <getline #x 
			::sys <strdelcntl #y #x> 
			::sys <split #l #y "。">
			<foreach (#i #l)
				(
				   ::sys <syntax #i <NULLLINE>>
				 | 
				   <print ">" #i "。"><print>
				   ::sys <syntax ::sys<concat _ (#i "。")> 
								{<文>}>
				)
			>>
	};
	
? <読み込み>;


例えば以下の文章で試してみましょう。


デカルト言語は、論理的な推論を中心とした言語として設計しました。 

狙っているのは、強力な論理的推論・探索機能があり、関数プログラミング機能を持つオブジェクト群が、人間に近い構文のI/Fによって、並列にマルチコアで動く知的なシステムです。 

名前は有名な数学者・哲学者であるデカルトに因んで名づけています。


プログラムをjp2として保存して、デカルト言語descartesの引数として実行すると入力待ちになります。


$ descartes jp2

このときコピー&ペーストで上記の文を入力すると以下のようになります。


デカルト言語は、論理的な推論を中心とした言語として設計しました。
> デカルト言語は、論理的な推論を中心とした言語として設計しました 。

動作主 デカルト言語 は
状態 論理的 な
対象 推論 を
追加 中心 と
立場 した言語 として
述語 設計し ました


狙っているのは、強力な論理的推論・探索機能があり、関数プログラミング機能を持つオブジェクト群が、人間に近い構文のI/Fによって、並列にマルチコアで動く知的なシステムです。
> 狙っているのは、強力な論理的推論・探索機能があり、関数プログラミング機能を持つオブジェクト群が、人間に近い構文のI/Fによって、並列にマルチコアで動く知的なシステムです
。

動作主 狙っている のは
状態 強力 な
説明 論理的推論・探索機能 があり
対象 関数プログラミング機能 を
動作主 持つオブジェクト群 が
目標 人間 に
所属 近い構文 の
理由 I/F によって
目標 並列 に
説明 マルチコア で
状態 動く知的 な
述語 システム です


名前は有名な数学者・哲学者であるデカルトに因んで名づけています。
> 名前は有名な数学者・哲学者であるデカルトに因んで名づけています 。

動作主 名前 は
状態 有名 な
説明 数学者・哲学者 で
動作 あ る
目標 デカルト に
説明 因ん で
述語 名づけてい ます

ちょっと変なところもありますが、このような簡単なプログラムでも形態素解析ができています。 (変なところについては、後の項で改造します。)

いろいろとWEB上の文章などを入力してみてください。 結構うまく解析できます。

これを使えば、検索エンジンへ入力するための検索ワードの抽出みたいな用途にも使えそうな気がしてきます。

プログラムの詳細については、次項から説明しましょう。

1. その他

「その他」が最初にくるのは変な構成ですが、これは、前の「デカルト言語による日本語の形態素解析 : 自然言語の読解」で 定義してあったプログラムの、「格」と「述語」以外の接続詞や副詞を集めて定義したものです。


<その他 #s>
                (
                   "万一"       <is #k "万一">
                 | "少しも"     <is #k "万一">
                 | "何故なら"   <is #k "説明">
                 | "因みに"     <is #k "順接,説明">
                 | "より"       <is #k "比較">
                 | "よもや"     <is #k "万一">
                 | "ようやく"   <is #k "徐々">
                 | "もっとも"   <is #k "逆接,説明">
                 | "もしくは"   <is #k "順接,選択">
                 | "もし"       <is #k "条件">
                 | "もう"       <is #k "既知">
                 | "まるで"     <is #k "説明">
                 | "まだ"       <is #k "未定">
                 | "または"     <is #k "順接,選択">
...途中略
                 | "おそらく"   <is #k "推測">
                 | "あるいは"   <is #k "順接,選択">
                 | "あのまま"   <is #k "状況">
                 | "あの"       <is #k "連体詞">
                 | "あと"       <is #k "追加">
                )
                                <GETTOKEN #s>
                [
                    ","
                  | "、"
                  | ","
                  | <SPACE>
                ]
                                <print #k #s>
                ;

中には「そして」、「しかし」などの接続詞や、「きっと」、「どうして」などの副詞や、その他連体詞などの 「格」としなくても自立できるような言葉をまとめてあります。

これらの語は、自立して意味を判別できるため、「格」とは独立して定義したのです。

「格」の場合は、「~+助詞」となり、~の部分はさまざまなバリエーションがありえます。 そのため、~の部分は構文解析を行う際に、ぜひ抽出したい部分です。

しかし、「その他」で定義されている語は、それ単独で意味が判明するので、それらをまとめて構文解析の対象となるようにしました。

前のプログラムと比べてこの部分を拡張することにより、本プログラムでは自然言語の文の解析精度を高くすることができました。

2. 格

「格」の部分については、前の「デカルト言語による日本語の形態素解析 : 自然言語の読解」で定義してあったプログラムの、 「格」に比べていろいろと拡張しています。


<格 #k #x>
	<* #x> 

	(
		  "等を"		<is #k "例示,目的"> 
		| "等の"		<is #k "例示,所属"> 
		| "等にも"	<is #k "例示"> 
...途中略
		| "け"		<is #k "動作">
		| "え"		<is #k "動作"> 
		| "?"		<is #k "疑問"> 
		| "?"		<is #k "疑問"> 
		| "!"		<is #k "驚愕"> 
		| "!"		<is #k "驚愕"> 
		| <NEXTSTR ",">	<is #k "区切り"> 
		| <NEXTSTR "、"> <is #k "区切り"> 
		| <NEXTSTR ","> <is #k "区切り"> 
		| <NEXTSTR "("> <is #k "区切り"> 
	  	| <NEXTSTR "("> <is #k "区切り"> 
		| <NEXTSTR "「"> <is #k "区切り"> 
		| <NEXTSTR "『"> <is #k "区切り"> 
		| <NEXTSTR "["> <is #k "区切り"> 
		| <NEXTSTR "{"> <is #k "区切り"> 
		| <NEXTSTR ")"> <is #k "区切り"> 
		| <NEXTSTR ")">  <is #k "区切り"> 
		| <NEXTSTR "」"> <is #k "区切り"> 
		| <NEXTSTR "』"> <is #k "区切り"> 
		| <NEXTSTR "]"> <is #k "区切り"> 
		| <NEXTSTR "}"> <is #k "区切り"> 
		| <NEXTSTR '"'> <is #k "区切り"> 
		| <NEXTSTR "'"> <is #k "区切り"> 
		| <NEXTSTR "”"> <is #k "区切り"> 
		| <NEXTSTR "“"> <is #k "区切り"> 
	)
		
		<NOTNEXTSTR "。">
		<NOTNEXTSTR ".">

 		<GETTOKEN #g>
	(
		  <eq #g "を"> [ "," | "、" | ","]
		| ","
		| "、"
		| ","
		| <SPACE>
		| (
		    ::sys <rightstr #rc #x 1>
		    <NEXTCHAR #lc>  
		   (
			(  ::sys <syntax #rc <NONRANGE _ "あ" "ん">>
		    	 | ::sys <syntax #lc <NONRANGE _ "あ" "ん">>
			)
		   )		  
		   <noteq #lc "ぁ">
		   <noteq #lc "ぃ">
		   <noteq #lc "ぅ">
		   <noteq #lc "ぇ">
		   <noteq #lc "ぉ">
		   //<noteq #lc "っ">
		   <noteq #lc "ゃ">
		   <noteq #lc "ゅ">
		   <noteq #lc "ょ">

		   <noteq #rc "な">
		   <noteq #rc "で">
		 )
	)


	<print #k #x #g>
	;

NEXTSTR述語は、現在読み込んだ文字の次の文字列が何かを先読みします。

上記では、区切り文字が次の文字かどうかを判断して、文の区切りを明確に判定しています。

noteq述語は引数が等しくないことを確認する述語です。

その引数で、ぁ、ぃ、ぅ等の小さな平仮名を判定しているのは、助詞の「が」のような述語の後に「ぁ」のような文字があると、 擬音の「がぁがぁ」というような言葉は判定できないためです。 また、助詞の後は新たな単語の開始位置ですから、小さな平仮名が最初の文字に来るのはありえないという判断でもあります。

3. 述語

「述語」の部分については、前の「デカルト言語による日本語の形態素解析 : 自然言語の読解」で定義してあったプログラムの、 「述語」に比べていろいろな述語を拡張しています。

また、語尾に「?」や「...」のような字句を拡張することにより、世の中に存在する文への対応が柔軟に行えるようになりました。


<述語 #y #t>
        <* #y>
        (
           "わ"
         | "る"
         | "らしかった"
         | "らしい"
         | "ようだった"
         | "ようだ"
...途中略
         | "い"
         | "ある"
         | "あった"
         | "?"
         | "?"
         | "."
         | "。"
         | "..."
         | "……"
         | "…"
         | <SPACE>
         | <CR>
        )
                <GETTOKEN #t>
        (
                  "?"
                | "?"
                | "."
                | "。"
                | "..."
                | "……"
                | "…"
                | <SPACE>
                | <CR>
                | <EOF>
        )                       <print "述語" #y #t><print>
        ;


本来は、述語の変化にも対応できると良いかもしれません。 過去形や未来形などの語尾の変化に対応するのは、そんなに難しいことではありません。 五段活用のような文法で定められた活用形をサポートすればよいでしょう。

4. 括弧

世の中の文では、括弧に括られた文がとても多いです。注釈、補足、モノローグや会話など、さまざまな場面で使用されます。

また、括弧といっても種類もとても多いですね。クォートやダブルクォートなどもあります。

括弧は、多用され文の中で重要な役割をすることから、ここの形態素プログラムの中では独立した一つの述語として定義しました。


<括弧 #p>
        (
            "("
          | "("
          | "「"
          | "『"
          | "["
          | "{"
          | "'"
          | '"'
          | "”"
          | "“"
        )
        <GETTOKEN #g>
        <print "括弧" #g>
        ;

しかし、上記のプログラムを見てもらうと少し変に思われるかもしれません。 括弧の開始はあるのですが、閉じ括弧がないですね。

閉じ括弧については、<格>述語で処理するようにしています。

たとえば以下の文を処理してみましょう。


> 一般的な(私はそう思わない)ことだが、違う結果になることがある 。

状態 一般的 な
括弧 (
動作主 私 は
区切り そう思わない
逆接 )こと だが
目標 違う結果 に
述語 なることが ある

上記に示した『)こと だが』のように、閉じ括弧を格の一部として、このプログラムでは解釈します。

5. 文

「文」述語は、今まで説明してきた「括弧」、「その他」、「格」および「述語」で構成されます。


<文>
	{
		(
		 <括弧 #p>
		|
		 <その他 #s>
		|
		 <格 #k #x>
		)
	}
	<述語 #y #t>
	;

まず、「括弧」述語か調べ、異なる場合は「その他」、「格」と順に調べます。 該当する述語の場合は、解析した結果を出力することになります。 そして、これらの述語の処理を繰り返し、最後に「述語」の処理を行い、その結果を出力して終了します。

このような処理の繰り返しにより、日本語の文を形態素解析していきます。

6. 拡張と改良の方法

ここで紹介したプログラムは、前の「デカルト言語による日本語の形態素解析 : 自然言語の読解」で定義してあったプログラム を基にして、いろいろな文章を入力し、その結果から拡張して改良してきたものです。

この項では、その拡張と改良の方法について説明したいと思います。

このページの最初に示した例をもう一度見てみましょう。


デカルト言語は、論理的な推論を中心とした言語として設計しました。
> デカルト言語は、論理的な推論を中心とした言語として設計しました 。

動作主 デカルト言語 は
状態 論理的 な
対象 推論 を
追加 中心 と
立場 した言語 として
述語 設計し ました

「中心とした言語として」が、「中心 と」、「した言語 として」となってしまっています。

これを、「中心 とした」、「言語 として」となるように改良してみます。

これは、じっとこの文をみてみると、助詞の「と」と間違えて判定したためと分かります。 つまり、「と」と判定される前に、「とした」と判定してしまえばよいのです。

次に、最初に示したプログラムの中で「と」を処理している部分を探してみましょう。

<格>述語の中で探します。


                | "としては"    <is #k "立場">
                | "として"      <is #k "立場">
                | "とき"        <is #k "条件">
                | "ということですので"  <is #k "立場">
                | "ということです"      <is #k "立場">
                | "ということ"  <is #k "立場">
                | "という"      <is #k "立場">
                | "と"          <is #k "追加">   //← ここです。
                | "でも"        <is #k "追加">

ありましたね。 この「と」よりも上に「とした」を追加すればOKです。


                | "としては"    <is #k "立場">
                | "として"      <is #k "立場">
                | "とした"      <is #k "立場"> //← ここに追加
                | "とき"        <is #k "条件">
                | "ということですので"  <is #k "立場">
                | "ということです"      <is #k "立場">
                | "ということ"  <is #k "立場">
                | "という"      <is #k "立場">
                | "と"          <is #k "追加">
                | "でも"        <is #k "追加">

「と」の上なら、とりあえず、どこでも良いのですが、ここでは、語順なども考えて、「として」の直下に追加しました。

さて、この新しいプログラムを使って同じ文を解析してみます。


> デカルト言語は、論理的な推論を中心とした言語として設計しました 。

動作主 デカルト言語 は
状態 論理的 な
対象 推論 を
立場 中心 とした
立場 言語 として
述語 設計し ました

狙い通りに解析できました。

実はこの形態素解析のプログラムは、さまざまなWWW上のニュースの文を多数読ませながら、 上記のような方法で拡張して作ったものです。

文を覚えさせれば、どんどんと賢くなっていくプログラムなのです。

7. デカルト言語の夢

デカルト言語の目的のひとつが

「人間に近い構文のI/Fによって動く知的なシステム」

です。

その実現のための最初の一歩にすることを、この形態素プログラムは狙っています。

日本語を、コンピュータで処理しようとすると、語と語の区切りが区別しにくく大変でした。 英語のように、単語の間が空いている分かち書きされているような文にくらべて、日本語ではまずそこが問題となって プログラムの処理が難しくなってしまいます。

ここで示したようなプログラムによって形態素の解析までできてしまうと、その後にさまざまな処理を行うのが容易になるでしょう。

しかも、400行ほどの予想していたよりも遥かに簡単なプログラムで、実現できてしまいました。 もう少し複雑で大規模なものになると思っていたので、自分でもビックリです。

- 人間との応答会話を、自然言語によって行う。

- 人間の書いた文を読み込み、使われている単語を抜き出して、検索エンジンに入力する。

- 自然言語で書ける日本語プログラム言語

- WWW上の文書の自動要約

ここで紹介したプログラムで形態素の解析まで行えます。このままでは無理でも目的に応じて改造していけば、さまざまな応用を考えることができるようになるでしょう。

どんなものに応用できるか、みなさんも考えてみてください。