テキストのベクトル表現

自然言語処理

自然言語処理(NLP)におけるテキストのベクトル表現は、テキストデータを数値ベクトルに変換する方法です。これにより、機械学習モデルがテキストデータを理解し、処理できるようになります。このメモではN-gramベクトルとシーケンスベクトルについて解説しています。

N-gramベクトル

N-gramベクトルは、テキストをベクトルで表現するための手法の一つです。N-gramとは、連続するn個の単語や文字のまとまりを指します。例えば、n=1の場合はユニグラム、n=2の場合はバイグラム、n=3の場合はトライグラムと呼ばれます。

N-gramの基本

  • ユニグラム (n=1): 各単語を個別に扱います。
    • 例: 「私は自然言語処理が好きです」→「私」「は」「自然言語処理」「が」「好き」「です」
  • バイグラム (n=2): 連続する2単語をペアにします。
    • 例: 「私は自然言語処理が好きです」→「私は」「は自然言語処理」「自然言語処理が」「が好き」「好きです」
  • トライグラム (n=3): 連続する3単語をグループにします。
    • 例: 「私は自然言語処理が好きです」→「私は自然言語処理」「自然言語処理が」「言語処理が好き」「処理が好きです」

N-gramベクトルの利点

N-gramベクトルを使用することで、テキストの文脈や単語の繋がりを捉えやすくなります。特にバイグラムやトライグラムを用いることで、単語同士の関係性をより詳細にモデル化できます。

実装例

Pythonを使ってN-gramを実装する方法を簡単に紹介します。

from nltk import ngrams
tokens =  ["私", "は", "自然言語", "処理", "が", "好き", "です"]

# バイグラムを生成
bigrams = list(ngrams(tokens, 2))
print(bigrams)

このコードでは、NLTKライブラリを使用してテキストをバイグラムに変換しています。結果は以下のようになります。

[('私', 'は'), ('は', '自然言語'), ('自然言語', '処理'), ('処理', 'が'), ('が', '好き'), ('好き', 'です')]

N-gramベクトルは、自然言語処理の様々なタスクで利用され、特にテキスト分類や機械翻訳などで効果を発揮します。そしてこれをより機会が扱いやすいようにBag-of-Ngrams(BoW)という形式でベクトル表現にします。

Bag-of-Ngrams(BoW)形式でベクトル表現

単語や文字のまとまりを作成したところで、これをベクトルに表現しなおし、より機会が扱いやすい形にします。手法は主に下記の3つです。

  • One-hotエンコーディング: 各単語をユニークなベクトルで表現。
  • Countエンコーディング: 各単語の出現回数をカウント。
  • TF-IDF: 単語の重要度を評価し、頻出単語には低い重み、希少単語には高い重みを与える。

1. One-hotエンコーディング

One-hotエンコーディングは、各単語をベクトルで表現する方法です。各単語に対してユニークなインデックスを割り当て、そのインデックスに対応する位置だけが1で、他はすべて0になるようにします。

from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd

t = Tokenizer(wakati=True)
vectorizer = CountVectorizer(tokenizer=t.tokenize, binary=True)
docs = ["一番目のサンプルテキストです","二番目のサンプルテキストです","これは三番目のサンプルテキストですのて3番目です"]
bow = vectorizer.fit_transform(docs)

vocab = vectorizer.get_feature_names_out()
print(vocab)
pd.DataFrame(bow.toarray(), columns=vocab)

2. Countエンコーディング

Countエンコーディングは、各単語の出現回数をカウントしてベクトル化する方法です。BoWモデルの基本的な形態です。

from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd

t = Tokenizer(wakati=True)
vectorizer = CountVectorizer(tokenizer=t.tokenize, binary=False)
docs = ["一番目のサンプルテキストです","二番目のサンプルテキストです","これは三番目のサンプルテキストですのて3番目です"]
bow = vectorizer.fit_transform(docs)

vocab = vectorizer.get_feature_names_out()
print(vocab)
pd.DataFrame(bow.toarray(), columns=vocab)

binary=Falseを選択したことで、語彙が出てくる回数に合わせて、1が2になったり、3になったりと、出現回数をカウントするようになります。

3. TF-IDF (Term Frequency-Inverse Document Frequency)

TF-IDFは、単語の重要度を評価するための手法です。頻繁に出現する単語には低い重みを、希少な単語には高い重みを与えます。

from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

t = Tokenizer(wakati=True)
vectorizer = TfidfVectorizer(tokenizer=t.tokenize)
docs = ["一番目のサンプルテキストです","二番目のサンプルテキストです","これは三番目のサンプルテキストですのて3番目です"]
bow = vectorizer.fit_transform(docs)

vocab = vectorizer.get_feature_names_out()
print(vocab)
pd.DataFrame(bow.toarray(), columns=vocab)

TF-IDFの基本的な考え方

  1. Term Frequency (TF):
    • これは、ある単語が文章の中でどれくらい頻繁に出てくるかを示します。
    • 例えば、「猫が好きです」という文章で「猫」が2回出てきたら、TFは2です。
  2. Inverse Document Frequency (IDF):
    • これは、単語がどれくらい希少かを示します。
    • たくさんの文章の中で、あまり出てこない単語ほど高い値になります。
    • 例えば、「猫」は多くの文章に出てくるかもしれませんが、「ユニコーン」はあまり出てこないので、IDFは「ユニコーン」の方が高くなります。

TF-IDFの計算

TFとIDFを掛け合わせることで、単語の重要度を計算します。

  • TF-IDF = TF × IDF

具体例

例えば、以下の2つの文章があるとします。

  1. 「私は猫が好きです」
  2. 「あなたは犬が好きです」

ここで、「猫」と「犬」のTF-IDFを計算してみましょう。

  1. TFの計算:
    • 「猫」のTFは1(1回出現)
    • 「犬」のTFも1(1回出現)
  2. IDFの計算:
    • 「猫」は1つの文章に出現
    • 「犬」も1つの文章に出現
    • しかし、もし「猫」が他の多くの文章にも出現するなら、IDFは低くなります。
  3. TF-IDFの計算:
    • 「猫」のTF-IDF = 1 × IDF(「猫」のIDF)
    • 「犬」のTF-IDF = 1 × IDF(「犬」のIDF)

このようにして、TF-IDFを使うと、文章中の重要な単語を見つけることができます。頻繁に出現する単語(例えば「は」や「です」など)は重要度が低くなり、希少な単語が重要度が高くなります。

今回の感想

今回テキストをベクトルで表現する際に教科書では英語の文章を前提としていたため苦労しました。今回の学習からテキストを単語に分割し、それをベクトルに変換することまでできたので次の学習も頑張りたいと思います。

※このシリーズは下記の書籍を参考に書いています。

コメント

タイトルとURLをコピーしました