フィルタ

文字フィルタ(Character Filter)とトークンフィルタ(Token Filter)は、lindera-analysisTokenizerパイプラインにおける前処理・後処理の2つの段階です。

  • 文字フィルタはセグメンテーションの前に入力テキストを変換します。バイトオフセットは自動的に補正されるため、変換後のテキストに対して生成されたトークンでも、元のフィルタ前のテキストにおける位置が正しく報告されます。
  • トークンフィルタはSegmenterが生成したトークンのリストをセグメンテーションの後に変換します。

どちらのフィルタも設定方法は共通で、kind文字列(CLIの--character-filter / --token-filterフラグでもkind:{"json": "args"}という形式で使用されます)と、フィルタ固有のパラメータを持つJSONのargsオブジェクトで構成されます。

文字フィルタ

文字フィルタはYAML設定ファイルのcharacter_filtersキーで設定します。各エントリは順番に適用され、あるフィルタの出力が次のフィルタの入力になります。

unicode_normalize

4種類の標準的なUnicode正規化形式のいずれかを使って入力テキストを正規化します。

パラメータ:

パラメータ必須説明
kindstringはいnfcnfdnfkcnfkdのいずれか

例:

{
  "kind": "unicode_normalize",
  "args": {
    "kind": "nfkc"
  }
}

japanese_iteration_mark

日本語の踊り字(繰り返し記号)であるを、それぞれが繰り返す文字に置き換えて正規化します。ひらがな・カタカナの繰り返し記号については、必要に応じて濁点の付与・除去も行います。

パラメータ:

パラメータ必須デフォルト説明
normalize_kanjiboolいいえfalse漢字の踊り字を正規化する
normalize_kanaboolいいえfalseひらがな・カタカナの踊り字を正規化する

例:

{
  "kind": "japanese_iteration_mark",
  "args": {
    "normalize_kanji": true,
    "normalize_kana": true
  }
}

mapping(文字フィルタ)

mappingのキーに一致する部分を対応する値に置き換えます。入力テキスト全体に対して、Aho-Corasickオートマトンによる最長一致検索を行います。

パラメータ:

パラメータ必須説明
mappingobject(string to string)はい置換対象の部分文字列と、その置換先の対応表

例:

{
  "kind": "mapping",
  "args": {
    "mapping": {
      "リンデラ": "Lindera"
    }
  }
}

regex

正規表現にマッチした箇所をすべて、リテラルな置換文字列で置き換えます。キャプチャグループの内容は置換文字列に展開されません。

パラメータ:

パラメータ必須説明
patternstringはい正規表現(regexクレートの構文)
replacementstringはいpatternにマッチした箇所すべてを置き換えるリテラル文字列

例:

{
  "kind": "regex",
  "args": {
    "pattern": "\\s{2,}",
    "replacement": " "
  }
}

トークンフィルタ

トークンフィルタはYAML設定ファイルのtoken_filtersキーで設定します。各フィルタは、Segmenterが生成したトークンリストに対して順番に適用されます。

japanese_base_form

トークンの表層形を、辞書のbase_form(またはorthographic_base_form)フィールドに登録された原形(辞書形)に置き換えます。動詞・形容詞のレンマ化(見出し語化)として機能します。未知語処理によって生成されたトークン(token.word_id.is_unknown())は変更されません。

このフィルタに設定パラメータはありません。

例:

{
  "kind": "japanese_base_form"
}

japanese_compound_word

品詞タグがtagsのいずれかに一致する連続したトークンを、1つの複合語トークンに結合します。

パラメータ:

パラメータ必須説明
tagsarray<string>はい結合対象となるトークンを示す品詞タグ(カンマ区切りで最大4階層)
new_tagstringいいえ結合後のトークンに付与する品詞タグ。省略した場合は複合語が付与される

例:

{
  "kind": "japanese_compound_word",
  "args": {
    "tags": [
      "名詞,数",
      "名詞,接尾,助数詞"
    ],
    "new_tag": "名詞,数"
  }
}

japanese_kana

トークンテキストをひらがなとカタカナの間で相互変換します。

パラメータ:

パラメータ必須説明
kindstringはい"hiragana"はカタカナをひらがなに、"katakana"はひらがなをカタカナに変換する

例:

{
  "kind": "japanese_kana",
  "args": {
    "kind": "hiragana"
  }
}

japanese_katakana_stem

カタカナのトークンの末尾にある長音記号(、U+30FC)を除去します。ただし、トークンの文字数がminより大きい場合のみ除去されます。

パラメータ:

パラメータ必須説明
min正の整数はい末尾の長音記号をステミングする対象となる、カタカナトークンの最小文字数

例:

{
  "kind": "japanese_katakana_stem",
  "args": {
    "min": 3
  }
}

japanese_keep_tags

品詞タグがtagsのいずれかに一致するトークンのみを保持し、それ以外を除去します。

タグは 4 階層のカンマ区切りに正規化され(不足分は * で補完)、各トークンの先頭 4 つの品詞詳細と完全一致で比較されます。IPADIC の助詞トークンは必ず 助詞,係助詞 のようにサブカテゴリを持つため、助詞 単独では一致しません。一方、助動詞はサブカテゴリを持たないため(助動詞,*,*,*)、助動詞 単独で一致します。この動作は japanese_stop_tags も同様です。

パラメータ:

パラメータ必須説明
tagsarray<string>はい保持する品詞タグ(カンマ区切りで最大4階層)

例:

{
  "kind": "japanese_keep_tags",
  "args": {
    "tags": [
      "名詞,一般"
    ]
  }
}

japanese_number

トークンの表層テキストに含まれる日本語の数値表現(漢数字、大字、全角数字)をアラビア数字に変換します。

パラメータ:

パラメータ必須説明
tagsarray<string>またはnullいいえ変換対象を限定する品詞タグ(カンマ区切りで最大4階層)。省略またはnullの場合はすべてのトークンが変換対象になる

例:

{
  "kind": "japanese_number",
  "args": {
    "tags": [
      "名詞,数"
    ]
  }
}

japanese_reading_form

トークンの表層テキストを、辞書のreadingフィールドに登録された読み(カタカナ)に置き換えます。未知語処理によって生成されたトークン(token.word_id.is_unknown())は変更されません。

このフィルタに設定パラメータはありません。

例:

{
  "kind": "japanese_reading_form"
}

japanese_stop_tags

品詞タグがtagsのいずれかに一致するトークンを除去します。

パラメータ:

パラメータ必須説明
tagsarray<string>はい除去する品詞タグ(カンマ区切りで最大4階層)

例:

{
  "kind": "japanese_stop_tags",
  "args": {
    "tags": [
      "助詞,格助詞,一般",
      "助詞,係助詞",
      "助詞,連体化",
      "助動詞"
    ]
  }
}

keep_words

表層テキストがwordsのいずれかに完全一致するトークンのみを保持します。

パラメータ:

パラメータ必須説明
wordsarray<string>はい保持する表層形の一覧

例:

{
  "kind": "keep_words",
  "args": {
    "words": [
      "すもも",
      "もも"
    ]
  }
}

korean_keep_tags

最初の品詞タグがtagsのいずれかに一致する韓国語トークンのみを保持します。

パラメータ:

パラメータ必須説明
tagsarray<string>はい保持する品詞タグ

例:

{
  "kind": "korean_keep_tags",
  "args": {
    "tags": [
      "NNG"
    ]
  }
}

korean_reading_form

トークンの表層テキストを、辞書のreadingフィールドに登録された読みに置き換えます。未知語処理によって生成されたトークン(token.word_id.is_unknown())は変更されません。

このフィルタに設定パラメータはありません。

例:

{
  "kind": "korean_reading_form"
}

korean_stop_tags

最初の品詞タグがtagsのいずれかに一致する韓国語トークンを除去します。

パラメータ:

パラメータ必須説明
tagsarray<string>はい除去する品詞タグ

例:

{
  "kind": "korean_stop_tags",
  "args": {
    "tags": [
      "EP",
      "EF",
      "JKG"
    ]
  }
}

length

表層テキストの文字数が[min, max]の範囲に収まるトークンのみを保持します。

パラメータ:

パラメータ必須説明
min符号なし整数いいえ最小文字数(この値を含む)
max符号なし整数いいえ最大文字数(この値を含む)

例:

{
  "kind": "length",
  "args": {
    "min": 2,
    "max": 3
  }
}

lowercase

トークンの表層テキストを小文字に変換します。

このフィルタに設定パラメータはありません。

例:

{
  "kind": "lowercase"
}

mapping(トークンフィルタ)

mappingのキーに一致する部分を、各トークンの表層テキスト内で対応する値に置き換えます。Aho-Corasickオートマトンによる最長一致検索を使用します。文字フィルタのmappingのトークン版に相当します。

パラメータ:

パラメータ必須説明
mappingobject(string to string)はい置換対象の部分文字列と、その置換先の対応表

例:

{
  "kind": "mapping",
  "args": {
    "mapping": {
      "籠": "篭"
    }
  }
}

remove_diacritical_mark

トークンの表層テキストからダイアクリティカルマーク(発音区別符号)を除去し、その後テキストの元のUnicode正規化形式を再適用します。

パラメータ:

パラメータ必須デフォルト説明
japaneseboolいいえfalse日本語の濁点・半濁点の結合文字(分解済みの濁音・半濁音仮名に含まれるものなど)も除去する

例:

{
  "kind": "remove_diacritical_mark",
  "args": {
    "japanese": false
  }
}

stop_words

表層テキストがwordsのいずれかに完全一致するトークンを除去します。

パラメータ:

パラメータ必須説明
wordsarray<string>はい除去する表層形の一覧

例:

{
  "kind": "stop_words",
  "args": {
    "words": [
      "も",
      "の"
    ]
  }
}

uppercase

トークンの表層テキストを大文字に変換します。

このフィルタに設定パラメータはありません。

例:

{
  "kind": "uppercase"
}

YAML設定

文字フィルタとトークンフィルタは、Segmenterと一緒に1つのYAMLファイルで設定します。ファイル全体の形式は設定を参照してください。関連する部分だけを抜粋すると次のようになります。

character_filters:
  - kind: "unicode_normalize"
    args:
      kind: "nfkc"
  - kind: "japanese_iteration_mark"
    args:
      normalize_kanji: true
      normalize_kana: true

token_filters:
  - kind: "japanese_stop_tags"
    args:
      tags:
        - "助詞,格助詞,一般"
        - "助詞,係助詞"
        - "助詞,連体化"
        - "助動詞"
  - kind: "japanese_katakana_stem"
    args:
      min: 3
  - kind: "lowercase"
  - kind: "length"
    args:
      min: 2

Rust API

文字フィルタとトークンフィルタは、プログラムから作成・適用することもできます。

use lindera::dictionary::load_dictionary;
use lindera::mode::Mode;
use lindera::segmenter::Segmenter;
use lindera_analysis::character_filter::BoxCharacterFilter;
use lindera_analysis::character_filter::unicode_normalize::{
    UnicodeNormalizeCharacterFilter, UnicodeNormalizeKind,
};
use lindera_analysis::token_filter::BoxTokenFilter;
use lindera_analysis::token_filter::japanese_stop_tags::JapaneseStopTagsTokenFilter;
use lindera_analysis::token_filter::japanese_katakana_stem::JapaneseKatakanaStemTokenFilter;
use lindera_analysis::tokenizer::Tokenizer;
use lindera::LinderaResult;

fn main() -> LinderaResult<()> {
    let dictionary = load_dictionary("embedded://ipadic")?;
    let segmenter = Segmenter::new(Mode::Normal, dictionary, None);

    let mut tokenizer = Tokenizer::new(segmenter);

    // 文字フィルタを追加
    let normalize_filter = UnicodeNormalizeCharacterFilter::new(UnicodeNormalizeKind::NFKC);
    tokenizer.append_character_filter(BoxCharacterFilter::from(normalize_filter));

    // トークンフィルタを追加
    let stop_tags_filter = JapaneseStopTagsTokenFilter::new(
        vec![
            "助詞,格助詞,一般".to_string(),
            "助詞,係助詞".to_string(),
            "助詞,連体化".to_string(),
            "助動詞".to_string(),
        ]
        .into_iter()
        .collect(),
    );
    tokenizer.append_token_filter(BoxTokenFilter::from(stop_tags_filter));

    let katakana_stem_filter =
        JapaneseKatakanaStemTokenFilter::new(std::num::NonZeroUsize::new(3).unwrap());
    tokenizer.append_token_filter(BoxTokenFilter::from(katakana_stem_filter));

    // フィルタを適用してトークナイズ
    let tokens = tokenizer.tokenize("Linderaは形態素解析エンジンです。")?;

    for token in tokens {
        println!(
            "token: {:?}, details: {:?}",
            token.surface, token.details
        );
    }

    Ok(())
}

append_character_filterappend_token_filterメソッドは、フィルタを追加した順番で登録します。文字フィルタはセグメンテーション前のテキストに対して順次適用され、トークンフィルタはセグメンテーション後のトークンリストに対して順次適用されます。