中国語の単語分割

Pocket

中国語や日本語の情報に対してコンピューターで何らかの処理、たとえば統計的な処理、要約、キーワード抽出などを行いたいと思った場合、まずは文章を単語単位に分割する必要がある。欧米の言語と違い、中国語などは単語間にスペース(区切りとなる文字)がないため、どこからどこまでが単語なのかコンピューターには判断できない。

この単語分割は、さまざまな処理のはじめの一歩であるにもかかわらず、とても手強い問題で今のところ100%の精度で分割を実現する手法は考案されていない。オンライン辞書の北辞郎には「今日熱聞」というコーナーを設けてあり、話題になっている新聞の見出しをネットから取得し、その見出しを単語単位に分割する処理を行っているが、機械的な手法を採用しているため、かなりの割合で誤った分割をしてしまう。以前からなんとかしたいと考えていて、今回少し勉強したので、その内容をメモしておきたい。

今回、私が試してみたのは中国の形態素解析ツール「jieba(结巴」で採用されている手法である。Pythonで書かれたオープンソースのツールで、さまざまな言語に移植されている。少し検索するとソースコードの解説を行っているブログがたくさんあり、分からないところを理解する上で大いに助けになった(感謝)。

jiebaの単語分割の考え方はとてもシンプルで、私の理解では大きく2つの部分に分かれている。まず、文章を単語に分割する際、分け方がいくつか考えられる場合、その判断の基準として词频(単語の出現頻度・出現率)を利用するというのが大きな特徴である。

ここでいう出現率は、あらかじめ人手で文章を単語に分割したデータを大量に登録したコーパスを利用し、ある単語がそのコーパス内に出現する合計回数を全単語の出現合計回数で割った値をいう。

具体的な利用方法として、たとえば「研究生命的起源」という文を分割する場合を考えると、「研究/生命/的/起源」と「研究生/命/的/起源」のようにいくつかの分け方がある。その際、「研究/生命」という2つの単語の出現率の合計と「研究生/命」の出現率の合計を比較し、値の大きい方を採用する。

単純な計算方法だが、これがとても有効に働く。中国語は漢字1文字でも単語して成り立つので(というか常用語ほど漢字1文字が多い)、先ほどの文は「研/究/生/命/的/起/源」という分割候補だって考えられる。jiebaは、こういう漢字1文字も含め、辞書に登録されている全単語を候補として先ほどの計算を行い、だいたい「研究/生命/的/起源」のように正しい結果を導き出す。

この単語の出現頻度を利用した処理がjiebaの1つめの部分である。

もう1つは未登録語の処理である。先ほど「辞書に登録されている全単語を候補とする」と書いたように、辞書に登録されていない単語が文章に含まれている場合、上記の方法だけでは正しく分割できない。

jiebaの実装で利用されているのは、人民日報コーパスをはじめとするデータだが、少し内容が古い(1990年代の記事など)ので、新型コロナ(新冠)のような単語は辞書に収録されていない。

こうした未登録語に対応するため、jiebaは漢字1文字の「构词位置(単語構成時の位置)」に注目して未登録語の単語分割を試みる。ある漢字が単語のどの位置に出てきやすいか、どのようにほかの漢字とつながり、単語を構築しているのかをコーパスを利用して分析し、B(BEGIN)=単語の先頭、E(END)=単語の末端、M(MIDDLE)=単語の中間、S(SINGLE)=1文字で単語となる、という4種類に分類する。

「新」という漢字を例に取ると、「新型冠状病毒」という単語ではB、「重新」という単語ではE、「高新科技」という単語ではM、そして単独で単語となる場合(例:输入新的密码での新)のSのように、単語のいろんな位置に出現する。ただ、その出現の仕方にはやはり傾向があり、また前方にどのような文字があるかにも影響を受ける。

こうした傾向やつながりやすさ、中国語の単語の特徴を、jiebaは隠れマルコフモデル(HMM)でモデルを構築し、漢字1文字の分割が連続した場合に未登録語がないか調べている。

※隠れマルコフモデルについては、下記の記事がたいへんていねいでわかりやすいので興味のある方は参照されたい。

参考:隠れマルコフモデル 入門 | Kabuku Developers Blog

この未登録語の処理は、漢字1文字の分割が連続した場合に限定されているので精度的に限界があるが、辞書ファイルからデータをすべて削除しても、このHMMだけである程度分割できてしまうのが面白い。下記リンクからソースが確認できる。わずか100行なのが刺激的である。

参考:jieba/__init__.py

ここまでの理解をもとに、jiebaをTclで書き直した。jiebaは文中に出てくる漢字以外の文字を無視して処理を行っているので、それを改め、HMMの処理で使用するデータや辞書データを、精度的に信頼できる人民日報コーパスだけで再構築してみた。一応動いている。これを今度はPHPに移植し、北辞郎に組み込むのが次の目標である。PHP版はすでに存在するが、車輪の再発明は私の趣味なので気にしない。

最後に代表的なコーパスへのリンクを以下に示す。上記のような処理を実現するには、人手で分割されたコーパスが必要になるが、信頼できるデータはそれほど多くない。中国語のコーパスは、下記の3つが実績があり、ある程度のボリュームもあるので使いやすい。

以上、ソースを示さずにプログラムのことを書くエントリにて候。


追記:
後日、PHPに移植しました。興味のある方はこちらをご覧ください。

2件のコメント

  1. pythonで中国語の文章を単語ごとにわける方法を探しててたどり着きました。
    とてもわかりやすく大まかな理解ができました。ありがとうございます!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください