概要
この手順書では、PostgreSQLを使用して、レコメンドエンジンの実装などに役立つ類似度検索を行う方法について説明します。
前準備データベースのインストール
PostgreSQLとpgvectorをインストール
以下のコマンドを実行して、PostgreSQLとpgvectorをインストールします。これにより、データベース管理とベクトル検索機能が利用可能になります。
brew install postgresql pgvector
PostgreSQLを起動
PostgreSQLサービスを開始するには、以下のコマンドを使用します。これにより、PostgreSQLデータベースがバックグラウンドで実行されるようになります。
brew services start postgresql
pgvectorを有効にするデータベースを作成
新しいデータベースvector_test
を作成します。これのデータベースをpgvector拡張機能のテストに使います。
createdb vector_test
データベースにログイン
作成したデータベースvector_test
にログインします。以下のコマンドを実行すると、psqlコンソールが開きます。
psql vector_test
拡張機能pgvectorを有効化
pgvector拡張機能をデータベースに追加して、ベクトル検索機能を有効にします。
CREATE EXTENSION vector;
サンプルデータの作成
vectorカラムを持つテーブルの作成
3次元のベクトルデータを格納できるuser_profiles
テーブルを作成します。このテーブルは、ユーザープロファイルの名前と、そのプロファイルを表す3次元ベクトルデータを格納します。
CREATE TABLE user_profiles (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
profile_vector vector(3) -- 3次元のベクトルデータを格納するカラム
);
サンプルデータの挿入
テーブルにサンプルデータを挿入します。この例では、3人のユーザーAlice
, Bob
, Charlie
のプロファイルベクトルを追加します。
INSERT INTO user_profiles (name, profile_vector)
VALUES
('Alice', '[0.1, 0.2, 0.3]'), -- 3次元ベクトルデータ
('Bob', '[0.4, 0.5, 0.6]'),
('Charlie', '[0.7, 0.8, 0.9]');
類似度を計算する
類似度計算には、ユークリッド距離、負の内積、コサイン距離の3つの演算子が使用できます。
- <-> (Euclidean Distance)
- 二点間の通常の距離を計算
- 最も直感的な「距離」を表す、物理的な距離の測り方
- <#> (Negative Inner Product)
- 二つのベクトル間の内積の負数を計算
- ベクトルの方向性の類似性や差異を強調するために使用される
- <=> (Cosine Distance)
- 二つのベクトル間の角度のコサインを基にした距離を計算
- ベクトルの方向性のみを考慮し、テキストの類似性検索や文書分類などでよく使用される
以下は、ユークリッド距離を使用して、特定のベクトルに最も近いユーザープロファイルを検索するクエリの例です。
SELECT *, profile_vector <-> '[0.6, 0.6, 0.6]' AS distance
FROM user_profiles
ORDER BY distance;
実行結果
id | name | profile_vector | distance
----+---------+----------------+---------------------
2 | Bob | [0.4,0.5,0.6] | 0.22360682440598487
3 | Charlie | [0.7,0.8,0.9] | 0.37416567973634735
1 | Alice | [0.1,0.2,0.3] | 0.7071068233333948
(3 rows)
お片付け
テスト用に作成したデータベースを削除し、PostgreSQLサービスを停止する方法を以下に示します。
データベースの削除
テストで使用したvector_test
データベースを削除します。
dropdb vector_test
PostgreSQLの停止
PostgreSQLサービスを停止します。
brew services stop postgresql
以上で、PostgreSQLとpgvectorを使用した類似度検索の基本的な手順の説明は終わりです。