自然言語処理におけるword2vecについて

概観

それが人工知能であろうとデータ科学であろうと、コアは数学的原理です。機械学習では、世界のすべてのものを数値に変換して、数学的な方法で問題を解決する方法が特に重要です。画像は通常、ピクセル値に基づいて入力されますが、テキストをどのように数値に処理する必要がありますか?

テキスト表現

ワードバッグモデル

最も基本的なテキスト表現モデルは、バッグオブワードモデルです。つまり、各ドキュメントが単語のバッグとして扱われ、各単語の出現順序は無視されます。各ドキュメントは長いベクトルとして表すことができ、ベクトルの各次元は単語を表し、この次元に対応する重みも記事内の単語の重要性を反映しています。重量の計算にはTF-IDFをよく使用します。

N-gramモデル

上記のBag-of-Wordsモデルには明らかな教育上の問題があります。「自然言語処理」というフレーズが3つの単語に分割されている場合、これらの3つの単語は別々に表示され、記事のセマンティクスで3つの単語が一緒に表示されることはまったく異なります。したがって、文書を分割する方法では、多くの単語間の関連情報が失われます。それから言語モデルが生まれました。n個の連続する単語(n <= N)で構成される句(N-gram)を単一の特徴としてベクトル表現に入れて、N-gramモデルを形成することもできます。ここで1つ追加する必要があります。実際のアプリケーションでは、単語に単語ステミング(単語ステミング)を実行して、同じ単語の複数の品詞の変化を統合します。

テーマモデル

これはまた、初期の自然言語処理の分野における古典的なモデルの1つであり、テキストライブラリから代表的なトピックを見つけるために使用されます(各トピックの単語の分布特性を取得するため)

単語の埋め込みとディープラーニングモデル

単語の埋め込みとは、単語をベクトル化するモデルの一般的な用語です。核となる考え方は、各単語を低次元空間(通常は約50〜300の次元)の密ベクトル(密ベクトル)にマッピングすることです。こんにちは。各ディメンションを暗黙のテーマと見なすこともできますが、テーマモデルのテーマほど直感的ではありません(テーマモデルには厳密な派生があります)。

Word2vec

2013年、GoogleはWord2vecモデルを提案しました。これは15年後に広く使用され、現在最も一般的に使用されている単語埋め込みモデルの1つです。これは、単語の連続バッグとスキップグラムという2つの構造を持つ浅いニューラルネットワークモデルです。もちろん、word2vecの後に多くの主流の単語埋め込みモデルがあります。これは、後のブログ投稿で紹介します。このブログでは、word2vecとその原則についてのみ質問します。

原理

ここに画像の説明を挿入CBOWとSkip-gramはどちらも浅いニューラルネットワークです。入力層の各単語は、一意のホットコードで表されます。1つは現在の単語を予測するために周囲の単語を使用することであり、もう1つは現在の単語を使用して周囲の単語を予測することです。浅いニューラルネットワークを通過した後、出力層もN次元ベクトルになり、最後に出力層ベクトルにsofmaxアクティベーション関数が適用されて、各単語の生成確率が計算されます。

word2vecとLDAの違いと接続

LDAは、ドキュメント内の単語の共起関係を使用してトピックごとに単語をクラスター化します。これは、「document-word」行列を分解して、「document-topic」と「topic-word」の2つの確率分布を取得すると理解できます。Word2vecは実際に「コンテキストワード」行列を学習します。この場合、コンテキストはその周囲のいくつかの単語で構成されているため、結果の単語ベクトルは、コンテキストの同時発生を組み込んだより多くの機能を表します。トピックモデルと単語の埋め込み方法の最大の違いは、モデル自体です。トピックモデルは、確率グラフモデルに基づく生成モデルです。その尤度関数は、陰関数を含むいくつかの条件付き確率乗算の形で記述できます。変数(つまり、トピック)を含みます。単語埋め込みモデルは通常ニューラルネットワークの形式で表現されますが、尤度関数はネットワークの出力で定義されます。単語の密なベクトル表現を取得するには、ネットワークの重みを学習する必要があります。

pytorchはword2vecを実装します

まず必要なパッケージをインポートします

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
import matplotlib.pyplot as plt
dtype = torch.FloatTensor

次に、単純なデータセットを作成し、データ全体の辞書を生成します。

sentences = [ "i like dog", "i like cat", "i like animal",
              "dog is animal", "cat is animal","dog like apple", "cat like fish",
              "dog like milk", "i like apple", "i hate apple",
              "i like movie", "i like book","i like music","cat hate dog", "cat like dog"]

word_sequence = " ".join(sentences).split()
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}

いくつかの基本的なパラメータを決定し、バッチなどを決定します。

batch_size = 20  #
embedding_size = 5 
voc_size = len(word_list)
def random_batch(data, size):
    random_inputs = []
    random_labels = []
    random_index = np.random.choice(range(len(data)), size, replace=False)
    for i in random_index:
        random_inputs.append(np.eye(voc_size)[data[i][0]]) 
        random_labels.append(data[i][1])  
    return random_inputs, random_labels

ウィンドウのskip_gramモデルを構築します。各単語について、前の単語と次の単語を特徴として使用するたびに。

skip_grams = []
for i in range(1, len(word_sequence) - 1):
    target = word_dict[word_sequence[i]]
    context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
    for w in context:
        skip_grams.append([target, w])

次に、モデルを作成します。ここで、浅いニューラルネットワークの重み行列と、重みを乗算して得られた行列を作成して出力行列を取得し、次元の単語数を出力する必要があります。

class Word2Vec(nn.Module):
    def __init__(self):
        super(Word2Vec, self).__init__()
        self.W = nn.Parameter(-2 * torch.rand(voc_size, embedding_size) + 1).type(dtype) 
        self.WT = nn.Parameter(-2 * torch.rand(embedding_size, voc_size) + 1).type(dtype) 
    def forward(self, X):
        # X : [batch_size, voc_size]
        hidden_layer = torch.matmul(X, self.W) # hidden_layer : [batch_size, embedding_size]
        output_layer = torch.matmul(hidden_layer, self.WT) # output_layer : [batch_size, voc_size]
        return output_layer

トレーニング中、入力データディメンションは[batch_size、voc_size]であり、ディメンションは非表示レイヤーの後で[batch_size、embedding_size]になり、行列を乗算した後の最終出力ディメンションは[batch_size、voc_size]のままです。
次に、モデルをインスタンス化し、損失、オプティマイザーなどを決定します。

model = Word2Vec()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(5000):
    input_batch, target_batch = random_batch(skip_grams, batch_size)
    input_batch = Variable(torch.Tensor(input_batch))
    target_batch = Variable(torch.LongTensor(target_batch))
    optimizer.zero_grad()
    output = model(input_batch)
    loss = criterion(output, target_batch)
    if (epoch + 1)%1000 == 0:
        print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
    loss.backward()
    optimizer.step()

最後に、図を描いて結果を確認します。

for i, label in enumerate(word_list):
    W, WT = model.parameters()
    x,y = float(W[i][0]), float(W[i][1])
    plt.scatter(x, y)
    plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
plt.show()

結果:
ここに画像の説明を挿入
ここでは例を示します。データが少ないため、モデルは完全に収束せず、最終結果はあまり良くありません。

Tensorflow2のWord2vec

では、どのようにword2vecをtensorflow2.0に実装するのですか?上記はpytorchの理論的な観点からword2vecを構築する方法を示しているため、原理の観点も同様です。ここでは主に、tf2でword2vecを使用する方法を示します。

import tensorflow as tf
docs =[ "i like dog", "i like cat", "i like animal",
              "dog is animal", "cat is animal","dog like apple", "cat like fish",
              "dog like milk", "i like apple", "i hate apple",
              "i like movie", "i like book","i like music","cat hate dog", "cat like dog"]
# 只考虑最常见的15个单词
max_words = 15
# 统一的序列化长度
# 截长补短 0填充,当然这里没有超过3的句子,默认是从前面填充0,也可以修改成从后面填充
max_len = 3
# 词嵌入维度
embedding_dim = 3
# 分词
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=max_words)
# fit_on_texts 获取训练文本的词表
tokenizer.fit_on_texts(docs)
# 字典索引
word_index = tokenizer.word_index
# 序列化
sequences = tokenizer.texts_to_sequences(docs)
# 统一序列长度
data = tf.keras.preprocessing.sequence.pad_sequences(sequences = sequences, maxlen= max_len)
# 添加Embedding层,传入字表长度,句子最大长度和嵌入维度
model = tf.keras.models.Sequential()
embedding_layer = tf.keras.layers.Embedding(input_dim=max_words, output_dim= embedding_dim, input_length=max_len)
model.add(embedding_layer)
model.compile('rmsprop', 'mse')
out = model.predict(data)
# 查看权重
layer = model.get_layer('embedding')
print(layer.get_weights())

最後に、出力する出力の次元は15 3 3です。15はこのウェーブの単語テーブルの長さ、3は各文の単語数、最後の3は埋め込み次元です。

GensimのWord2vec

実際、実際の使用プロセスでは、基本的にgensimパッケージを使用しています。自分で作成したプログラムは、必ずしもgensimほど優れているわけではありません。gensimは非常に単純です。組み込み効果のみを取得したい場合は、それを使用できます。gensimの使用方法は次のとおりです。

from gensim.models import Word2Vec
import re
docs = [ "i like dog", "i like cat", "i like animal",
              "dog is animal", "cat is animal","dog like apple", "cat like fish",
              "dog like milk", "i like apple", "i hate apple",
              "i like movie", "i like book","i like music","cat hate dog", "cat like dog"]
sentences = []
# 去标点符号
stop = '[’!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]+'
for doc in docs:
    doc = re.sub(stop, '', doc)
    sentences.append(doc.split())
# size嵌入的维度,window窗口大小,workers训练线程数
# 忽略单词出现频率小于min_count的单词
# sg=1使用Skip-Gram,否则使用CBOW
model = Word2Vec(sentences, size=5, window=1, min_count=1, workers=4, sg=1)

これで、単語ベクトルを非常に便利にトレーニングできます。もちろん、gensim関数はword2vecに限定されませんが、類似性計算、情報検索などのTF-IDF、LSA、LDAもnlpエントリのアーティファクトです。

元の記事を31件公開 20 件を賞賛 2095年を訪問

おすすめ

転載: blog.csdn.net/qq_34523665/article/details/105685941