目次


UIMA 101 後編 - テキスト分析エンジンを開発する

Comments

分析エンジンを開発するには

前編で見てきたように分析エンジンには、次の3点が必要でした。

  • Annotatorによるアルゴリズム
  • Type Systemによる入出力定義
  • Analysis Engine Descriptorによる構成定義

分析エンジンの開発では通常これらを次のような手順で行っていきます。

  1. 入出力するCASのタイプ、フィーチャーをType System Descriptor に定義
  2. Annotatorに必要な分析アルゴリズムを実装
  3. Analysis Engine Descriptor で 分析エンジンを定義

UIMA SDKに付属のEclipse plug-inにはUIMA Descriptor を新規作成、編集する機能が含まれています。本稿ではEclipse環境上でUIMA Descriptorを作成し、さらにJava™でAnnotatorを実装することで、新規分析エンジンの開発する方法を説明します。

分析エンジンの仕様

前編で見てきた ” Name Recognizer and Person Title Annotator TAE” (以降、NP-TAEと表記します) は英語の固有名詞と敬称に対して情報を付与するテキスト分析エンジンでした。本稿では、NP-TAEを参考に、日本語の人名・敬称を抽出するテキスト分析エンジンを次のような仕様に従って開発します。

  • Primitive型分析エンジン。名前はOnamaeTAE。
  • PersonTitleとして次のような接尾辞を定義します
    • CivilianTitles: 「様」「君」
    • GovernmentTitle: なし
    • MilitaryTitles: なし
  • 漢字一文字以上 + PersonTitle をNameとします
  • Type SystemはNP-TAEと同じです
  • Annotatorはcom.ibm.uima.examples.cas.OnamaeAnnotator として実装します
  • 対応言語は日本語です

新規プロジェクトの作成

Eclipseを起動し、新規Javaプロジェクトを作成します。メニューから File → New → Projectを実行し、プロジェクトウィザードからJava Projectを選択します。「Next」をクリックし、 New Java Project のダイアログでプロジェクト名を入力します (例: NewTAE。以下NewTAEProjectと表記します)。またProject layout の Create separate source and output folders にチェックします。「Next」でJava Settingの画面に進み、LibraryタブからUIMA SDKの設定を追加します。

  1. 「Add Variables…」からNew Variable Classpath Entry画面を開きます
  2. 「Configure Variables…」をクリックします
  3. Preferences 画面で右側の「New」をクリックします
  4. New Variable Entryを追加します
    Name : UIMA_HOME
    Path : %UIMA_HOME% (前編でUIMA_SDKを展開したディレクトリ)
  5. Preferences 画面 でUIMA_HOMEが正しく設定されているか確認します(図 1)
    図1. 環境変数UIMA_HOMEの追加
    図1. 環境変数UIMA_HOMEの追加
    図1. 環境変数UIMA_HOMEの追加
  6. New Variable Classpath Entry画面に戻り、「Extend…」をクリックします
  7. Variable Extensionでlib以下から次の4つのライブラリを選択して「OK」をクリックします
    uima_core.jar,
    uima_cpe.jar,
    uima_tools.jar,
    xsdbeans.jar
  8. Librariesで上記4つが追加されていることを確認します (図 2)
    図2. Librariesの追加
    図2. Librariesの追加
    図2. Librariesの追加

ここまでの設定が終了したら、「Finnish」をクリックして、Project作成を完了します。

UIMA Natureの追加

プロジェクトを作成したところで、UIMA Natureと呼ばれるディレクトリ構造を導入します。これは分析エンジンの開発とは直接関係ありませんが、PEAR (Processing Engine ARchive) と呼ばれるUIMA コンポーネントのパッケージを作成するときに必要な構造になります。将来分析エンジンを配布する可能性を考えて、これに準じた形で開発を進めます。

JavaパースペクティブでNewTAEProjectを選択し、右クリックから「Add UIMA Nature」を実行します (図 3)。確認ダイアログで「Yes」をクリックすると、プロジェクトにdescなどのフォルダが追加されます。

図3. UIMA Natureの追加
図3. UIMA Natureの追加
図3. UIMA Natureの追加

Type Systemの作成

NP-TAEでは個々のAnalysis Engine DescriptorにType Systemの定義が含まれていましたが、Type Systemは別のファイルに定義して、Analysis Engine Descriptor ではインポートすることが推奨されています。Type System Descriptor を別ファイルで新規作成します。

メニューからFile → New → Other を実行し、ウィザード画面で UIMA - Type System Descriptor File を選択します (図 4)。

図4. UIMA Descriptor Wizard
図4. UIMA Descriptor Wizard
図4. UIMA Descriptor Wizard

「Next」をクリックし、Descriptorのファイル名 (typeSystemDescriptor.xml) とペアレントフォルダを入力します。ペアレントフォルダにはプロジェクト内のdescフォルダを指定します (図 5)。

図5. 新規Type System Descriptor Fileの作成
図5. 新規Type System Descriptor Fileの作成
図5. 新規Type System Descriptor Fileの作成

「Finish」をクリックすると、新規Descriptorが作成され、Component Descriptor Editor が自動的に開きます。

NP-TAEとおなじType Systemを追加していきます。NP-TAEのType Systemの定義はPersonTitleAnnotator_WithinNamesOnly.xmlのtypeSystemDescription タグに記載されています。最初にexample.Name を追加します。Type Systemタブを選択し、「Add Type」をクリックします。Add a Type の画面にType NameとSupertypeを入力します (図 6)。「OK」をクリックするとexample.Nameが作成されます。

図6. Typeの追加
図6. Typeの追加
図6. Typeの追加

同様にexample.PersonTitle、example.PersonTitleKind も追加します。example.PersonTitleKindの SuperType は uima.cas.String であることに注意してください (図 7)。uima.cas.StringはCASに最初から定義されている文字列型です。

図7. 追加されたTypeの定義
図7. 追加されたTypeの定義
図7. 追加されたTypeの定義

次にPersonTitleKindに対するallowedValuesを設定します。PersonTitleKind を選択して 「Add」をクリックすると Allowed Value の設定画面が開きます (図 8)。Civilian、Military、 Government を追加します。

図8. Allowed Valueの追加
図8. Allowed Valueの追加
図8. Allowed Valueの追加

最後にPersonTitleとPersonTitleKindの関連付けを行います。PersonTitleKind はPersonTitleのフィーチャーとして関連付けられています。 PersonTitleを選択して「Add」をクリックし、フィーチャーを追加します (図 9)。

図9. フィーチャーの追加
図9. フィーチャーの追加
図9. フィーチャーの追加

以上でType Systemの作成が完了しました。Sourceタブを選択して生成されたXMLを見てみると、PersonTitleAnnotator_WithinNamesOnly.xmlのtypeSystemDescription部分と同じ定義が生成されているはずです。

このDescriptorを保存すると、JCasGenというユーティリティが実行され、タイプの定義に則したJava クラスが自動作成されます。クラスにはフィーチャーに対するgetter/setterメソッドとコンストラクターが用意されており、このクラスのインスタンスが実際にCASに格納されるデータに対応します。今回は生成されたこれらのクラスには手を入れず、そのまま利用します。

Annotatorの開発

次にAnnotatorを開発します。まずNew → Packages を実行してcom.ibm.uima.examples.casパッケージを追加します。次にクラスを作成します。New → Class を実行して New Java Class Wizardを開きます。パッケージ名にcom.ibm.uima.examples.cas、クラス名にOnamaeAnnotatorを入力します。また、スーパークラスには、テキストを取り扱うAnnotator の標準的なアブストラクトクラスであるJTextAnnotator_ImplBaseを指定します。「Finish」をクリックするとText Annotatorの実装クラスが生成されます。processメソッドが処理の中心となる部分です。OnamaeAnnotator#processに分析のアルゴリズムを先に決めた仕様に従って実装していきます。ここでは簡単にするために、正規表現のパターンや敬称の定義はこのAnnotatorに静的な形でもたせるように実装しました (リスト 1)。

リスト1. OnamaeAnnotator.java
package com.ibm.uima.examples.cas;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ibm.uima.analysis_engine.ResultSpecification;
import com.ibm.uima.analysis_engine.annotator.AnnotatorProcessException;
import com.ibm.uima.analysis_engine.annotator.JTextAnnotator_ImplBase;
import com.ibm.uima.jcas.impl.JCas;

import example.Name;          
import example.PersonTitle;

/**
* 日本語の人名と敬称を分析するAnnotator
*/
public class OnamaeAnnotator extends JTextAnnotator_ImplBase {

/* 漢字2文字以上の正規表現パターン */
private static final Pattern pHan = Pattern.compile("\\p{InCJKUnifiedIdeographs}{2,}");
/* 敬称接尾辞 */
private static final String civilianSuffixes[] = new String[] { "様", "君" };

/**
* 処理対象のテキスト全体を取得し,人名・敬称にアノテーションを付与する
* 
* @see com.ibm.uima.analysis_engine.annotator.JTextAnnotator#process(
*      com.ibm.uima.jcas.impl.JCas,
*      com.ibm.uima.analysis_engine.ResultSpecification)
*/
 public void process(JCas jCas, ResultSpecification rSpec)
throws AnnotatorProcessException {
// 処理するテキストを取得
String document = jCas.getDocumentText();
// 正規表現により漢字2文字以上の文字列を切り出しする
Matcher matcher = pHan.matcher(document);

// 正規表現にマッチするものがあれば
while (matcher.find()) {
final int begin = matcher.start();
final int end = matcher.end();
// 文字列の接尾に指定された敬称があるかどうか探す (civilian)
for (int i = 0; i < civilianSuffixes.length; i++) {
// 敬称がつかったらアノテーションする
if (document.substring(begin, end).endsWith(civilianSuffixes[i])) {
// Nameを作成
Name nameAnno = new Name(jCas);
nameAnno.setBegin(begin);
nameAnno.setEnd(end);
nameAnno.addToIndexes();

// PersonTitleを作成
PersonTitle personAnno = new PersonTitle(jCas);
personAnno.setBegin(end - civilianSuffixes[i].length());
personAnno.setEnd(end);
// Kindの種別を付与する
personAnno.setKind("Civilian");
personAnno.addToIndexes();
}
}
}
}
}

Analysis Engine Descriptor の作成

最後にAnalysis Engine Descriptorを作成します。メニューからFile → New → Other を実行し、ウィザード画面を開きます。UIMA - Analysis Engine Descriptor Fileを選択して、「Next」をクリックし、Descriptorのファイル名 (例 : aeDescriptor)とペアレントフォルダを入力します。Type Systemの時と同様に、ペアレントフォルダはプロジェクト内のdescフォルダに設定して「Finish」をクリックします。

Component Descriptor Editorが開いたら、設定を追加していきます。OverviewページでEngine Type を Primitiveにチェックして、Annotatorのクラス名に先ほど作成したcom.ibm.uima.examples.cas.OnamaeAnnotatorを指定します (図 10)。また、Nameにこの分析エンジンの名前(OnamaeTAE) を設定します。

図10. Overviewの設定
図10. Overviewの設定
図10. Overviewの設定

次にType System DefinitionページでType System Descriptorのインポート設定を追加します。Imported Type Systems から「Add」をクリックします。インポートするファイルを選択するダイアログが開いたら、先ほど作成したdesc\typeSystemDescriptor.xmlを選択し、「Import By Location」にチェックを入れて「OK」をクリックします (図 11)。

図11. Type System Descriptorのインポート
図11. Type System Descriptorのインポート
図11. Type System Descriptorのインポート

Capabilities ページで入出力の設定を行います。「Add Type」をクリックすると設定したType Systemからどのタイプを入出力するかを選択するダイアログが表示されます。

Nameと PersonTitle の Output 列をクリックして、この2つを出力に指定します(図 12)。

図12. 出力タイプの指定
図12. 出力タイプの指定
図12. 出力タイプの指定

以上でAnalysis Engine Descriptorの作成は完了です。これで分析エンジンの開発も完了したことになります。

OnamaeTAEによる解析

でき上がったOnamaeTAEを使ってドキュメントを分析してみましょう。今回はEclipse上からDocument Analyzer を起動します。Run → Run から Java Application の新規実行を選択します。Include libraries when seaching for a main class に チェックを入れ、

Main class に com.ibm.uima.reference_impl.application.DocumentAnalyzer を指定します (図 13)。

図13. EclipseからのDocument Analyzerの起動
図13. EclipseからのDocument Analyzerの起動
図13. EclipseからのDocument Analyzerの起動

Document Analyzer を下記のように設定して、NP-TAEと同様に文章を解析します (図 14)。日本語を入力する場合にはシステムにあった文字コードを選択してください。

  • Input/Output Directory : Eclipseワークスペースの下にあるNewTAEProject
  • XML Descriptor : descフォルダに作成したAnalysis Engine Descriptor
  • Character Encoding : windows-932 (Windows® XP の場合)
図14.OnamaeTAEによる日本語の分析結果
図14.OnamaeTAEによる日本語の分析結果
図14.OnamaeTAEによる日本語の分析結果

OnamaeTAEの構成は図 15のようになります。

図15. OnamaeTAEの構成
図15. OnamaeTAEの構成
図15. OnamaeTAEの構成

改善すべき点

期待する動作は確認できましたが、いくつか改善すべき点があります。Annotatorに静的に正規表現のルールや敬称を定義しましたが、これらはDescriptorから与えるパラメータとして設定すべきです。サンプルのPersonTitleAnnotatorのようにAnnotator_ImplBase# initializeをオーバーライドしてDescriptorからの設定値を取り込む実装が必要でしょう。性能の面から見ると、OnamaeAnnotatorはあまりに単純です。「雨模様」のような表記は誤認識されてしまいます。また「奥様」のように文脈次第では人名とも尊敬語とも取れるような表記もあります。正規表現だけでこれらを取り扱うのは難しく、形態素解析や関係解析などの自然言語処理技術の導入が無ければ正確な分析は困難です。

組み合わせて新しい分析エンジンを構成する

開発したOnamaeTAEとNP-TAEを組み合わせることによって、日英二ヶ国語を含むテキストを解析するテキスト分析エンジン(図 16)や、入力された言語に応じて処理を切り替えるテキスト分析エンジンを簡単に構成できます。

図16. 日本語英語双方を含むテキストを扱う分析エンジンの例
図16. 日本語英語双方を含むテキストを扱う分析エンジンの例
図16. 日本語英語双方を含むテキストを扱う分析エンジンの例

日英二ヶ国語を含むテキストを扱う分析エンジンを開発するには、先ほどと同様に新規Analysis Engine Descriptorを作成して、次の設定をするだけです。

  1. Engine Type を Aggregate型にする
  2. AggregateページでOnamaeTAEとNP-TAEのDescriptorを指定する
  3. Capabilitiesページで出力タイプを指定する

またAggregateしたTAEの処理をFixed FlowからCapability Language Flowを切り替えた上で、CapabilitiesのLanguageに適切な言語を設定することにより、言語に応じた分析エンジンの切り替えが可能になります。

まとめ

Eclipse開発環境において、Type System Descriptor、Annotator、Analysis Engine Descriptorを作成し、テキスト分析エンジンの開発する手順を説明しました。

このように分析エンジン開発し、またそれらを組み合わせることで、より高度な分析処理が可能になります。付属のチュートリアルやサンプルプロジェクトを参考に、目的に最適な分析エンジンを開発してください。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Java technology
ArticleID=246067
ArticleTitle=UIMA 101 後編 - テキスト分析エンジンを開発する
publish-date=03092007