← PC・IT用語集へ戻る

エンベディング

Embedding
ai data beginner
単語や文章の意味を、数値の並び(ベクトル)に変換したもののこと。
エンベディング (Embedding)

概要(サマリー)

エンベディングとは、単語や文章の意味を、数値の並び(ベクトル)に変換したもののことである。日本語では「埋め込み」「分散表現」とも呼ばれる。

コンピュータは文字そのものの意味を理解できない。そこで、意味を座標として表す。地図の上で、東京と横浜が近く、東京とロンドンが遠いのと同じように、「犬」と「猫」を近い座標に、「犬」と「経理」を遠い座標に置く。こうすると、意味の近さを距離の計算で求められるようになる。

この変換によって、文字が一致しなくても「意味が似ている」文章を探せるようになる。RAGや検索機能の土台になっている技術である。

以下は、あらかじめ計算しておいた意味の近さを、単語を選んで確かめられるデモである。

基準の単語を選ぶと、他の単語との「意味の近さ」が並び替わる。

    詳細解説

    意味を数値にするとはどういうことか

    エンベディングは、1つの単語や文章を数百〜数千個の数値の並びに変換する。たとえば次のようなイメージである。

    "犬"     → [0.21, -0.85, 0.44, 0.09, ... ]  ← 1536個の数値
    "猫"     → [0.19, -0.81, 0.47, 0.12, ... ]  ← 犬とよく似た並び
    "サーバー" → [-0.63, 0.28, -0.11, 0.77, ... ] ← 全然違う並び
    

    数値ひとつひとつに人が理解できる意味があるわけではない。「1番目は動物らしさ、2番目は大きさ」といった具合には分かれていない。重要なのは並び全体としての位置関係であり、意味が近いものは近い場所に、遠いものは遠い場所に配置される、という点だけである。

    この数値の個数を「次元数」と呼ぶ。1536次元なら、1536個の数値で1つの意味を表している。次元が多いほど細かい違いを表現できるが、そのぶん計算も保存も重くなる。

    近さの測り方

    2つのベクトルがどれくらい近いかは、計算で求められる。もっともよく使われるのがコサイン類似度で、2つの向きがどれだけ揃っているかを −1〜1 の数値で表す。

    • 1.0 に近い: ほぼ同じ意味
    • 0 あたり: 無関係
    • -1.0 に近い: 逆の意味(実務ではあまり出てこない)

    上のデモで表示している数値がこれにあたる。「犬」と「猫」が 0.82、「犬」と「サーバー」が 0.06 というように、意味の近さが数値になる。ここが肝心な点で、意味の比較が単なる算数になるため、何万件の文書でも高速に比較できる。

    文字の一致で探す検索との違い

    従来のキーワード検索は、文字が一致するかどうかで探す。そのため、次のような取りこぼしが起きる。

    • 「休みを取りたい」で検索 → 「年次有給休暇の申請について」が見つからない
    • 「PCが重い」で検索 → 「パソコンの動作が遅い場合の対処」が見つからない

    エンベディングを使った検索なら、文字がまったく違ってもどちらも見つかる。意味の座標が近いからだ。この性質を「セマンティック検索(意味検索)」と呼ぶ。

    ただし万能ではない。型番や人名のような、意味ではなく文字そのものが重要なものは逆に苦手である。「XR-2200」と「XR-2100」は意味的にはほぼ同じ座標に来てしまう。実務ではキーワード検索と併用することが多い。

    使いどころ

    • RAG: 質問に関係する資料を探し出す。もっとも代表的な用途である
    • セマンティック検索: サイト内検索で、言い回しが違っても目的の記事にたどり着けるようにする
    • 関連記事の表示: 記事同士の近さを計算して、内容の近いものを並べる
    • 分類・グループ分け: 問い合わせ内容を自動で仕分ける
    • 重複の検出: 表現は違うが同じ内容の投稿を見つける

    実際の作り方

    エンベディングは自分で計算するものではなく、専用のモデルにテキストを渡して受け取る。多くはAPI経由で使う。

    # 文章を渡すと、意味を表す数値の並びが返ってくる
    res = client.embeddings.create(
        model="text-embedding-3-small",
        input="有給休暇はいつから取れますか"
    )
    vec = res.data[0].embedding   # [0.013, -0.027, ... ] 1536個の数値
    

    重要な約束事がひとつある。保存するときと検索するときで、同じモデルを使わなければならない。 モデルが違えば座標系そのものが違うので、比較しても意味のない数値しか出てこない。モデルを新しいものに変えるなら、保存済みの全データを作り直す必要がある。

    計算したベクトルはベクトルデータベースに保存して、高速に検索できるようにするのが一般的である。

    生成AIのトークンとの違い

    トークンと混同されやすいが、役割がまったく違う。

    • トークン: 文章を細かく区切った「単位」。「有給休暇」を「有給」「休暇」の2つに分ける、といった分割の話
    • エンベディング: その単位や文章全体の「意味」を数値にしたもの

    トークンは切り分け、エンベディングは意味の座標化である。トークン数はAPIの料金や入力量の目安に使われるが、エンベディングは検索や分類に使われる。

    AIコーディングとの関係

    エンベディングをAIに実装してもらうこと自体は難しくない。API呼び出しが数行で済むためだ。ただし、AIが黙って決めてしまいがちな箇所があるので、先に指定しておくとよい。

    • どのモデルを使うか(次元数と費用が変わる)
    • 何を1件として保存するか(記事単位か、段落単位か)
    • どこに保存するか(ベクトルデータベースか、ファイルか)
    • 正規化するかどうか(コサイン類似度を使うなら通常は正規化する)

    たとえば「Markdownの記事200本を見出し単位で分割し、text-embedding-3-small でベクトル化して保存する処理を書いて。あとから検索できるよう、元の見出しとファイル名も一緒に保存して」と伝えると、実用的なものが出てくる。

    生成後に確認したいのは、同じモデルで保存と検索をしているかと、元テキストを一緒に保存しているかである。ベクトルだけ保存して元の文章を捨ててしまうと、検索で見つけても何が見つかったのか分からない、という状態になる。AIが書いたコードで意外とやりがちな抜けである。

    よくある勘違い

    エンベディングは文章を圧縮したもの?

    圧縮ではない。エンベディングから元の文章を復元することはできない。意味の座標だけを取り出したもので、元の言葉は捨てられている。だから検索システムでは、ベクトルとは別に元テキストも必ず保存しておく必要がある。

    数値の1つ1つに意味がある?

    「3番目の数値は感情の強さ」といった具合に、人が読み取れる意味は割り当てられていない。意味を持つのは並び全体の位置関係だけである。個々の数値を見ても何も分からない。

    次元数が多いほど高性能?

    次元が多いほど細かい違いを表せるが、保存容量も計算量も増える。用途によっては小さいモデルで十分なことが多く、実際に検索精度を比べてから決めるのがよい。「大きいほうが良い」とは限らない。

    エンベディングとトークンは同じもの?

    別物である。トークンは文章を区切った単位、エンベディングはその意味を数値化したものだ。「1000トークンの文章を1536次元のベクトルに変換する」というように、両方が同時に登場することもある。

    まとめ

    • エンベディングは、単語や文章の意味を数値の並び(ベクトル)に変換したものである
    • 意味が近いものは近い座標に置かれ、近さをコサイン類似度などの計算で求められる
    • 文字が一致しなくても意味で探せるが、型番や固有名詞の完全一致は苦手である
    • 保存時と検索時で同じモデルを使う必要がある。モデルを変えるなら全件作り直す
    • ベクトルからは元の文章を復元できないので、元テキストも必ず一緒に保存する

    情報ソース

    より詳しくAIに聞いてみよう

    • エンベディングとは何かを、意味を座標にするというたとえで初心者向けに説明してください。
    • コサイン類似度がどう計算されるのかを、簡単な例つきで教えてください。
    • キーワード検索とベクトル検索の得意・不得意を比較して整理してください。
    • エンベディングのモデルを変更するとき、既存データにどんな影響があるか教えてください。
    • AIに検索機能のコードを生成してもらうとき、元テキストとベクトルをどう保存させるべきか教えてください。