[Anthy-dev 863] anthy の変換精度向上

アーカイブの一覧に戻る

henkm****@trans***** henkm****@trans*****
2004年 6月 21日 (月) 20:36:50 JST


岡本(henkma)です.
はじめまして > はじめましての方々
お久しぶりです > お久しぶりの方々

anthyの変換精度を上げたいと考え, 少しソースコードを読んでみて,
どうすれば良いかについて考えとメモをまとめてみました.
開発に必要なドキュメントはdoc/* にかなり質の良いものが揃っていて
以下のことはこれのsubset的なものになっているかもしれませんが, 
Subjectの視点に特化したものとしてコンパクトに, またその方向にある程度詳しく
したつもりです. 突込み等いただければ幸いです.
長文なので, 興味のない方は申し訳ありませんが無視して下さい.


1. 変換精度向上のために

   変換精度向上のために, 2つのアプローチが考えられます. 一つは
   アルゴリズムの向上, もう一つは辞書の充実です. それぞれに対し,
   現状最も効果的なのは前者に関してsplitterの改良, 後者に関しては
   付属語グラフの充実だと私は考えています. 

   この文書はこれらの点, 特に前者に注目して書いたものです.
   

2. 用語

   anthyのコメントやコード中に使われている用語の意味についてまとめます.

 ・candidate   候補
 ・commit      (変換の)確定
 ・context     入力コンテキスト 変換する文字列一つに対応する.
 ・metaword    文節を複数まとめたもの
 ・extent      文(context)中の範囲
 ・nr_*        何かの数を表す変数名の接頭辞. 
               主に"nr_配列名"で配列の長さを表す.
 ・anty_*(...) 外部に公開する関数.


3. 型

   anthyで用いられている型(主にstruct)について意味や構造をまとめます.   

  ・xchar 
    include/xstr.h	
    文字一個分を表す型. 正体はint. EUCもしくはASCIIのコードが入っている.

  ・xstr 
    include/xstr.h	
    正体はstruct xstr_.
    struct xstr_ のメンバは以下の通り.
    - xchar* str;
      xcharの配列
    - int len;
      上記配列の長さ

  ・struct anthy_context
    src-main/main.h	 
    contextを表すstruct.
    メンバは以下の通り
    - xstr str;
      contextの持つ文字列
    - struct segment_list seg_list;
      文節のリスト
    - dic_session_t dic_session;
      コンテキストと一対一対応?
      辞書キャッシュのエントリがどのコンテキストに使われているかを
      把握するのに使う.  
   - struct splitter_context split_info;
      splitterのcontext

  ・struct segment_list
    include/segment.h
    文節リストを表す.
    メンバは以下の通り
    - int nr_segments;
      文節リストの要素数
    - struct seg_ent list_head;
      文節リストの先頭

  ・struct seg_ent
    include/segment.h
    context内に存在する文節の列
    メンバは以下の通り
    - xstr str;
      文字列(実体はcontextの中, らしい. つまりallocateするなということか)
    - int committed;
      確定された候補の番号. 負のときは未確定.
    - int nr_cands;
      候補の数. ↓の配列の長さ.
    - struct cand_ent **cands;
      候補のポインタの配列.
    - int from, len;
    - int core_from, core_len;
    - int nr_seginfo;
      ↓の配列の長さ.
    - struct seg_info **si;
      文節の構成に関する情報へのポインタの配列
    - struct seg_ent *prev,*next;
      リストの前要素, 後要素へのポインタ.

  ・struct seg_info
    include/splitter.h
    文節に関する細かい情報.
    メンバは以下の通り
    - enum {SI_NORMAL, SI_CAND} type;
      seg_infoの持つ情報. 
      SI_NORMAL=品詞情報を持っている, SI_CAND=候補が与えられている.
    - int info_len;
      word_infoでカバーされている部分の長さ.
    - int nr_word_info;
      ↓で表される配列の長さ.
    - struct word_info *word_info;
      word_infoの配列.
    - int core_word_info_index;
      自立語部のインデックス
    - int struct_ratio;
      文節の形式のスコア. 0以上でなければならない. この数字が高いほど確率の高い構造をしている.
    - struct seg_class seg_class;
      文節クラス
    - xstr cand;
      type == SI_CANDの時に候補が入っている.
    - int score;
      seginfoのスコア(seg_infoのスコア?)

  ・struct word_info
    seg_info用の構造体  

  ・struct splitter_context
    include/splitter.h
    splitterのcontext
    メンバは以下の通り
    - struct word_split_info_cache* word_split_info;
      context中の自立語などの情報. 
    - int char_count;
      上記structのメンバcnodeで表される配列の長さ.
    - struct char_ent *ce;
      配列として使う. char_entは文字, 文節境界, 文節の長さ等を持っている模様.
    # なんでこんな構造になっているのだろう?

  ・struct word_split_info_cache;
    context中の自立語などの情報.


4. 関数

   splitterに関する動作に関連した関数の仕様(メモ)です.
   splitterのエントリポイントはanthy_do_context_set_str()のようなので,
   この関数と, これに関する関数について述べています. 
   anthyの文節区切りアルゴリズムは, 基本的に全ての部分文字列を出し, 
   その可能な組み合わせに関して最もスコアの高いものを選択する, という
   感じになっているようです.

  ・int anthy_do_context_set_str(struct anthy_context*, xstr*)
    src-main/context.c
    文節区切のエントリポイント.

  ・void anthy_do_reset_context(struct anthy_context *)
    src-main/context.c
    struct anthy_contextの初期化

  ・void anthy_init_split_context(xstr*, struct splitter_context *sc) 
    src-splitter/splitter.c
    splitterの初期化. 左右両端を文節境界に設定する.
    ここでmake_word_cache()が呼ばれている.
    make_word_cache()が文節区切のキモ.

  ・static void make_word_cache(struct splitter_context *)
    src-splitter/splitter.c
    全ての部分文字列をチェックし, 文節候補を列挙する.

  ・void anthy_make_word_list_all(struct splitter_context *)
    src-splitter/wordlist.c
    文節の形式を満たす部分文字列を列挙する.
    部分文字列は30文字まで(ここソースに即値ベタ書き)

  ・static void make_word_list(struct splitter_context *, seq_ent_t, int, int)
    独立語に対し, 接頭辞, 接尾辞, 付属語を付けたものを文節の候補word_listとして
    cacheに追加する.

  ・static void compose_segment_list(struct anthy_context* , int, int)
    src-main/context.c
    splitterによって配列中に付けられた文節境界のマークから文節リストを
    構成する.

  ・void anthy_sort_seginfo(struct segment_list*)
    src-ordering/infosort.c
    各文節のseginfoをsortする.

  ・void anthy_mark_border(struct splitter_context *, int, int, int)
    src-splitter/splitter.c 
    文節を区切る(境界をマークする)


5. 付属語グラフ

  付属語グラフに関する関数は以下の通りです.

  ・void anthy_scan_node(struct splitter_context*, struct word_list*, xstr* int)
    src-splitter/depgraph.c
    付属語の付いていない状態から検索を開始する.

  ・int anthy_get_node_id_by_name(const char*)
    src-splitter/depgraph.c
    付属語グラフのノード名からそのidを探す. 見付からなかった場合は
    作ってそのidを返す.

  ・int anthy_init_depword_tab(void)
    src-splitter/depgraph.c
    付属語グラフを初期化する. 成功すれば0, 失敗すれば-1を返す.

  ・void anthy_release_depword_tab(void)
    src-splitter/depgraph.c
    付属語グラフを解放する.

  また, 附属グラフの情報はdepgraph/の下にまとめられているようです.


6. テスト

   test/の下で, ./anthyとやるとテストができます.
   詳しくは./anthy --helpで. テストで出るメッセージの構造は

   例文のインデクス:(例文)
   "|"で文節に区切られた例文
   1番目の文節の変換候補とスコア情報,
   …
   n番目の文節の変換候補とスコア情報,

   と, なっています.
   なお, 文節の変換候補とスコア情報に関しては,

   候補(何か謎のもの, 構造のスコア, 何か謎のもの)候補のスコア

   の羅列です.
   となっています. 「何か謎のもの」についてはわかりません.
   「候補のスコア」は三桁毎に","が入っています.


--------------------------------------------------------
岡本 暁広
henkm****@trans***** ((株)トランス・ニュー・テクノロジー)
henkm****@kmc*****    (京大マイコンクラブ)




Anthy-dev メーリングリストの案内
アーカイブの一覧に戻る