Embeddingモデル入門|テキスト・画像のベクトル化と類似検索の実践

kento_morota 19分で読めます

AIアプリケーションの開発が身近になるなか、「Embedding(埋め込み)」は避けて通れない技術になっています。検索エンジン、レコメンドシステム、RAG(検索拡張生成)など、多くのAI機能の基盤となるのがEmbeddingモデルです。

本記事では、Embeddingモデルの仕組みから、テキスト・画像のベクトル化、類似検索の実装まで、Pythonのコード例を交えて実践的に解説します。

Embeddingとは何か

Embedding(埋め込み)とは、テキスト・画像・音声などのデータを、固定長の数値ベクトル(数値の配列)に変換する技術です。たとえば、「プログラミング」というテキストを[0.12, -0.34, 0.56, ...]のような1536次元のベクトルに変換します。

なぜベクトルに変換する必要があるのでしょうか。それは、コンピュータが「意味の近さ」を計算できるようにするためです。人間は「犬」と「猫」が似た概念であることを直感的に理解できますが、コンピュータにとっては単なる異なる文字列にすぎません。Embeddingを使えば、意味的に近い概念のベクトルは数値的にも近くなるため、コンピュータが「意味の類似度」を数値として計算できるようになります。

ベクトル空間での意味表現

Embeddingモデルが生成するベクトルは、高次元のベクトル空間上の点として表現されます。この空間では、意味的に関連するデータが近くに配置されます。

たとえば、テキストEmbeddingの場合、以下のような関係が成り立ちます。

・「Python入門」と「Pythonチュートリアル」のベクトルは非常に近い
・「Python入門」と「JavaScript入門」のベクトルはやや近い(プログラミング言語の入門という共通点)
・「Python入門」と「イタリア料理のレシピ」のベクトルは遠い

この性質を利用することで、キーワードの完全一致に頼らない「意味検索(セマンティック検索)」が実現できます。

Embeddingモデルの種類

Embeddingモデルには、用途に応じていくつかの種類があります。

テキストEmbeddingモデル
テキストを固定長のベクトルに変換します。代表的なモデルとして、OpenAIのtext-embedding-3-small/large、Cohereのembed-v3、オープンソースのBGE-M3やE5-mistralなどがあります。

画像Embeddingモデル
画像をベクトルに変換します。CLIPやSigLIPなどのマルチモーダルモデルは、テキストと画像を同じベクトル空間に変換できるため、テキストで画像を検索することも可能です。

マルチモーダルEmbeddingモデル
テキスト・画像・音声などの異なるモダリティのデータを、同一のベクトル空間にマッピングするモデルです。異なる種類のデータ間の類似度を計算できます。

主要なテキストEmbeddingモデルの比較

2026年時点で利用可能な主要テキストEmbeddingモデルを比較します。用途と予算に応じて最適なモデルを選択しましょう。

APIベースのモデル

OpenAI text-embedding-3-small
次元数は1536で、コストパフォーマンスに優れたモデルです。100万トークンあたりの料金が安く、多くのユースケースで十分な品質を提供します。日本語のサポートも良好です。RAGの初期構築やプロトタイピングに最適です。

OpenAI text-embedding-3-large
次元数は3072で、smallモデルより高品質なベクトルを生成します。精度が重要な本番環境での使用に向いています。次元数の削減(マトロシカ表現)にも対応しており、品質とコストのトレードオフを調整できます。

Cohere embed-v3
多言語対応に優れ、日本語の品質も高いモデルです。検索用途に特化したsearch_documentタイプと、分類用途に特化したclassificationタイプを使い分けられます。

オープンソースのモデル

BGE-M3
中国のBAAI(Beijing Academy of Artificial Intelligence)が開発した多言語Embeddingモデルです。100以上の言語をサポートし、日本語の品質も高水準です。自社サーバーで動作させることで、データの外部送信を避けられます。

E5-mistral-7b-instruct
Mistralベースの大規模Embeddingモデルで、タスク別のプロンプトを指定することで用途に応じた最適なベクトルを生成できます。GPUリソースが必要ですが、APIベースのモデルに匹敵する品質が得られます。

multilingual-e5-large
軽量で多言語対応のモデルです。CPUでも動作するため、リソースが限られた環境での使用に適しています。品質は大規模モデルに劣りますが、小規模なプロジェクトには十分な性能です。

モデル選定の指針

モデル選定の際は、以下の観点で検討します。

品質優先:text-embedding-3-large、E5-mistral-7b-instruct
コスト優先:text-embedding-3-small、multilingual-e5-large
データプライバシー重視:BGE-M3、multilingual-e5-large(自社サーバーで実行)
多言語対応:Cohere embed-v3、BGE-M3

テキストEmbeddingの実装

ここからは、Pythonを使ったEmbeddingの実装例を紹介します。まずはテキストEmbeddingの基本から始めます。

OpenAI APIでのテキストベクトル化

OpenAIのEmbedding APIを使った基本的な実装です。

from openai import OpenAI

client = OpenAI()

def get_embedding(text: str, model: str = "text-embedding-3-small") -> list[float]:
    """テキストをベクトルに変換する"""
    response = client.embeddings.create(
        input=text,
        model=model
    )
    return response.data[0].embedding

# 使用例
text = "Pythonでwebアプリケーションを開発する方法"
vector = get_embedding(text)
print(f"ベクトルの次元数: {len(vector)}")  # 1536
print(f"先頭5要素: {vector[:5]}")

バッチ処理で複数のテキストを一度にベクトル化することも可能です。APIの呼び出し回数を減らしてコストを抑えられます。

def get_embeddings_batch(texts: list[str], model: str = "text-embedding-3-small") -> list[list[float]]:
    """複数テキストを一括でベクトル化する"""
    response = client.embeddings.create(
        input=texts,
        model=model
    )
    return [item.embedding for item in response.data]

texts = [
    "Pythonの基本文法",
    "JavaScriptフレームワーク比較",
    "データベース設計入門"
]
vectors = get_embeddings_batch(texts)

オープンソースモデルでのベクトル化

sentence-transformersライブラリを使うと、オープンソースモデルをローカルで実行できます。

from sentence_transformers import SentenceTransformer

# モデルの読み込み(初回はダウンロードが発生)
model = SentenceTransformer("BAAI/bge-m3")

# テキストのベクトル化
texts = [
    "機械学習の基礎",
    "深層学習入門ガイド",
    "イタリアンレストランの予約"
]
embeddings = model.encode(texts, normalize_embeddings=True)

print(f"ベクトルの形状: {embeddings.shape}")  # (3, 1024)

ローカル実行のメリットは、APIの呼び出しコストがかからないことと、データを外部に送信しなくて済むことです。GPUがあれば処理速度も高速です。

類似度の計算方法

ベクトル化したデータの類似度を計算する方法を解説します。最もよく使われるのはコサイン類似度です。

コサイン類似度

コサイン類似度は、2つのベクトルの角度の余弦を計算する手法です。値は-1から1の範囲で、1に近いほど類似度が高いことを示します。

import numpy as np

def cosine_similarity(vec1: list[float], vec2: list[float]) -> float:
    """コサイン類似度を計算する"""
    a = np.array(vec1)
    b = np.array(vec2)
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 類似度の計算例
text1 = "Python プログラミング入門"
text2 = "Pythonの基本的な書き方"
text3 = "今日の天気予報"

vec1 = get_embedding(text1)
vec2 = get_embedding(text2)
vec3 = get_embedding(text3)

print(f"text1 vs text2: {cosine_similarity(vec1, vec2):.4f}")  # 高い類似度
print(f"text1 vs text3: {cosine_similarity(vec1, vec3):.4f}")  # 低い類似度

その他の距離尺度

コサイン類似度以外にも、用途に応じた距離尺度があります。

ユークリッド距離(L2距離)
ベクトル空間上の直線距離を計算します。値が小さいほど類似度が高くなります。正規化されたベクトルに対してはコサイン類似度と同等の結果になります。

内積(ドット積)
ベクトルの大きさと方向の両方を考慮した類似度です。正規化されたベクトルに対してはコサイン類似度と一致します。計算が高速なため、大量のベクトルを扱う場合に適しています。

実際の開発では、コサイン類似度を使うケースが最も多いです。Embeddingモデルの多くが正規化されたベクトルを出力するため、内積を使っても同じ結果が得られます。

ベクトルデータベースを使った類似検索の実装

少量のデータならnumpyでの類似度計算で十分ですが、数万件以上のデータを扱う場合はベクトルデータベース(Vector Database)の利用が必要です。

主要なベクトルデータベース

Chroma
軽量で導入が簡単なベクトルデータベースです。ローカル環境やプロトタイピングに最適です。Pythonライブラリとして簡単に組み込めます。

Pinecone
フルマネージドのクラウドベクトルデータベースです。インフラ管理が不要で、スケーラビリティに優れています。本番環境での利用に向いています。

Qdrant
Rust製の高性能ベクトルデータベースです。フィルタリング機能が充実しており、メタデータによる絞り込みと類似検索を組み合わせた検索が得意です。

pgvector
PostgreSQLの拡張機能として動作するベクトル検索エンジンです。既存のPostgreSQLインフラにベクトル検索機能を追加できるため、新たなインフラを構築する必要がありません。

Chromaを使った類似検索の実装

Chromaを使った類似検索の実装例を示します。

import chromadb
from chromadb.utils import embedding_functions

# OpenAIのEmbedding関数を設定
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    model_name="text-embedding-3-small"
)

# クライアントとコレクションの作成
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(
    name="tech_articles",
    embedding_function=openai_ef
)

# ドキュメントの追加
collection.add(
    documents=[
        "Pythonで機械学習モデルを構築する方法",
        "React Hooksの使い方完全ガイド",
        "PostgreSQLのパフォーマンスチューニング",
        "Docker Composeで開発環境を構築する",
        "TypeScriptの型システム入門"
    ],
    ids=["doc1", "doc2", "doc3", "doc4", "doc5"],
    metadatas=[
        {"category": "AI"},
        {"category": "フロントエンド"},
        {"category": "データベース"},
        {"category": "インフラ"},
        {"category": "フロントエンド"}
    ]
)

# 類似検索
results = collection.query(
    query_texts=["機械学習の入門書が読みたい"],
    n_results=3
)

for doc, distance in zip(results["documents"][0], results["distances"][0]):
    print(f"類似度: {1 - distance:.4f} | {doc}")

メタデータを使ったフィルタリングも可能です。カテゴリやタグで絞り込んだ上で類似検索を行えます。

# メタデータによるフィルタリング付き検索
results = collection.query(
    query_texts=["Webアプリケーションの開発"],
    n_results=3,
    where={"category": "フロントエンド"}
)

画像Embeddingとマルチモーダル検索

テキストだけでなく、画像のベクトル化と類似検索も実装できます。CLIPモデルを使えば、テキストと画像を同じベクトル空間に変換できるため、テキストで画像を検索することが可能になります。

CLIPを使った画像Embedding

from sentence_transformers import SentenceTransformer
from PIL import Image

# CLIPモデルの読み込み
model = SentenceTransformer("clip-ViT-B-32")

# 画像のベクトル化
image = Image.open("sample.jpg")
image_embedding = model.encode(image)

# テキストのベクトル化(同じ空間)
text_embedding = model.encode("a photo of a cat")

# テキストと画像の類似度計算
from numpy import dot
from numpy.linalg import norm
similarity = dot(image_embedding, text_embedding) / (norm(image_embedding) * norm(text_embedding))
print(f"テキストと画像の類似度: {similarity:.4f}")

マルチモーダル検索の活用例

テキストと画像のクロスモーダル検索は、以下のような場面で活用されています。

ECサイトの商品検索
「赤いワンピース」というテキストで商品画像を検索したり、参考画像をアップロードして似た商品を見つけたりする機能を実装できます。

社内資料の横断検索
テキスト文書・プレゼンテーション・画像資料をすべてベクトル化し、一つの検索クエリで横断的に検索できるシステムを構築できます。

コンテンツレコメンド
ユーザーが閲覧したコンテンツ(テキスト・画像問わず)のベクトルから、類似するコンテンツを推薦するシステムに活用できます。

RAG(検索拡張生成)への応用

EmbeddingモデルのもっともポピュラーなRAG(Retrieval-Augmented Generation)は、LLMの回答精度を向上させる手法として広く使われています。

RAGの基本的な仕組み

RAGは以下の3ステップで動作します。

1. ドキュメントの前処理:社内文書や技術資料をチャンクに分割し、Embeddingモデルでベクトル化してベクトルデータベースに格納
2. 検索(Retrieval):ユーザーの質問をベクトル化し、ベクトルデータベースから関連するチャンクを検索
3. 生成(Generation):検索結果をコンテキストとしてLLMに渡し、質問に対する回答を生成

RAGの実装例

from openai import OpenAI
import chromadb
from chromadb.utils import embedding_functions

client = OpenAI()

# ベクトルDBの準備
chroma_client = chromadb.PersistentClient(path="./rag_db")
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    model_name="text-embedding-3-small"
)
collection = chroma_client.get_or_create_collection(
    name="knowledge_base",
    embedding_function=openai_ef
)

def add_documents(documents: list[str], ids: list[str]):
    """ドキュメントをベクトルDBに追加"""
    collection.add(documents=documents, ids=ids)

def rag_query(question: str, n_results: int = 3) -> str:
    """RAGによる質問応答"""
    # 関連ドキュメントの検索
    results = collection.query(
        query_texts=[question],
        n_results=n_results
    )
    context = "\n\n".join(results["documents"][0])

    # LLMで回答を生成
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": f"以下のコンテキストを参考に質問に回答してください。\n\nコンテキスト:\n{context}"},
            {"role": "user", "content": question}
        ]
    )
    return response.choices[0].message.content

RAGの品質を高めるテクニック

RAGの検索品質を向上させるテクニックをいくつか紹介します。

チャンクサイズの最適化
ドキュメントの分割サイズは検索品質に大きく影響します。一般的には200〜500トークン程度が適切ですが、ドキュメントの性質によって調整が必要です。技術文書は見出し単位、FAQは質問・回答単位で分割するとよいでしょう。

ハイブリッド検索
ベクトル検索とキーワード検索(BM25など)を組み合わせるハイブリッド検索は、単独の検索方式より高い精度を実現します。固有名詞やコード名などはキーワード検索のほうが正確に検索できます。

リランキング
ベクトル検索の結果を、Cross-Encoderモデルで再順位付け(リランキング)することで、最終的な検索精度を向上させます。Cohere RerankやBGE-rerankerなどのモデルが利用できます。

まとめ

Embeddingモデルは、テキストや画像を数値ベクトルに変換し、意味的な類似度を計算可能にする技術です。本記事で紹介した内容を整理します。

・Embeddingはデータを固定長ベクトルに変換し、意味的な類似度の計算を可能にする
・OpenAI APIやオープンソースモデルで手軽にベクトル化を実装できる
・コサイン類似度で2つのベクトルの意味的な近さを測定する
・Chroma、Pinecone、pgvectorなどのベクトルデータベースで大規模な類似検索を実現する
・CLIPモデルを使えばテキストと画像のクロスモーダル検索が可能になる
・RAGへの応用により、LLMの回答精度を大幅に向上できる

まずはOpenAI APIとChromaを使った小規模な類似検索を試し、Embeddingの動作を体感することをおすすめします。基本を理解した上で、RAGやレコメンドシステムなど、より高度な活用に段階的に取り組んでいきましょう。

#Embedding#ベクトル化#AI
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

AI活用のヒントをお探しですか?お気軽にご相談ください。

まずは話だけ聞いてもらう