7.8. トークナイザー¶
7.8.1. 概要¶
Groongaにはテキストをトークナイズするトークナイザーモージュールがあります。次のケースのときにトークナイザーを使います。
全文検索ではトークナイザーは重要なモジュールです。トークナイザーを変えることで 適合率と再現率 のトレードオフを調整することができます。
一般的に TokenBigram が適切なトークナイザーです。トークナイザーについてよく知らない場合は TokenBigram を使うことをオススメします。
tokenize コマンドと table_tokenize コマンドを使うことでトークナイザーを試すことができます。 tokenize コマンドを使って TokenBigram トークナイザーを試す例を以下に示します。
実行例:
tokenize TokenBigram "Hello World"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "He"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "el"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "ll"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "lo"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "o "
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": " W"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "Wo"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "or"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "rl"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "ld"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "d"
# }
# ]
# ]
7.8.2. 「トークナイズ」とはなにか¶
「トークナイズ」はテキストから0個以上のトークンを抽出する処理です。「トークナイズ」する方法はいくつかあります。
例えば、バイグラムというトークナイズ方法では Hello World は次のトークンにトークナイズされます。
Heelllloo_(_は空白文字という意味)_W(_は空白文字という意味)Woorrlld
上記の例では、 Hello World から10個のトークンを抽出しました。
例えば、空白区切りのトークナイズ方法では Hello World は次のトークンにトークナイズされます。
HelloWorld
上記の例では、Hello World から2つのトークンを抽出しました。
トークンは検索時のキーとして使われます。使用したトークナイズ方法で抽出したトークンでしかインデックス化されたドキュメントを探すことはできません。例えば、トークナイズ方法としてバイグラムを使った場合は ll で Hello World を見つけることができます。しかし、空白区切りのトークナイズ方法を使ったときは ll で Hello World を見つけることはできません。なぜなら、空白区切りのトークナイズ方法は ll というトークンを抽出していないからです。空白区切りのトークナイズ方法は Hello というトークンと World というトークンしか抽出していません。
一般的に、小さいトークンを生成するトークナイズ方法は再現率が高い代わりに適合率が低くなりがちです。一方、大きいトークンを生成するトークナイズ方法は適合率が高い代わりに再現率が低くなりがちです。
例えば、バイグラムというトークナイズ方法では or で Hello World と A or B を検索できます。しかし、「論理和」を検索したい人にとっては Hello World は不要な結果です。これは、適合率が下がったということです。しかし、再現率は上がっています。
空白区切りのトークナイズ方法を使った場合は or で A or B だけが見つかります。なぜなら、空白区切りのトークナイズ方法では World は World という1つのトークンだけにトークナイズされるからです。これは、「論理和」を探したい人にとっては適合率が挙がっています。しかし、 Hello World も or を含んでいるのに見つかっていないので再現率が下がっています。
7.8.3. 組み込みトークナイザー¶
以下は組み込みのトークナイザーのリストです。
TokenBigramTokenBigramSplitSymbolTokenBigramSplitSymbolAlphaTokenBigramSplitSymbolAlphaDigitTokenBigramIgnoreBlankTokenBigramIgnoreBlankSplitSymbolTokenBigramIgnoreBlankSplitSymbolAlphaTokenBigramIgnoreBlankSplitSymbolAlphaDigitTokenUnigramTokenTrigramTokenDelimitTokenDelimitNullTokenMecabTokenRegexp
7.8.3.1. TokenBigram¶
TokenBigram はバイグラムベースのトークナイザーです。多くのケースでは、このトークナイザーを使うことをオススメします。
バイグラムというトークナイズ方法は、隣り合った2つの文字を1つのトークンとしてテキストをトークナイズします。例えば、 Hello は次のトークンにトークナイズします。
Heellllo
バイグラムというトークナイズ方法は再現性に優れています。なぜなら、2文字以上の文字のクエリーに対してはすべてのテキストを見つけることができるからです。
一般的に、1文字のクエリーではすべてのテキストを見つけることはできません。なぜなら、1つの文字のトークンが存在しないからです。しかし、Groongaでは1文字のクエリーでもすべてのテキストを見つけることができます。なぜなら、Groongaは前方一致検索によりクエリーで指定した文字で始まるトークンをすべて見つけることができるからです。例えば、Groongaは l というクエリーから ll というトークンと lo というトークンを見つけることができます。
バイグラムというトークナイズ方法は適合率はそれほど優れていません。なぜなら、単語の一部にクエリーが含まれていればすべてのテキストが見つかってしまうからです。例えば、 or で world が見つかります。これは非ASCIIを使う言語よりASCIIのみを使う言語で顕著です。以降の説明で触れる通り、 TokenBigram はこの問題を解決しています。
TokenBigram の挙動は ノーマライザー を使うかどうかで変わります。
ノーマライザーを使っていない場合は TokenBigram は純粋なバイグラム(最後のトークンをのぞいてすべてのトークンを2文字にする)のトークナイズ方法を使います。
実行例:
tokenize TokenBigram "Hello World"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "He"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "el"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "ll"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "lo"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "o "
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": " W"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "Wo"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "or"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "rl"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "ld"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "d"
# }
# ]
# ]
ノーマライザーを使っている場合は TokenBigram はASCIIの文字には空白区切りのようなトークナイズ方法を使います。非ASCII文字にはバイグラムのトークナイズ方法を使います。
もしかしたら、複数の方法が混ざったこの挙動はわかりにくいかもしれません。しかし、英語のテキスト(ASCII文字列のみ)や日本語テキスト(ASCII文字列と非ASCII文字列が混ざっている)ような多くのユースケースでは合理的な方法です。
ASCII文字しか使わない多くの言語は単語の区切りに空白文字を使っています。このようなケースに空白区切りのトークナイズ方法は適切です。
非ASCII文字を使う言語では単語の区切りに空白文字を使いません。このケースにはバイグラムなトークナイズ方法は適切です。
複数の言語が混ざっている場合は、複数の方法を組み合わせたトークナイズ方法が適切です。
ASCII文字にバイグラムなトークナイズ方法を使いたい場合は TokenBigramSplitSymbolAlpha のような TokenBigramSplitXXX というトークナイザーを参照してください。
例を使いながら TokenBigram の挙動を確認しましょう。
TokenBigram はASCII文字には1つ以上の空白文字をトークンの区切りとして使います。
実行例:
tokenize TokenBigram "Hello World" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "hello"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "world"
# }
# ]
# ]
TokenBigram はASCII文字には文字の種類が変わったところをトークンの区切りとします。文字の種類は次のどれかです。
- アルファベット
- 数字
- 記号(たとえば
(、)、!など)- ひらがな
- カタカナ
- 漢字
- その他
次の例は2つのトークン区切りを示しています。
100(数字)とcents(アルファベット)の間のところcents(アルファベット)と!!!(記号)の間のところ
実行例:
tokenize TokenBigram "100cents!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "100"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "cents"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "!!!"
# }
# ]
# ]
以下は TokenBigram が非ASCII文字にはトークナイズ方法としてバイグラムを使う例です。
実行例:
tokenize TokenBigram "日本語の勉強" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "日本"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "本語"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "語の"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "の勉"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "勉強"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "強"
# }
# ]
# ]
7.8.3.2. TokenBigramSplitSymbol¶
TokenBigramSplitSymbol は TokenBigram と似ています。違いは記号の扱いです。 TokenBigramSplitSymbol は記号のトークナイズ方法にバイグラムを使います。
実行例:
tokenize TokenBigramSplitSymbol "100cents!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "100"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "cents"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
7.8.3.3. TokenBigramSplitSymbolAlpha¶
TokenBigramSplitSymbolAlpha は TokenBigram と似ています。違いは記号とアルファベットの扱いです。 TokenBigramSplitSymbolAlpha は記号とアルファベットのトークナイズ方法にバイグラムを使います。
実行例:
tokenize TokenBigramSplitSymbolAlpha "100cents!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "100"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "ce"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "en"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "nt"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "ts"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "s!"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
7.8.3.4. TokenBigramSplitSymbolAlphaDigit¶
TokenBigramSplitSymbolAlphaDigit は TokenBigram と似ています。違いは記号とアルファベットと数字の扱いです。 TokenBigramSplitSymbolAlphaDigit は記号とアルファベット数字のトークナイズ方法にバイグラムを使います。つまり、すべての文字をバイグラムでトークナイズします。
実行例:
tokenize TokenBigramSplitSymbolAlphaDigit "100cents!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "10"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "00"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "0c"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "ce"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "en"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "nt"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "ts"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "s!"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
7.8.3.5. TokenBigramIgnoreBlank¶
TokenBigramIgnoreBlank は TokenBigram と似ています。違いは空白文字の扱いです。 TokenBigramIgnoreBlank は連続する記号と非ASCII文字の間にある空白文字を無視します。
日 本 語 ! ! ! というテキストを使うと違いがわかります。なぜならこのテキストは記号と非ASCII文字を両方含んでいるからです。
TokenBigram での実行結果です。
実行例:
tokenize TokenBigram "日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "日"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "本"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "語"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
TokenBigramIgnoreBlank での実行結果です。
実行例:
tokenize TokenBigramIgnoreBlank "日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "日本"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "本語"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "語"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "!!!"
# }
# ]
# ]
7.8.3.6. TokenBigramIgnoreBlankSplitSymbol¶
TokenBigramIgnoreBlankSplitSymbol は TokenBigram と似ています。違いは次の通りです。
- 空白文字の扱い
- 記号の扱い
TokenBigramIgnoreBlankSplitSymbol は連続した記号と非ASCII文字の間の空白文字を無視します。
TokenBigramIgnoreBlankSplitSymbol は記号をバイグラムでトークナイズします。
日 本 語 ! ! ! というテキストを使うと違いがわかります。なぜならこのテキストは記号と非ASCII文字を両方含んでいるからです。
TokenBigram での実行結果です。
実行例:
tokenize TokenBigram "日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "日"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "本"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "語"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
TokenBigramIgnoreBlankSplitSymbol の実行結果です。
実行例:
tokenize TokenBigramIgnoreBlankSplitSymbol "日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "日本"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "本語"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "語!"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
7.8.3.7. TokenBigramIgnoreBlankSplitSymbolAlpha¶
TokenBigramIgnoreBlankSplitSymbolAlpha は TokenBigram と似ています。違いは次の通りです。
- 空白文字の扱い
- 記号とアルファベットの扱い
TokenBigramIgnoreBlankSplitSymbolAlpha は連続した記号と非ASCII文字の間の空白文字を無視します。
TokenBigramIgnoreBlankSplitSymbolAlpha は記号とアルファベットをバイグラムでトークナイズします。
Hello 日 本 語 ! ! ! というテキストを使うと違いがわかります。なぜなら空白文字入りの記号と非ASCII文字だけでなく、アルファベットも含んでいるからです。
TokenBigram での実行結果です。
実行例:
tokenize TokenBigram "Hello 日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "hello"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "日"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "本"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "語"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
TokenBigramIgnoreBlankSplitSymbolAlpha の実行結果です。
実行例:
tokenize TokenBigramIgnoreBlankSplitSymbolAlpha "Hello 日 本 語 ! ! !" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "he"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "el"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "ll"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "lo"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "o日"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "日本"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "本語"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "語!"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "!"
# }
# ]
# ]
7.8.3.8. TokenBigramIgnoreBlankSplitSymbolAlphaDigit¶
TokenBigramIgnoreBlankSplitSymbolAlphaDigit は TokenBigram と似ています。違いは次の通りです。
- 空白文字の扱い
- 記号とアルファベットと数字の扱い
TokenBigramIgnoreBlankSplitSymbolAlphaDigit は連続した記号と非ASCII文字の間の空白文字を無視します。
TokenBigramIgnoreBlankSplitSymbolAlphaDigit は記号、アルファベット、数字をバイグラムでトークナイズします。つまり、すべての文字をバイグラムでトークナイズします。
Hello 日 本 語 ! ! ! 777 というテキストを使うと違いがわかります。なぜなら、このテキストは空白文字入りの記号と非ASCII文字だけでなく、アルファベットと数字も含んでいるからです。
TokenBigram での実行結果です。
実行例:
tokenize TokenBigram "Hello 日 本 語 ! ! ! 777" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "hello"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "日"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "本"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "語"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "!"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "777"
# }
# ]
# ]
TokenBigramIgnoreBlankSplitSymbolAlphaDigit の実行結果です。
実行例:
tokenize TokenBigramIgnoreBlankSplitSymbolAlphaDigit "Hello 日 本 語 ! ! ! 777" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "he"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "el"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "ll"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "lo"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "o日"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "日本"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "本語"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "語!"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "!!"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "!7"
# },
# {
# "position": 11,
# "force_prefix": false,
# "value": "77"
# },
# {
# "position": 12,
# "force_prefix": false,
# "value": "77"
# },
# {
# "position": 13,
# "force_prefix": false,
# "value": "7"
# }
# ]
# ]
7.8.3.9. TokenUnigram¶
TokenUnigram は TokenBigram に似ています。違いはトークンの単位です。 TokenBigram は各トークンが2文字ですが、 TokenUnigram は各トークンが1文字です。
実行例:
tokenize TokenUnigram "100cents!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "100"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "cents"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "!!!"
# }
# ]
# ]
7.8.3.10. TokenTrigram¶
TokenTrigram は TokenBigram に似ています。違いはトークンの単位です。 TokenBigram は各トークンが2文字ですが、 TokenTrigram は各トークンが3文字です。
実行例:
tokenize TokenTrigram "10000cents!!!!!" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "10000"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "cents"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "!!!!!"
# }
# ]
# ]
7.8.3.11. TokenDelimit¶
TokenDelimit は1つ以上の空白文字( U+0020 )で分割してトークンを抽出します。たとえば、 Hello World は Hello と World にトークナイズされます。
TokenDelimit はタグテキストに適切です。 groonga full-text-search http というテキストから groonga 、 full-text-search 、 http を抽出します。
以下は TokenDelimit の例です。
実行例:
tokenize TokenDelimit "Groonga full-text-search HTTP" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "groonga"
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "full-text-search"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "http"
# }
# ]
# ]
TokenDelimit はオプションを指定することもできます。 TokenDelimit は delimiter オプションと pattern オプションを持っています。
delimiter option can split token with a specified characters.
例えば、以下のように Hello,World は、Hello と World にトークナイズされます。
実行例:
tokenize 'TokenDelimit("delimiter", ",")' "Hello,World"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "value": "Hello",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "World",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
delimiter オプションは、複数の区切り文字を指定することもできます。
例えば、以下のように Hello, World は、Hello と World にトークナイズされます。
実行例:
tokenize 'TokenDelimit("delimiter", ",", "delimiter", " ")' "Hello, World"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "value": "Hello",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "World",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
pattern オプションは、正規表現でトークンを分割できます。pattern オプションを使うことで、不要な空白を除去することができます。
例えば、以下のように pattern オプションによって、 This is a pen. This is an apple は This is a pen と This is an apple にトークナイズされます。
通常、 This is a pen. This is an apple. を . で分割する際は、"This is an apple."の文頭に不要な空白が含まれます。
以下の例の用に pattern オプションを使うことで、その不要な空白を除去できます。
実行例:
tokenize 'TokenDelimit("pattern", "\\.\\s*")' "This is a pen. This is an apple."
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "value": "This is a pen.",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "This is an apple.",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
pattern オプションを使って複雑な条件でトークンを抽出できます。
例えば、以下のように delimiter オプションを使って、 これはペンですか!?リンゴですか?「リンゴです。」 を これはペンですか と リンゴですか 、 「リンゴです。」 とトークナイズします。
実行例:
tokenize 'TokenDelimit("pattern", "([。!?]+(?![)」])|[\\r\\n]+)\\s*")' "これはペンですか!?リンゴですか?「リンゴです。」"
# [
# [
# 0,
# 1545179416.22277,
# 0.0002887248992919922
# ],
# [
# {
# "value": "これはペンですか",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "リンゴですか",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "「リンゴです。」",
# "position": 2,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
上記の正規表現の末尾の \\s* は、区切り文字の後ろの0個以上の空白にマッチします。
[。!?]+ は、1個以上の 。 または !、 ? にマッチします。例えば、 [。!?]+ は これはペンですか!? の !? にマッチします。
(?![)」]) は否定先読みです。 (?![)」]) は ) または 」 にマッチしない場合にマッチします。否定先読みは直前の正規表現と合わせて解釈します。
したがって、 [。!?]+(?![)」]) を解釈します。
[。!?]+(?![)」]) は、。 または !、 ? の後ろに ) または 」 が無い場合にマッチします。
つまり、 [。!?]+(?![)」]) は、 これはペンですか。 の 。 にマッチしますが、 「リンゴです。」 の 。 にはマッチしません。 。 の後ろに 」 があるためです。
[\\r\\n]+ は、1個以上の改行文字にマッチします。
まとめると、 ([。!?]+(?![)」])|[\\r\\n]+)\\s* は、 。 と ! と ?、 改行文字を区切り文字としています。ただし、 。 または !、 ? の後ろに ) または 」 がある場合は、 。 や !、 ? は区切り文字としません。
7.8.3.12. TokenDelimitNull¶
TokenDelimitNull は TokenDelimit に似ています。違いは区切り文字です。 TokenDelimit は空白文字( U+0020 )を使いますが、 TokenDelimitNull はNUL文字( U+0000 )を使います。
TokenDelimitNull もタグテキストに適切です。
以下は TokenDelimitNull の例です。
実行例:
tokenize TokenDelimitNull "Groonga\u0000full-text-search\u0000HTTP" NormalizerAuto
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": "groongau0000full-text-searchu0000http"
# }
# ]
# ]
7.8.3.13. TokenMecab¶
TokenMecab は MeCab 形態素解析器をベースにしたトークナイザーです。
MeCabは日本語に依存していません。その言語用の辞書を用意すれば日本語以外でもMeCabを使えます。日本語用の辞書には NAIST Japanese Dictionary を使えます。
TokenMecab を使うには、追加のパッケージをインストールする必要があります。追加のパッケージをインストールする方法の詳細については、各OSのインストール方法 を参照して下さい。
TokenMecab は再現率より適合率に優れています。 TokenBigram では 京都 というクエリーで 東京都 も 京都 も見つかりますが、この場合は 東京都 は期待した結果ではありません。 TokenMecab を使うと 京都 というクエリーで 京都 だけを見つけられます。
新語をサポートしたい場合は、MeCabの辞書を更新し続ける必要があります。これはメンテナンスコストがかかります。( TokenBigram には辞書のメンテナンスコストはありません。なぜなら、 TokenBigram は辞書を使っていないからです。)新語への対応に mecab-ipadic-NEologd : Neologism dictionary for MeCab が役に立つかもしれません。
以下は TokenMeCab の例です。 東京都 は 東京 と 都 にトークナイズされています。 京都 というトークンはありません。
実行例:
tokenize TokenMecab "東京都"
# [
# [
# 0,
# 1545812631.661493,
# 0.0002415180206298828
# ],
# [
# {
# "value": "東京",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "都",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
TokenMecab はオプションを指定することもできます。TokenMecab は、target_class オプション、 include_class オプション、 include_reading オプション、 include_form オプションと use_reading オプションがあります。
target_class オプションは、指定した品詞のトークンを検索します。例えば、以下のように名詞のみを検索できます。
実行例:
tokenize 'TokenMecab("target_class", "名詞")' '彼の名前は山田さんのはずです。'
# [
# [
# 0,
# 1545810238.195525,
# 0.0003066062927246094
# ],
# [
# {
# "value": "彼",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "名前",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "山田",
# "position": 2,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "さん",
# "position": 3,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "はず",
# "position": 4,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
target_class オプションは、サブクラスを指定することや、 + や - を使って、特定の品詞を追加または、除外することもできます。したがって、以下のように人名の接尾語と非自立語を除いた名詞を検索することもできます。
このようにして、ノイズとなるトークンを除外して検索できます。
実行例:
tokenize 'TokenMecab("target_class", "-名詞/非自立", "target_class", "-名詞/接尾/人名", "target_class", "名詞")' '彼の名前は山田さんのはずです。'
# [
# [
# 0,
# 1545810363.771334,
# 0.0003197193145751953
# ],
# [
# {
# "value": "彼",
# "position": 0,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "名前",
# "position": 1,
# "force_prefix": false,
# "force_prefix_search": false
# },
# {
# "value": "山田",
# "position": 2,
# "force_prefix": false,
# "force_prefix_search": false
# }
# ]
# ]
7.8.3.14. TokenRegexp¶
バージョン 5.0.1 で追加.
ご用心
このトークナイザーは実験的です。仕様が変わる可能性があります。
ご用心
このトークナイザーはUTF-8でしか使えません。EUC-JPやShift_JISなどと一緒には使えません。
TokenRegexp はインデックスを使った正規表現検索をサポートするトークナイザーです。
一般的に、正規表現検索は逐次検索で実行します。しかし、次のケースはインデックスを使って検索できます。
helloのようにリテラルしかないケース\A/home/aliceのようにテキストの最初でのマッチとリテラルのみのケース\.txt\zのようにテキストの最後でのマッチとリテラルのみのケース
多くのケースでは、逐次検索よりもインデックスを使った検索の方が高速です。
TokenRegexp はベースはバイグラムを使います。 TokenRegexp は、インデックス時に、テキストの先頭にテキストの先頭であるというマーク( U+FFEF )を入れ、テキストの最後にテキストの最後であるというマーク( U+FFF0 )を入れます。
実行例:
tokenize TokenRegexp "/home/alice/test.txt" NormalizerAuto --mode ADD
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# {
# "position": 0,
# "force_prefix": false,
# "value": ""
# },
# {
# "position": 1,
# "force_prefix": false,
# "value": "/h"
# },
# {
# "position": 2,
# "force_prefix": false,
# "value": "ho"
# },
# {
# "position": 3,
# "force_prefix": false,
# "value": "om"
# },
# {
# "position": 4,
# "force_prefix": false,
# "value": "me"
# },
# {
# "position": 5,
# "force_prefix": false,
# "value": "e/"
# },
# {
# "position": 6,
# "force_prefix": false,
# "value": "/a"
# },
# {
# "position": 7,
# "force_prefix": false,
# "value": "al"
# },
# {
# "position": 8,
# "force_prefix": false,
# "value": "li"
# },
# {
# "position": 9,
# "force_prefix": false,
# "value": "ic"
# },
# {
# "position": 10,
# "force_prefix": false,
# "value": "ce"
# },
# {
# "position": 11,
# "force_prefix": false,
# "value": "e/"
# },
# {
# "position": 12,
# "force_prefix": false,
# "value": "/t"
# },
# {
# "position": 13,
# "force_prefix": false,
# "value": "te"
# },
# {
# "position": 14,
# "force_prefix": false,
# "value": "es"
# },
# {
# "position": 15,
# "force_prefix": false,
# "value": "st"
# },
# {
# "position": 16,
# "force_prefix": false,
# "value": "t."
# },
# {
# "position": 17,
# "force_prefix": false,
# "value": ".t"
# },
# {
# "position": 18,
# "force_prefix": false,
# "value": "tx"
# },
# {
# "position": 19,
# "force_prefix": false,
# "value": "xt"
# },
# {
# "position": 20,
# "force_prefix": false,
# "value": "t"
# },
# {
# "position": 21,
# "force_prefix": false,
# "value": ""
# }
# ]
# ]

