Skip to main content

サブワード情報による単語ベクトルの強化

単語埋め込みの次のステップ。
Created on February 26|Last edited on February 16
このレポートは、Devjyoti Chakraborty, Aritra Roy Gosthipatyによる「Enriching Word Vectors with Sub-word Information」の翻訳です。



概要

ソース:
インテリジェンスは、判断能力、論理を理解する能力として定義されることがあります。これはほとんどのケースに絶対に当てはまりますが、コンピュータインテリジェンスを「教える」という問題が提起されがちです。
私は、知識ベースを使用してコンピューターを教えることは、疑似知能に該当すると思います。コンピューターは、知識のデータベースに設定したルールとパラダイムに常に基づいています。論理を推測して理解する方法を超えることは決してありません。見方を変えると、サーカスのライオンが食べ物と引き換えに燃えるようなフープを飛び越えるように教えられているのに勝るものはありませんが、それが十分に硬く見える場合は、周りに食べ物があります。
では、すべてを明示的に述べることなく、コンピューターの知能を教えるという質問にどのように答えればよいのでしょうか。そのために、プロセスを少し変更しましょう。知識ベースですべてを定義する代わりに、n次元空間の数値(ベクトル)を介してコンピューターにオブジェクトの意味を理解させるのはどうでしょうか。
ここで例を見てみましょう。コンピューターに電球の概念を理解させたいとします。2次元空間を取ります。ここで、一方の次元は光の強度を表し、もう一方の次元はオブジェクトのサイズを表します。このような簡単な設定で、電球を2次元空間の点として表すことができます。この空間は、コンピューターが電球だけでなく、チューブライトも理解できるようにします。オブジェクトのベクトル表現により、コンピューターはポイントを微調整し、さまざまなオブジェクトを理解できるようになりました。これは、コンピューターが物事を理解するためのより簡単な方法ですか?同意する場合は、AIの権威者であるGeoffrey Hinton氏と同じ意見を持つことになります。では、あなたは「知性はベクトルである」についてどういう意見を持っておられますか?
ベクトルによる単語の表現は、長い間議論されてきた概念です。Word2VecGloVeに関する以前の記事では、アイデアの核心に触れています。そこでは、アイデアの背後にある直感について話すだけでなく、Embeddingレイヤーを介してコードを記述します。この記事はフォローアップレポートとして役立ちます。ここでは、Piotr Bojanowski氏等による論文Enriching Word Vectors with Subword Informationを解読してみます。これはWord2Vecの直接の後継と見なされます。ここで著者は、より良いベクトル表現のために個々の単語の形態を検討しています。

直感

Word2Vecについて少し話しましょう。Word2Vecの提案はシンプルでありながら強力です。
単語の意味は、周囲の単語によって異なります。
これにより、Skip-GramとCBOWという2つの戦略が考案され、この概念を使用して単語をベクトルにエンコードしました。単語ベクトルに関する最も興味深い洞察は、十分に訓練された単語ベクトルの線形代数が直接論理に変換されることです。非常に有名な例は、King-Man+Woman=Queenの例です。熱心な読者は、Word2VecGloVeの記事に進んで、トピックをよりよく理解することができます。
ベクトル表現と関連付け(単語を囲む)の助けを借りて、word2vecの独創的なアイデアが導入され、N次元の空間でベクトルを介して単語の意味を機械に教えることができました。しかし、私たちは各単語をベクトルとして教えているので、単語の背後にある形態と語源を絶対に無視します。これは、単語がどのように生まれたのか、単語のサブワードを別の単語にリンクする方法を示す情報の重要な部分を無視することにつながります。
知識に富んだエッセイを書いたり、複雑なアイデアや感情を表現しようとする場合、まれで複雑な言葉が使用されます。単語連想ルート(Word2Vec、GloVeファミリー)を介してモデルをトレーニングしようとすると、そのような場合に失敗する可能性があります。一方、そのようなまれな単語は、他の単語の一部または語源的に解読可能な特性によって構築されるため、形態によって解読される可能性があります。サンスクリット語やその現代の派生インド言語のようないくつかの言語は、いくつかのルート音節から体系的に派生できるため、そのようなトレーニングに非常に適しています。
形態を理解する
論文からの抜粋:
たとえば、フランス語またはスペイン語では、ほとんどの動詞には40を超える異なる屈折形がありますが、フィンランド語には15の名詞の場合があります。これらの言語には、トレーニングコーパスではめったに発生しない(またはまったく発生しない)多くの単語形式が含まれているため、適切な単語表現を学習することは困難です。多くの造語は規則に従っているため、文字レベルの情報を使用することで、形態学的に豊富な言語のベクトル表現を改善することができます。
この論文の著者は、Skip-Gramモデルの拡張を提案しています。スキップグラムモデルの背後にある主なアイデアは、単一の中心/ターゲット単語が与えられた場合に複数のコンテキスト単語を予測することでした。
For example, consider the sentences:
  1. 「赤い色が飛び出します」
  2. 「緑色は何ですか?」
  3. 「黄色の色合いがあなたに合っています」
上記の文でモデルをトレーニングすると、最終的に「色」という単語が「赤」、「緑」、「黄色」という単語に関連付けられることがわかります。単語の連想を通して単語「色」の意味を見つけるという基本的な目的は確かに達成されます。
一方、エンティティとしての言語には、はるかに深く定義された意味があります。世界に��7000の異なる人間の言語があり、それぞれが独特の方言と定義された語彙を持っていると推定されています。特定の単語がどのようにして特定の言語になったかを理解することは、その単語を定義されたサブ単語に分解することを意味します。ただし、タスクをword2vecモデルに委任すると、言語の微妙な美しさを無視することを選択することになります。次の例を見てください。
単語の形態の例
「読めない」という単語は、その構成要素であるサブ単語に簡単に分解できるため、その意味を定義できます。この論文では、ターゲット/センターワードをその構成サブワードに置き換えることにより、この情報をスキップグラムモデルに含めたいと考えています。このようにして、「unreadable」に属するサブワードを「unstoppable」などの別のワードに関連付けることもできます。2つの単語の意味は異なりますが、共通のサブ単語があります。これは、彼らの形成が同様の考えを持っていたことを意味します。このアプローチが役立つもう1つの方法は、単語の意味が2つの要因にどのように依存するかです。つまり、単語の関連付けと形態学。これは、出現がなくても、まれにしか出現しない単語を解読できることを意味します。

目的

この論文でPiotr Bojanowski氏等によって提案された方法は、Skip-Gramモデルを直接拡張したものです。サブワードスペースに飛び込む前に、Skip-Gramsについて少し修正しましょう。
サイズWWの単語語彙が与えられ、単語はそのインデックス w{1,...,W}w\in \{1,...,W\} によって識別されます。目標は、各単語wのベクトル表現を学習することです。単語のシーケンスw1、...、wTとして表される大規模なトレーニングコーパスが与えられた場合、スキップグラムモデルの目的は、次の対数尤度を最大化することです。
J(θ)=t=1TcCtlogp(wcwt)J(\theta)=\sum ^{T}_{t=1}\sum _{c\in C_{t}}\log p( w_{c} |w_{t})

ここで、コンテキストCtC_t は、ターゲット単語 wtw_tを囲む単語のインデックスのセットです。
対数尤度関数のパラメーター化について、具体的には「対数尤度を最大化するために何を調整するか」という疑問が生じます。これに対する答えは、確率関数にあります。
p(wcwt)=exp(s(wt,wc))j=1Wexp(s(wt,j))p( w_{c} |w_{t}) =\frac{\exp( s( w_{t} ,w_{c}))}{\sum ^{W}_{j=1}\exp( s( w_{t} ,j))}

確率関数は確かにソフトマックス関数です。ここで、 s(x,y)s(x,y) は、ベクトルxとyの間の類似性を計算するスコアリング関数と見なされます。対数尤度を最大化する間に微調整されるパラメーターは、単語のベクトル表現です。目的関数は、単語のより良いベクトル表現で損失が減少するようなものです。
ソフトマックスの実装により、より高い確率分布を実現し、1つのコンテキストワードのみに焦点を当てることができます。
ただし、このようなモデルは、単語ord wcw_c が与えられた場合、1つのコンテキスト単語のみを予測することを意味するため、このケースには適合しません。
これにより、確率関数のフレーミングが異なります。現在、文脈語を予測する問題は、二項分類タスクであると見なされていました。文脈語の有無を独自に予測することが課題になります。写真のネガティブサンプリングでは、このバイナリ分類のタスクは、ポジティブとネガティブの2種類のコンテキストワードで実行されます。ポジティブコンテキストワードは、ターゲットワードと同じウィンドウにあるものであり、ネガティブコンテキストワードは、ウィンドウ内のワード以外のものです。

サブワードスペース

スキップグラムモデルは、単語ごとに異なるベクトル表現を使用することにより、単語の内部構造を無視します。
この問題に対処するために、著者は別のスコアリング関数を提案しています。スコアリング関数を深く掘り下げるには、彼らが提案している設定も理解する必要があります。彼らは、各単語wを文字n-gramのバッグと見なします。また、他の文字シーケンスの接頭辞と接尾辞の境界を考慮して、各単語の最初と最後に特別な境界記号<<と>>を追加します。また、n-gramのセットに単語w自体を追加します。コードスニペットを通して次のことを理解しましょう。
>>>word = "where"
>>>word = f"<{word}>"
>>>n_grams = [word[i:i+3] for i in range(len(word)-2)]+[word]
n_grams
>>>n_grams
['<wh', 'whe', 'her', 'ere', 're>', '<where>']
ここで、スコアリング関数 s(wt,wc)s( w_{t} , w_c) は、パラメーターとして2つのベクトル、つまりターゲットとコンテキストベクトルを取ります。フレーム内のサブワードを使用して、スコアリング関数が変更され、ターゲットワードのサブワードのみが含まれるようになりました。これは、スコアがコンテキストベクトルとすべてのターゲットn-gramベクトル間の内積として計算されることを意味します。
サイズGのnグラムの辞書が与えられたとします。単語wが与えられた場合、 wwに現れるnグラムのセットをG Gw{1,...,G}G_w \sub \{1,...,G\} で表します。ベクトル表現 zgz_g を各n-gramgに関連付けます。単語は、そのnグラムのベクトル表現の合計で表されます。したがって、スコアリング関数を取得します。
s(w, c)=gGwzgTvcs( w,\ c) = \sum\limits _{g\in G_{w}} z^{T}_{g} v_{c}

ここで注意すべき最も重要なことは、ターゲット単語のベクトル表現をそのnグラムのすべてのベクトルの合計と見なすことです。
ここで、zgはターゲット単語に対応するn-gramのそれぞれを指します。たとえば、ターゲット単語が'<where>'の場合;zgは、「<wh」、「whe」、「her」、「ere」、「re>」、および「<where>」に対応するベクトルになります。覚えておくべき重要なことは、ある単語に現れるサブ単語が別の単語にも現れる可能性があるということです。これが相互情報共有が行われる方法です。この単純なモデルにより、アーキテクチャは単語間でサブ単語に関する情報を共有できます。across words.

コード

このセクションでは、論文のTensorFlow実装について説明します。このコードは、公式のTensorFlowWord2Vecガイドの影響を強く受けています。
コードの最も重要な部分はデータの準備です。取得するデータは、キャリッジリターンで区切られた多くの文を含むテキストファイルです。
# Create a `tf.data` with all the non-negative sentences
>>> text_ds = tf.data.TextLineDataset(path_to_file).filter(lambda x: tf.cast(tf.strings.length(x), bool))

>>> for text in text_ds.take(5):
print(text)

tf.Tensor(b'First Citizen:', shape=(), dtype=string)
tf.Tensor(b'Before we proceed any further, hear me speak.', shape=(), dtype=string)
tf.Tensor(b'All:', shape=(), dtype=string)
tf.Tensor(b'Speak, speak.', shape=(), dtype=string)
tf.Tensor(b'First Citizen:', shape=(), dtype=string)
次に、各文をトークン化して標準化します。
# We create a custom standardization function to lowercase the text and
# remove punctuation.
def custom_standardization(input_data):
lowercase = tf.strings.lower(input_data)
return tf.strings.regex_replace(lowercase,
'[%s]' % re.escape(string.punctuation), '')

# Define the vocabulary size and number of words in a sequence.
vocab_size = 4096
sequence_length = 10

# Use the text vectorization layer to normalize, split, and map strings to
# integers. Set output_sequence_length length to pad all samples to same length.
vectorize_layer = TextVectorization(
standardize=custom_standardization,
max_tokens=vocab_size,
output_mode='int',
output_sequence_length=sequence_length)

# build the vocab
vectorize_layer.adapt(text_ds.batch(1024))
トークンを取得したら、学習用の監視対象セットアップに役立つセットアップを作成する必要があります。
出典: Word2Vec
トレーニングプロセスでは、tf.random.log_uniform_candidate_samplerを使用せず、代わりにプロセスをカスタマイズして、トレーニングプロセスにより良いネガティブサンプルを含めます。議論に従うStackOverFlowスレッド
サブワードの場合、セットアップが少し変更されます。図に示すように、初期位置にターゲットワードインデックスがありません。代わりに、ターゲット単語のサブワードのインデックスがあります。
バッチサイズが1000の場合、データセットの形状は次のようになります。
<PrefetchDataset shapes: (((1000, None), (1000, 5, 1)), (1000, 5)), types: ((tf.int32, tf.int64), tf.int64)>
  • (1000, None) - 1000 ngrams.
  • (1000, 5, 1) - 1000 5-pieces context words.
  • (1000, 5) - 1000 5-piece labels.
そのモデルはかなり単純です
class Word2Vec(Model):
def __init__(self, subword_vocab_size, vocab_size, embedding_dim):
super(Word2Vec, self).__init__()
self.target_embedding = Embedding(subword_vocab_size+1,
embedding_dim,
input_length=None,
name="w2v_embedding",)
self.context_embedding = Embedding(vocab_size+1,
embedding_dim,
input_length=num_ns+1)
self.dots = Dot(axes=(3,1))
self.flatten = Flatten()

def call(self, pair):
target, context = pair
we = tf.math.reduce_sum(self.target_embedding(target),axis=1)
ce = self.context_embedding(context)
dots = self.dots([ce, we])
return self.flatten(dots)
2つの埋め込みレイヤーを定義します。次に、ドット積を実行することにより、コンテキストとターゲットの埋め込みがスコアリングされます。次に、このスコアが評価され、損失が逆伝播されて埋め込みが微調整されます。

結果

モデルの損失と精度をここに示します。ここでは、両方のメトリックがうまく機能しているようです。

Run set
0


埋め込みプロジェクション

埋め込みを見る別の方法は、プロジェクターでそれらを表示することです。TensorFlowには、それを視覚化するための優れたツールがあります。埋め込み用のvector.tsvとmetadat.tsvを作成し、それをプロジェクターにロードすることができます。プロジェクターは、PCAのような次元削減技術を適用して、データを視覚的なベクトル空間に合体させますが、それでも重要な情報を保持することができます。すばやくアクセスできるように、tsvファイルをアーティファクトとしてwandbプロジェクトにアップロードしました。アーティファクトをダウンロードしてご利用ください。また、ファイルをGitHubリポジトリにアップロードしました。

コンテキスト

損失が大幅に安定した後、コンテキストの埋め込みがどのように形成されたかを確認することにしました。探索的な単語として「for」を選択します。「the」「a」「of」「with」などの単語が最も近いことが示されていることに注目してください。これは、私たちのモデルが、主要な文法的意味を持つ単語をグループ化する方法を学習したことを意味します。
検索された単語:「for」

次に、もう少しまれにしか発生しない単語「secrets」を選択します。モデルが「safeguard」、「Signal」、「strangely」などの単語に追いついていることがわかります。私たちのデータはシェイクスピアの一節にすぎないことを念頭に置いて、モデルは比較的素晴らしい仕事をしました!
検索された単語:「secrets」

目標

ターゲットの埋め込みには、特定のデータから考案されたすべてのサブワードが含まれていました。まず、「<th」というフレーズを検索します。サブワードを使用してさまざまな単語をリンクすることが私たちの主な目的であったことを要約します。「the」「they」「them」「this」「thou」、「thy」などの単語が「<th」というフレーズに最も近いことがわかるので、私たちはかなりの程度まで意図を達成しました。
検索された単語:「<th」

「the」という単語を検索すると、同様の結果が表示されます。同様のサブワードを持つ単語は、最近傍として表示されています。モデルを通じて単語の形態を捉えたと結論付けることができます。より意味的な意味を捉えるために、さまざまなサイズのn-gramを試してみることができます。
検索された単語:「the」

結論

この論文で描かれている作業は、word2vecの後継として高く評価されており、fastTextの基盤の3つの前提条件の1つになりました(効率的な単語表現を生成するために多くの概念を利用するので、自然言語処理で行われる作業のベンチマークであると考えられる)。
私たちの実験は、この論文が単純な方法を利用して単語表現を学習し、その過程でサブ単語情報も学習することを示しています。スキップグラム法の理想的な後継であるこのモデルは、他のレガシーモデルよりもはるかに高速にトレーニングし、サブワード情報や形態素解析なしで認識されるベースラインを上回ります。
結論として、サブワード情報を扱うことで、コンピューターが言語の美しさと力を最大限に活用できるようにするための一歩を踏み出すことができます。

著者:
名前ツイッターGitHub
Devjyoti Chakrobarty@Cr0wley_zz@cr0wley-zz
Aritra Roy Gosthipaty@ariG23498@ariG23498

Iterate on AI agents and models faster. Try Weights & Biases today.