12,782 測定値
12,782 測定値

Embeddings 101: Unlocking Semantic Relationships in Text(テキスト内のセマンティックな関係を解除する)

Ritesh Modi14m2025/03/27
Read on Terminal Reader
Read this story w/o Javascript

長すぎる; 読むには

Embeddings は、機械が言語を理解する方法の限界に対処します。それらは単に新しい技術ではなく、言語理解の根本的な限界に対処します。
featured image - Embeddings 101: Unlocking Semantic Relationships in Text(テキスト内のセマンティックな関係を解除する)
Ritesh Modi HackerNoon profile picture
0-item
1-item


私は何年も前にテキストデータで作業を始めたとき、埋め込みのコンセプト全体が不必要に複雑に見えました. 私は私のバッグ・オブ・ワード・アプローチとシンプルなTF-IDFベクターで快適でした. I believed they were straightforward, easy to understand, and effectively accomplished the task at hand.


私は感情分析プロジェクトで課題に直面するまで、インベーディングを真剣に検討しませんでした. 私は製品レビューで作業していて、私の伝統的なモデルはサルカズムや色合いのある言語でレビューを誤って分類し続けました. 問題は明らかになりました:私のモデルは「この製品は病気です」が実際にはポジティブであるか、「期待通りに働いた」が文脈に応じて中立またはネガティブであるかを理解していませんでした.


それは、組み込みが実際に何を解決するかを発見したときです。それらは単に素晴らしい新しいテクニックではなく、機械が言語を理解する方法の根本的な限界に取り組んでいます。


The Old Days: Life Before Embeddings

『The Old Days: Life Before Embeddings』

これらの方法やアプローチの詳細に触れずに組み込む前にテキスト表示を使用する歴史を理解しましょう。

One-Hot Encoding

それは、単語の中でその単語に匹敵する位置にある単一の「1」を除くすべてのゼロを含む稀なベクターとして各単語を表し、それぞれの単語が独自の次元を獲得した巨大で稀なベクターとして単語を表した。 あなたの単語が10万単語(謙虚なもの)を持っていた場合、各単語ベクターは99999ゼロと1個1を持っていた。 これらの表現は私たちにまったく意味がないことを教えてくれました。 単語「優れた」と「素晴らしい」は、数学的に「優れた」と「恐ろしい」と同じように異なっていた - 明らかなセマンティックな関係を完全に欠いている。


「猫」 → [1, 0, 0, 0, ..., 0] (語彙の第 5432 号) 「犬」 → [0, 1, 0, 0, ..., 0] (語彙の第 8921 号)


制限

  • Dimensionality explosion: Vectors had as many dimensions as vocabulary size (often 100,000+)
  • 「猫」と「猫」は「猫」と「飛行機」と同じくらい異なっていた。
  • 計算効率の低下:これらの希少なマトリックスを倍増することは、非常にリソース密集でした。
  • 一般化なし:システムは元の語彙以外の単語を理解できませんでした。

Bag-of-Words Approach

それは文書の単語の発生を数え、時にはそれらの重要性によって重視され、文書の単語を単語のコレクションとして扱い、完全に単語の順序を捨てました。


ドキュメント: 「猫はマットの上に座った」 BoW: {"the": 2, "cat": 1, "sat": 1, "on": 1, "mat": 1}

制限:

  • 「犬は人を噛む」と「人間は犬を噛む」は、同じ表現でした。
  • Sparse high-dimensional vectors: Still required vocabulary-sized vectors. スパレスの高次元ベクター:まだ必要
  • No semantic understanding: Synonyms were represented as completely different features. シノニマは完全に異なる特性として表されていた。
  • 文脈的意義がない:各単語は文脈に関係なく固定的な表現を持っていた。

N-grams

いくつかの単語の順序をキャプチャするために、我々はn-grams(n連続単語の順序)を使用し始めた。


With unigrams (single words), you might have a vocabulary of 100,000. With bigrams (word pairs), suddenly you're looking at potential millions of features. With trigrams? Billions, theoretically. Even with aggressive pruning, the dimensionality became unmanageable.

Limitations:

制限:
  • Combinatorial explosion: The number of possible n-grams grows exponentially. 可能なnグラムの数は膨大に増加する。
  • Data sparsity: Most possible n-grams never appear in training data. ほとんどの可能なn-gramsはトレーニングデータに表示されません。
  • 限定コンテキストウィンドウ:小さなウィンドウ内でのみキャプチャされた関係(通常2〜5単語)

TF-IDF (Term Frequency-Inverse Document Frequency)

TF-IDFは、単語が特定の文書にどれほど重要であるかを基に、単語を重ねることにより、物事を改善しましたが、それでも「素晴らしい」と「素晴らしい」は全く関係のない用語として扱われました。

Limitations:

制限:

セマンティックな意味がない:その使用の重要性を決定する単語の数と頻度です。

The Embedding Revolution: What Changed?

インベーディング革命:何が変わったのか?

埋め込みへの移行は、単に段階的な改善ではなく、私たちが言語を表現する方法におけるパラダイムの変化でした。

Meaning Through Context

埋め込みの背後にある基本的な洞察は、誤解的に単純である:類似した文脈に現れる単語は、おそらく類似した意味を持っている. 「犬」と「猫」が同じ種類の単語(「ペット」、「食べ物」、「フール」)の周りに現れるのを見ると、彼らは恐らく意味的に関連している。


Word2Vecのような初期の埋め込みモデルは、神経ネットワークを訓練して次のことを予測した。


  • 周囲の文脈に基づく単語(Continuous Bag of Words)
  • 単語に基づく周囲の文脈(Skip-gram)


これらのモデルの隠された層重量は、我々の単語ベクターとなり、ベクター空間の地理的性質における語学的関係を暗号化した。


僕が最初に単語ベクターを構成し、「王」=「男」=「女」=「女王」を観たとき、僕は革命的なものにいたことを知っていた。


Word2VecやGloVeのような初期のモデルは、文脈に関係なく、各単語に単一のベクターを与えました。


"I need to bank the money" vs. "I'll meet you by the river bank"


BERTやGPTのようなモデルは、その周囲の文脈に応じて同じ単語の異なる埋め込みを生成することによってこの問題を解決しました。


そこで、まず、埋め込みが何であるか、どのようにNLPを変革し、以前のアプローチの限界に対処したかを理解しましょう。

What Are Embeddings?

Embeddingsとは?

Embeddings are numerical representations of data (text, images, audio, etc.) in a continuous vector space. For text, embeddings capture semantic relationships between words or documents, allowing machines to understand meaning in a way that is mathematically processable. テキストでは、 embeddingsは単語や文書の間のセマンティックな関係をキャプチャし、マシンが意味を数学的に処理可能な方法で理解することを可能にします。

Key Concepts:

  • ベクトル: 多次元空間の点を表す数列
  • Dimensions: The number of values in each vector (e.g., 768-dim, 1024-dim)
  • Vector Space: Embeddings が存在する数学的空間
  • Semantic Similarity: Measured by distance or angle between vectors (nearer = more similar)

What Do Dimensions Represent?

埋め込みベクターの各次元は、データの学習された特徴または側面を表します。古典的な特徴エンジニアリングとは異なり、現代の埋め込みモデルでは、人間がそれぞれの次元の意味を定義している。


  • 訓練中に次元が抽象的な「概念」を表すように現れる
  • 個々の次元はしばしば、特定の人間解釈可能な意味を欠く。
  • しかし、完全なベクターは、セマンティックな情報を総合的にキャプチャします。
  • いくつかの次元は、感情、形式性、トピック、またはシンタクスに対応するかもしれませんが、ほとんどは機能の複雑な組み合わせを表します。

Why We Need Embeddings

コンピュータは基本的に単語ではなく数字で動作します. 言語を処理するとき、私たちはテキストを次のような数字表現に変換する必要があります。


  1. Capture semantic relationships - similar concepts should have similar representations. 類似の概念は類似の表現を持つべきである。
  2. 文脈的意義を維持する - 同じ単語は異なる文脈で異なることを意味することができる
  3. 数学操作を有効にする - 類似点を見つけることや類似点を実行するなど
  4. スケールで効率的に作業 - コンピュータ爆発なしで大量のテキストを処理


Embeddings は、単語、フレーズ、または文書を密集したベクターとして、セマンティックな関係が地理的関係として保存される継続的な空間で表すことで、これらの問題を解決します。

Embeddingsの基礎

デンス・ベクター代表

数千または数百万の次元を持つ希少なベクターの代わりに、埋め込みは数百の密度を使用し、それぞれの次元が意味に貢献します。


"cat" → [0.2, -0.4, 0.1, -0.8, ..., 0.3] (300 dimensions)

"kitten" → [0.19, -0.38, 0.15, -0.75, ..., 0.29] (similar to "cat")


これにより、大きさの計算順序がより効率的になり、より豊富なセマンティックな表現が可能になります。

配布セマンティクス

Embeddings are built on the principle that "you shall know a word by the company it keeps" (J.R. Firth). By analyzing what words appear in similar contexts, embeddings capture semantic relationships automatically.


たとえば、「王様」と「女王」は類似した文脈を持っているので、まったく同じ位置に現れないにもかかわらず、類似した埋め込みがあります。

数学的財産

埋め込みスペースには驚くべき数学的性質があります:


vector("king") - vector("man") + vector("woman") ≈ vector("queen")


これにより、ベクトル空間内で直接アナログ推論とセマンティック操作が可能になります。

転送学習

事前訓練された埋め込みは、特定のタスクに細かく調整できる一般的な言語知識をキャプチャし、新しいアプリケーションに必要なデータを劇的に削減します。

文脈理解

現代の文脈的埋め込み(BERT、GPTなど)は、文脈に基づいて同じ単語を異なる形で表しています。


"I'll deposit money in the bank" → "bank" relates to finance

"I'll sit by the river bank" → "bank" relates to geography


埋め込みの歴史と理解に関するすべての知識を持って、それらを使用する時が来ました。

LLM/SLM モデルを使用して組み込みを生成する

さまざまな研究チームは、複数の言語やドメインをカバーするさまざまなデータセットで訓練されたインベーディングモデルを開発しました。この多様性は、非常に異なる語彙とセマンティック理解能力を持つモデルを生み出しています。例えば、主に英語の科学文献で訓練されたモデルは、多言語のソーシャルメディアコンテンツで訓練されたものとは異なり、技術概念をコードします。


組み込みの実践的実装は、Hugging Face の SentenceTransformer パッケージのようなライブラリによって大幅に簡素化されており、さまざまな組み込みモデルで作業するための包括的な SDK を提供しています。同様に、OpenAI の SDK は、多くのベンチマークで印象的なパフォーマンスを示した組み込みモデルへの直接のアクセスを提供しています。


モデルは、この記事の目的のために、入力として文をとり、それらに対応するベクトル表示を返すブラックボックスとして扱われるべきです。

SentenceTransformers Library for Embeddings を使用する

SentenceTransformer を使用して埋め込みを生成する最も簡単な方法:

from sentence_transformers import SentenceTransformer

# Load a pre-trained model
model = SentenceTransformer('all-MiniLM-L6-v2')  # 384 dimensions

# Generate embeddings
texts = ["This is an example sentence", "Each sentence becomes a vector"]

embeddings = model.encode(texts)

print(f"Shape: {embeddings.shape}")  # (2, 384)

max_seq_length = model.tokenizer.model_max_length

print(max_seq_length) # 256


​​HuggingFaceから入手可能な「all-MiniLM-L6-v2」モデルには384の次元があります。これは、特定の単語や文の384の特徴や色合いをキャプチャできることを意味します。このモデルのシーケンス長は256トークンです。 文は埋め込むプロセス中にトークニザーによって単語や単語に分割されます。 文のためのトークンの数は、一般的に文の単語の数よりも25%から40%増えます。


順序の長さは、モデルが与えられた入力として処理できるトークンの数を表します. 少なくとも 256 の長さを作るようにパッドアップされ、それ以上のものは捨てられます. これには影響があり、我々は別の投稿でそれらを論じます.


SentenceTransformer クラスのコードメソッドは、モデルを使用する PyTorch 推定モードのウラッパーです。


from sentence_transformers import SentenceTransformer
import torch

# Load the model directly with SentenceTransformer
model = SentenceTransformer("sentence-transformers/msmarco-distilbert-base-tas-b")

# Input text
texts = ["This is an example sentence", "Each sentence becomes a vector"]

# Get embedding directly
with torch.no_grad():
    embedding = model.encode(texts, convert_to_tensor=True)
print(embedding)


ここでは、torch.no_grad 関数は、後ろの拡散中に階段が計算されないことを保証します。


PyTorch を使用して埋め込みを生成するもう一つのより一般的な方法:


# Load the model
model = AutoModel.from_pretrained("sentence-transformers/msmarco-distilbert-base-tas-b")

# Get the tokenizer
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/msmarco-distilbert-base-tas-b")

# Tokenize input
text = ["This is an example sentence"]
encoded_input = tokenizer(text, padding=True, truncation=True, return_tensors='pt')

# Get embedding of the [CLS] token
with torch.no_grad():
    outputs = model(**encoded_input, return_dict=True)
    cls_embedding = outputs.last_hidden_state[:, 0]
print(cls_embedding)


このコードと以前のコードのスナップットの違いは、コード機能がトークネイザーとモデルを明示的に使用することによって置き換えられたことです。


もう一つの違いは、私たちは outputs.last_hidden_state[:、0] を使用して CLS トークンに関連するベクターを取得しているということです. この CLS 特別なトークンは、各文の開始時に各文に追加され、全体の文に関する蓄積された情報を含んでいます. コード方法は私たちのために自動的にこれを行う。


CLSトークンを追加するこのアプローチは、特定のトランスフォーマーベースのアーキテクチャにのみ適用可能であり、これはBERTとその変数とエンコーダーのみベースのトランスフォーマーを含みます。


Best for:分類および順序レベルの予測タスク


Why they work:BERT スタイルのモデルの [CLS] トークンは、プレトレーニング中にセクション全体から情報を集計するために特別に訓練されています。


When to choose:

  • BERT、ROBERTa、または類似のモデルを使用する場合
  • セクション全体を表す単一のベクターが必要な場合
  • ダウンストリームのタスクが全体テキストのプロパティを予測することを含む場合


使用される CLS メソッドは、句の埋め込みをキャプチャするためのメソッドの 1 つに過ぎません。

Mean Pooling

すべてのトークン埋め込みの平均値を取ることは、多くのタスクで驚くほど効果的です。


Best for:Semantic similarity, retrieval, and general-purpose representations. セマンティックの類似性、回収、および一般的な目的の表現。


Why it works:すべてのトークン表示を平均すると、 mean pooling は、騒音を減らしながら、集合的なセマンティックコンテンツをキャプチャします。


When to choose:

  • 文書類似性またはセマンティック検索アプリケーション
  • 単一のトークンによって支配されていない強力な表現が必要な場合
  • 実証的なテストが示す場合、それは他の方法を上回る(しばしば類似性のタスクのために)


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Mean pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get attention mask to ignore padding tokens
    attention_mask = inputs['attention_mask']
    
    # Sum token embeddings and divide by the number of tokens
    sum_embeddings = torch.sum(outputs.last_hidden_state * attention_mask.unsqueeze(-1), dim=1)
    count_tokens = torch.sum(attention_mask, dim=1, keepdim=True)
    mean_embeddings = sum_embeddings / count_tokens

print(f"Shape: {mean_embeddings.shape}")  # (2, 768)


Max Pooling

Max pooling はすべてのトークンのそれぞれの次元の最大値を占め、テキストに表示される場所に関係なく重要な機能をキャプチャするのに驚くほど優れている。


Best for:機能検出と情報抽出のタスク


Why it works:Max pooling は、すべてのトークンのそれぞれの次元で最も強力なアクティベーションを選択し、テキストに表示される場所に関係なく、最も顕著な機能を効果的にキャプチャします。


When to choose:

  • 特定の特徴が、その周波数や位置よりも重要である場合
  • 特定の概念やエンティティの存在を求めるとき
  • 重要な信号が平均値で溶解される可能性のある長いテキストに対処する場合


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Max pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Create a mask to ignore padding tokens for max pooling
    attention_mask = inputs['attention_mask'].unsqueeze(-1)
    
    # Replace padding token representations with -inf so they're never selected as max
    token_embeddings = outputs.last_hidden_state.masked_fill(attention_mask == 0, -1e9)
    
    # Take max over token dimension
    max_embeddings = torch.max(token_embeddings, dim=1)[0]

print(f"Shape: {max_embeddings.shape}")  # (2, 768)

Weighted Mean Pooling

Not all words contribute equally to meaning. The weighted pooling method tries to give more weight to more important tokens based on position (e.g., giving more weight to later tokens).


Best for:入力の異なる部分が異なる重要性を有するタスク


Why it works:すべての単語が同じように意味に貢献するわけではありません。 重量集計は、その位置、注意点、またはその他の関連度の指標に基づいて特定のトークンを強調することを可能にします。


When to choose:

  • 順序の順序が重要な場合(例えば、後日トークンにより多くの重みを与える場合)
  • 特定のトークンが本質的により情報的である場合(例えば、ノンネンと動詞対記事)
  • When you have a specific importance heuristic that makes sense for your task. あなたの仕事に意味がある特定の重要性があるとき


import torch
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Weighted mean pooling - more weight to later tokens
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get token embeddings and attention mask
    token_embeddings = outputs.last_hidden_state
    attention_mask = inputs['attention_mask']
    
    # Create position-based weights (later positions get higher weights)
    input_lengths = torch.sum(attention_mask, dim=1).unsqueeze(-1)
    position_indices = torch.arange(token_embeddings.size(1)).unsqueeze(0).expand_as(attention_mask)
    position_weights = position_indices.float() / input_lengths.float()
    position_weights = position_weights * attention_mask
    
    # Normalize weights to sum to 1
    position_weights = position_weights / torch.sum(position_weights, dim=1, keepdim=True)
    
    # Apply weights and sum
    weighted_embeddings = torch.sum(token_embeddings * position_weights.unsqueeze(-1), dim=1)

print(f"Shape: {weighted_embeddings.shape}")  # (2, 768)


最後のトークンポール

Last token pooling is a technique for creating a single embedding vector from a sequence of token embeddings by selecting only the final token's representation. 最後のトークン集合は、最終的なトークンの表示だけを選択することによって、トークンの組み込みのセクションから単一のベクトルを作成するためのテクニックです。


Best for:Autoregressive models and sequential processing セキュリティモデル


Why it works:GPTのような左から右のモデルでは、最終トークンは、セクション全体から蓄積された文脈を含み、特定のタスクのための情報が豊富になります。


When to choose:

  • GPT または他のデコードのみモデルを使用する場合
  • 前回の完全な文脈に大きく依存するタスクで作業する場合
  • テキスト生成または完了タスク


import torch
from transformers import AutoTokenizer, AutoModel

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Tokenize input
texts = ["This is an example sentence", "Each sentence becomes a vector"]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# Last token pooling
with torch.no_grad():
    outputs = model(**inputs)
    
    # Get the last non-padding token for each sequence
    attention_mask = inputs['attention_mask']
    last_token_indices = torch.sum(attention_mask, dim=1) - 1
    batch_indices = torch.arange(attention_mask.size(0))
    
    # Extract the last token embedding for each sequence
    last_token_embeddings = outputs.last_hidden_state[batch_indices, last_token_indices]

print(f"Shape: {last_token_embeddings.shape}")  # (2, 768)



多くの方法があり、これらの方法は一緒に組み合わせることができ、カスタムメソッドを作成することもできます. This was just the beginning for understanding embeddings as a concept and basic implementation to get embeddings using different techniques. これらは、異なる技術を使用して embeddings を取得するためのコンセプトと基本的な実装のための始まりに過ぎません。

Looking Forward: Where Embeddings Are Headed

展望:インベーダーが向かう場所

The embedding space (pun intended) continues to evolve:


  • Multimodal embeddings are breaking down barriers between text, images, audio, and video. CLIP や DALL-E のようなモデルは embeddings を使用して、異なるモダリティ間で共有されたセマンティックな空間を作成します。
  • MobileBERTやDistilBERTのようなより効率的なアーキテクチャは、限られたリソースを持つエッジデバイスで強力な埋め込みを可能にしています。
  • 専門機関で事前に訓練されたドメイン特有の埋め込みは、医学、法律、財務などの分野における最先端を推進しています。

私は、より小さな単位から意味がどのように構築されているかをよりよく捉える構成意識の組み込みに特に興奮しており、ついに否定と構成的なフレーズで長年にわたる課題を解決することができます。

Final Thoughts

最終思考

埋め込みは別のNLPテクニックではなく、機械が言語を理解し、処理する方法の根本的な転換であり、テキストを任意のシンボルとして扱うことから、人間が直感的に理解する意味や関係の豊富で複雑なネットワークをキャプチャすることに移しました。


あなたが取り組んでいるNLPの任務に関係なく、慎重に適用された埋め込みがそれをより良くする可能性があります。鍵は、それらを生成する方法だけでなく、いつ、なぜ異なるアプローチを使用するかを理解することです。


そして、あなたがまだテキスト分析のためのバッグオブ-単語またはワンホットエンコーディングを使用している場合は、


あなたを待っている可能性の世界です。

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks