地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【LLM】Embeddingとは

Embedding(エンベディング)とは、情報をコンパクトな数値ベクトル(多くの場合は高次元ベクトル)に変換する技術を指します。主に機械学習自然言語処理の分野で使用され、文章や単語、画像、その他のデータを数値の形で表現することで、コンピュータがそれらを処理しやすくする。ベクトルとかは高校とか大学でもやって気がするけど苦手な分野なので正直難しそうという印象しかない。

atmarkit.itmedia.co.jp

Embeddingのフロー

データ収集と前処理
語彙の作成
単語の数値化
モデルに渡してEmbeddingベクトルを生成
Embeddingベクトルの利用

こんな流れになる。ベクトルデータ自体はどこかに保存するのでそこで出てくるのがベクトルデータベースというやつ。ベクトル検索 SQLite 拡張のsqlite-vecとかPostgreSQLの拡張のpgvectorというのがある。

github.com

github.com

Embeddingのモデル

Embeddingのモデルとは、単語や文章、画像などのデータを数値ベクトルに変換するためのアルゴリズムニューラルネットワークモデルを指します。このモデルは、データ間の意味的・特徴的な関係を捉えるために、ベクトル空間にデータを配置することを目指します。ここでは、特に自然言語処理における代表的なEmbeddingモデルをいくつか見てみます。

Word2Vec

Word2Vecは、自然言語処理で広く使われる単語埋め込みモデルです。Googleによって開発され、2つの主要なアーキテクチャ(CBOWとSkip-Gram)を使用して単語の埋め込みベクトルを学習します。

ja.wikipedia.org

BERT

Googleが開発したトランスフォーマーベースのモデルで、双方向のコンテキスト情報を利用して文脈に基づく単語の埋め込みを学習します。BERTは文全体の意味や単語の前後関係を理解するため、より高度な言語理解が可能とのこと。

ja.wikipedia.org

(Transformerとは、主に自然言語処理NLP)において利用される強力なニューラルネットワークアーキテクチャです。2017年にGoogleによって発表された論文「Attention is All You Need」で初めて紹介され、その後、多くのNLPモデルやタスクにおいて基盤となる技術となっている。)

触ってみる

BERTとpgvectorを使ってベクトルデータ化してデータに突っ込んでみるというのをやってみます

# pgvectorをインストール
psql -c "CREATE EXTENSION IF NOT EXISTS vector;"

pipでライブラリを持ってくる

$ pip install transformers torch psycopg2 numpy

BERTで文をベクトル化する

from transformers import BertTokenizer, BertModel
import torch
import numpy as np

# BERTモデルとトークナイザーをロード
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

def encode_text(text):
    # テキストをトークナイズし、BERTでベクトル化
    inputs = tokenizer(text, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
    
    # 文全体のベクトルとして[CLS]トークンのベクトルを取得
    cls_embedding = outputs.last_hidden_state[0][0].numpy()
    
    return cls_embedding

# サンプルの文をベクトル化
text = "I love natural language processing"
vector = encode_text(text)
print(f"Vector for the text: {vector}")

ベクトルを保存

import psycopg2
import numpy as np

conn = psycopg2.connect(
    dbname="your_db_name", 
    user="your_username", 
    password="your_password", 
    host="your_host", 
    port="your_port"
)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS text_embeddings (
    id SERIAL PRIMARY KEY,
    text TEXT,
    embedding VECTOR(768)
);
""")
conn.commit()

def insert_embedding(text, vector):
    # ベクトルをPostgreSQLに挿入
    cur.execute("INSERT INTO text_embeddings (text, embedding) VALUES (%s, %s)", (text, vector.tolist()))
    conn.commit()

# サンプルの文とベクトルを挿入
insert_embedding(text, vector)

# 挿入結果の確認
cur.execute("SELECT * FROM text_embeddings;")
rows = cur.fetchall()
for row in rows:
    print(row)

cur.close()
conn.close()

検索もできる

def search_similar_vectors(vector, top_k=5):
    cur = conn.cursor()
    cur.execute("""
    SELECT text, embedding 
    FROM text_embeddings 
    ORDER BY embedding <-> %s 
    LIMIT %s;
    """, (vector.tolist(), top_k))
    
    results = cur.fetchall()
    cur.close()
    return results

# 検索実行
similar_texts = search_similar_vectors(vector)
print(f"Similar texts: {similar_texts}")