ページ構成にあたって次の情報源を参考にした。
伝統的な自然言語処理において利用される辞書として、単語辞書の他にシソーラス (thesaurus)とコーパス (corpus)がある。 シソーラスは英語で類語辞典を意味し、treasure (宝物)同じ語源を持つ。日本語では、単なる類語辞典を越えて、単語を体系的に分類した辞典を指すことが多い。現在もアクセス可能なシソーラスに、日本語WordNetがある。 コーパスは、自然言語の文章を大量に集めたもの。言語資源開発センターなどからアクセスできる。
文章を機械的に処理する際、性能と速度はトレードオフの関係にある。英語のスペルチェックを考えると、単語単位の処理ではスペルミスしか検出できないが、動詞の前の主語を考慮すれば三単現のsのような語尾変化を検出できるようになる。そこで、文章を処理する単位を複数の連続する単語とする手法をN-gram (nグラム)と呼ぶ。
自然言語処理では、文を単語単位で分割して扱う。英語の場合は単語と単語の間にスペースがあるため、単語単位の分割が簡単である。日本語の場合は品詞ごとに分割を行う。この分割を分かち書きといい、分割した単語を特に形態素という。日本語の形態素解析ライブラリとしては、MeCabやChaSenが有名である。
プログラムでの処理のためには、それぞれの形態素を識別する必要があるが、分割した形態素の中には使用頻度が非常に低いものもある。例えば、形式言語における「線形拘束オートマトン」という単語は、「プッシュダウンオートマトン」や「チューリングマシン」に比べて使用機会が少ない。また、後続処理で形態素同士の関連性を計算することを考えると、使用機会の少ない形態素は取り除きたい。そこで、「線形拘束オートマトン」を「線形」「拘束」「オートマトン」といったサブワードに分割することが考えられる。このようにして分割したサブワードをトークンという。
サブワード分割において、すべての文字を一度分割し、その後隣り合う頻度が高い文字を結合する手法をBPE(Byte-Pair Encoding)という。BPEはシンプルな手法だが、語源的に分かれていても差し支えない単語を、出現頻度が高いという理由で結合させてしまうおそれがあり、勿体ない。例えば(かなり無理矢理だが)次のようなコーパスとサブワードを考える。
# コーパス
unbelievable, unbreakable, unluck, lucky
# サブワード
[un, b, elievable, reakable, lu, ck, y]
ここで、”un+b”と”lu+ck”を比較する。BPEの場合は、それぞれの出現頻度が等しいため、新たに結合しペア化する可能性も等しい。しかしヒューリスティックには、”un”は否定の接頭語だから、結合しなくても良さそうだ。そこで、ペアの出現頻度をそれぞれのサブワードの出現頻度で割ることを考える。
# ペアの出現頻度
(un+b): 2
(lu+uk): 2
# サブワードの出現頻度
un: 3 (unbelievable, unbreakable, unlucky)
b: 2 (unbelievable, unbreakable)
lu: 2 (unlucky, lucky)
uk: 2 (unlucky, lucky)
# スコア計算
(un+b): 2 / (3 * 2) = 0.333
(l+u): 2 / (2 * 2) = 0.5
すると、”un”が”unluck”にも出現しているため、スコアが下がる。このような手法をWordPieceという。[^dalab_japanese-llm-tokenizer]
マルチバイト文字を、言語依存の形態素解析なくトークン化するための手法として、SentencePieceがある。[^kudo_2018] [^kudo_2018]: Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates
SentencePieceは正規化とサブワード分割を含む複数のステップからなる。正規化では主にUnicode NFKCを用いる。[^dalab_japanese-llm-tokenizer]続いて、特にサブワード分割について解説したい。BPEやWordPieceでは、サブワードのペアの出現頻度を見る一方で、コーパスの尤もらしさに対するペアの貢献度合いを測らない。例えば、次のようなコーパスを考える。 [^dalab_japanese-llm-tokenizer]: 日本語LLMにおけるトークナイザーの重要性
# コーパス
lamb, wombat
# サブワードのセグメンテーション(文字単位)
[l, a, m, b, w, o, m, b, a, t]
# サブワードのセグメンテーション(BPEを用いた例)
[mb, l, a, w, o, m, b, a, t]
# サブワードのセグメンテーション(SentencePieceを用いた例)
[lamb, w, o, m, b, a, t]
サブワードの組合せをセグメンテーションと呼ぶが、BPEでは隣り合う文字の出現頻度だけを見るため、特に意味を持たない”mb”のようなサブワードが生まれる。しかし、”mb”という文字を知っているからと言って、”l”+”a”+”mb”という文字の並びを生成する確率がどれだけ高まるだろうか?同じ1トークンなら、”lamb”をそのまま暗記したほうがずっと意味がありそうだ。
そこで、まず様々なサブワードのペアを含むセグメンテーションを想定し、次にそのサブセットを考える。それらのサブセットの出現確率の和を最大化するように、それぞれのサブワードの出現確率を推定する。ただし、サブセットの出現確率の和の対数尤度がlog-sum形式のため、EMアルゴリズムを用いる。これによって推定される出現確率が低いサブワードを削除し、新たな出現確率を再びEMアルゴリズムで求める、という二重のループによって最適化する。
プログラムのコンパイルで抽象構文木を作るように、自然言語の解析では係り受け木(dependency tree)を作り、この作業を係り受け解析(dependency parsing)という。日本語の係り受け解析のライブラリとしてはCaboChaが有名である。
[!NOTE] 大規模言語モデルでは構文解析以降のステップをニューラルネットワークが隠蔽しているけれど、従来の手法はどのような意味を持ちうるの? Transformerの初期レイヤーが文法的な現象を捉え、高次レイヤーがより複雑な意味を学習するという研究があるそうなので、そうした構造を踏まえた検証やファインチューニングで活躍する…のかもしれない。
文章の意味を明示的に表すための構造として述語項構造があり、それを解析する技術として述語項構造解析がある。
文章ではなく、コーパス全体における単語間の意味も有向グラフを用いて表現される。次の表にその構造をまとめた。
構造 | 特徴 |
---|---|
意味ネットワーク | 概念をノード、関係を辺で表現する。関係には”is-a”や”part-of”などがある。 |
RDF | WIP |
知識グラフ | WIP |
文書の検索エンジンを考える。文書をキーワードの集合と見做して、検索キーワードを含む、あるいは含まないように条件にあった文書を探す考え方を、ブーリアンモデルという。それに対して、文書のキーワードに重み付けを行ったモデルをベクトル空間モデルという。文書のキーワードと検索キーワードの類似性が高い文書を探す。類似性の高さは、それぞれをベクトルと見立てた内積(ベクトルの各次元の積和)の大小を見るほかに、内積を2つのベクトルの長さで割って正規化したコサイン類似度 (cosine similarity)を用いることもある。
キーワードの重み付けの方法を考える。文書中に繰り返し「ピカチュウ」が登場したら、それはおそらくポケモンの文書だろう。つまり、ある文書に繰り返し登場するキーワードは、その文書における重みを高く設定したい。このような文書内での頻度を用いた重み付けの手法をTF(term frequency)法という。一方で、「私」「思う」といったキーワードは、文書を問わず繰り返し登場するから文書の特徴を表していない可能性が高い。そこで、その単語が文書に登場する頻度(DF (document frequency))の逆数を対数など[^note_idf]で調整して倍率とし、これをIDF(inverse document frequency)という。TFをIDFで重み付けする方法をTF-IDF法という。 [^note_idf]: 自然言語処理の基礎(奥村学)では$idf(t)=log(N/df(t))+1$と、調整のための定数項が含まれる
例えば、次の文書に対して、「犬」のTFとIDFを計算する。
文書 | 文書の全単語数 | 「犬」のTF | 「犬」のIDF | 「犬」のTF-IDF |
---|---|---|---|---|
犬のおまわりさん | 4 (犬,の,おまわり,さん) | 0.25 (1/4) | 1.585 (ln(2/3)) | 0.146 |
猫が営むラーメン屋さん | 5 (猫,が,営む,ラーメン屋,さん) | 0 (0/5) | 1.585 (ln(2/3)) | 0 |
犬と猫を飼う | 5 (犬,と,猫,を,飼う) | 0.2 (1/5) | 1.585 (ln(2/3)) | 0.117 |
[!NOTE] IDFの底は? 数学的には何でも構わない。通常2を使用するが、
sklearn
など実装によっては自然対数を用いることもあるという書き込みを見つけた。1出典の論文へのアクセス権がないため、それ以上の調査はできていない。
単語をベクトルで表したものを単語埋め込み(word embedding)ということがある。
CBoW: WIP
コサイン類似度
機械学習を参照。