

ベクトル埋め込みのコンテキストでは、埋め込みとベクトルは同じものです。
https://www.elastic.co/jp/what-is/vector-embedding
ベクトルデータベースの検索では、このベクトルが近いものを検索します。
何をもって"近い"とするか (類似度) は、以下のように色んな判断方法があります。

緯度、経度を例にすると、地理的距離が近い方が近くなります

緯度、経度を例にすると、方角が近い方が近くなります。
ベクトルデータベース (キーワード検索ではなく、ベクトル検索) を利用する理由は以下です。
- 画像や音楽などの非構造化データを検索
- キーワードに含まれないが、関連するテキストを検索

「東京スカイツリー 観光」とキーワードが一致しないが、近くのおすすめランチがヒットしている
| RAG (検索拡張生成) | |||
|---|---|---|---|
| 学習ロードマップ | |||||
|---|---|---|---|---|---|
ベクトルデータベースの種類一覧
ベクトルデータベースには、主に以下のデータベースが利用されます。

本記事では、OpenSearch (Elasticsearch の fork) を元に、ベクトルデータベースを解説します。
ベクトルデータベースの作り方
OpenSearch のベクトル検索 (ベクトルデータベースを使った検索) は、主に 2 種類存在します。
- OpenSearch 外でベクトルを生成して、保存・検索
- OpenSearch 内でベクトルを生成して、保存・検索


OpenSearch 外でベクトルを生成
OpenSearch 外で生成したベクトルを検索する方法について説明します。


0. ベクトル埋め込み
まずは、ベクトル埋め込みを利用してデータをベクトルに変換する必要があります。
※ OpenSearch 外の作業
| 変換前のデータ | ベクトル埋め込み |
|---|---|
| 単語 | Word2Vec, GloVe, FastText |
| 文章 | Universal Sentence Encoder (USE) |
| ドキュメント | Doc2Vec |
| 画像 | CNN |
| 地理空間 | 国土地理院 API |
今回は、各都道府県を緯度と経度の 2 次元ベクトルで表現して検索してみます。
なお、今回は既に都道府県を緯度と経度に変換済みのデータを利用します。
(自分で変換したい方は、国土地理院 API などをご利用ください)
http://agora.ex.nii.ac.jp/digital-typhoon/search_place.html.ja
都道府県 地名 緯度 (N) 経度 (E) 沖縄県 那覇市 26.212 127.681 大阪府 大阪市 34.686 135.520 神奈川県 横浜市 35.448 139.692 東京都 東京 35.689 139.692 北海道 札幌市 43.065 141.347 一部抜粋
1. k-NN インデックスを作成

何をもって"近い"とするかは、OpenSearch の space_type で設定できます。(こちら)

緯度、経度を例にすると、地理的距離が近い方が近くなります

緯度、経度を例にすると、方角が近い方が近くなります。
PUT prefectures
{
"settings": {
"index.knn":true
},
"mappings": {
"properties": {
"location": {
"type": "knn_vector",
"dimension": 2
}
}
}
}
2. k-NN インデックスにデータを追加
以下のデータを追加します。
| 都道府県 | 地名 | 緯度 (N) | 経度 (E) |
|---|---|---|---|
| 沖縄県 | 那覇市 | 26.212 | 127.681 |
| 大阪府 | 大阪市 | 34.686 | 135.520 |
| 東京都 | 東京 | 35.689 | 139.692 |
| 北海道 | 札幌市 | 43.065 | 141.347 |
POST /_bulk
{ "index": { "_index": "prefectures", "_id": "沖縄" } }
{ "location": [26.212, 127.681] }
{ "index": { "_index": "prefectures", "_id": "大阪" } }
{ "location": [34.686, 135.520] }
{ "index": { "_index": "prefectures", "_id": "東京" } }
{ "location": [35.689, 139.692] }
{ "index": { "_index": "prefectures", "_id": "北海道" } }
{ "location": [43.065, 141.347] }
3. k-NN インデックスを検索
神奈川の緯度経度と近いベクトルの都道府県を検索してみます。
| 都道府県 | 地名 | 緯度 (N) | 経度 (E) |
|---|---|---|---|
| 神奈川県 | 横浜市 | 35.448 | 139.692 |
POST /prefectures/_search
{
"query": {
"knn": {
"location": {
"vector": [35.448, 139.642],
"k": 3
}
}
}
}
神奈川に緯度経度が近い県から順番に検索結果が表示されます。
(近いほど _score が高くなります)
"hits": [
{
"_index": "prefectures",
"_id": "東京",
"_score": 0.9428803,
"_source": {
"location": [
35.689,
139.692
]
}
},
{
"_index": "prefectures",
"_id": "大阪",
"_score": 0.053846005,
"_source": {
"location": [
34.686,
135.52
]
}
},
{
"_index": "prefectures",
"_id": "北海道",
"_score": 0.016148392,
"_source": {
"location": [
43.065,
141.347
]
}
},
{
"_index": "prefectures",
"_id": "沖縄",
"_score": 0.0043597827,
"_source": {
"location": [
26.212,
127.681
]
}
}
OpenSearch 内でベクトルを生成


OpenSearch では、Neural search を利用すると、クエリに含まれるデータをベクトルに変換してから保存・検索できます。

ニューラル検索で利用できるベクトル変換モデル (ML モデル) は以下のとおりです。
| 検索方法 | 用途 | ベクトル変換モデル (ML モデル) |
|---|---|---|
| セマンティック検索 | テキストの意味を考慮して検索 | テキスト埋め込みモデル |
| マルチモーダル検索 | 画像検索 | マルチモーダル埋め込みモデル |
| スパース検索 | スパース検索 (計算コストの削減) | スパース埋め込みモデル |
| 会話型検索 | 自然言語で会話するように検索 | 大規模言語モデル (LLM) |
今回は MS MARCO モデルを利用して、セマンティック検索を行います。
1. ML モデルをセットアップ
前提条件:メモリの潤沢なマシンを使ってください。
PUT _cluster/settings
{
"persistent": {
"plugins.ml_commons.only_run_on_ml_node": false
}
}
msmarco-distilbert-base-tas-b という MS MARCO モデルを登録します。
POST /_plugins/_ml/models/_register
{
"name": "huggingface/sentence-transformers/msmarco-distilbert-base-tas-b",
"version": "1.0.1",
"model_format": "TORCH_SCRIPT"
}
GET /_plugins/_ml/tasks/_search
{}
"state": "COMPLETED",
"model_id": "0123456789abcdefghij",
※state が CREATED から COMPLETED になると、model_id が表示されます。
POST /_plugins/_ml/models/model_id/_deploy
デプロイが完了したかどうかは、GET /_plugins/_ml/tasks/_search で確認できます。
2. Neural search でデータ取込
PUT /_ingest/pipeline/nlp-ingest-pipeline
{
"processors": [
{
"text_embedding": {
"model_id": "model_id",
"field_map": {
"text": "passage_embedding"
}
}
}
]
}
OpenSearch 外でベクトルを生成する場合と同じく、k-NN インデックスを作成します。
PUT /my-nlp-index
{
"settings": {
"index.knn": true,
"default_pipeline": "nlp-ingest-pipeline"
},
"mappings": {
"properties": {
"passage_embedding": {
"type": "knn_vector",
"dimension": 768
},
"text": {
"type": "text"
}
}
}
}
dimension はモデルの次元に合わせて 768 にします。
POST _bulk
{ "index": { "_index": "my-nlp-index", "_id": "東京" } }
{ "text": "Tokyo is the capital of Japan and one of the most populous cities in the world, with a population of over 14 million residents as of 2023 and the second-most-populated capital in the world." }
{ "index": { "_index": "my-nlp-index", "_id": "北海道" } }
{ "text": "Hokkaido is the second-largest island of Japan and comprises the largest and northernmost prefecture, making up its own region." }
{ "index": { "_index": "my-nlp-index", "_id": "沖縄" } }
{ "text": "Okinawa Prefecture is the southernmost and westernmost prefecture of Japan." }
{ "index": { "_index": "my-nlp-index", "_id": "大阪" } }
{ "text": "Osaka is a designated city in the Kansai region of Honshu in Japan, and one of the three major cities of Japan (Tokyo-Osaka-Nagoya)." }
OpenSearch 外でベクトルを生成する場合と異なり、事前にベクトルに変換する必要が無いです。
※利用しているモデルは英語のモデルなので、英語で投入します。
3. データを検索
GET /my-nlp-index/_search
{
"_source": {
"excludes": [
"passage_embedding"
]
},
"query": {
"neural": {
"passage_embedding": {
"query_text": "vast area",
"model_id": "model_id",
"k": 4
}
}
}
}
{
"_index": "my-nlp-index",
"_id": "北海道",
"_score": 0.014841334,
"_source": {
"text": "Hokkaido is the second-largest island of Japan and comprises the largest and northernmost prefecture, making up its own region."
}
},
{
"_index": "my-nlp-index",
"_id": "東京",
"_score": 0.014191683,
"_source": {
"text": "Tokyo is the capital of Japan and one of the most populous cities in the world, with a population of over 14 million residents as of 2023 and the second-most-populated capital in the world."
}
},
{
"_index": "my-nlp-index",
"_id": "大阪",
"_score": 0.013411345,
"_source": {
"text": "Osaka is a designated city in the Kansai region of Honshu in Japan, and one of the three major cities of Japan (Tokyo-Osaka-Nagoya)."
}
},
{
"_index": "my-nlp-index",
"_id": "沖縄",
"_score": 0.012613818,
"_source": {
"text": "Okinawa Prefecture is the southernmost and westernmost prefecture of Japan."
}
}
vast area (広大な面積) で検索したところ、北海道が一番上にヒットしました。
ドキュメントには vast や area が一切含まれていませんが、second-largest island と相関が高いのか、無事に北海道が取得できました。
関連記事
| RAG (検索拡張生成) | |||
|---|---|---|---|
| Elasticsearch & OpenSearch の使い方 | ||||
|---|---|---|---|---|
| 学習ロードマップ | |||||
|---|---|---|---|---|---|
| ディープラーニング | ||||
|---|---|---|---|---|

KNN







![Elastic Stack実践ガイド[Elasticsearch/Kibana編] impress top gearシリーズ](https://m.media-amazon.com/images/I/51ieij7UhAL._SL160_.jpg)






































![[増補改訂]ビッグデータを支える技術 ——ラップトップ1台で学ぶデータ基盤のしくみ WEB+DB PRESS plus](https://m.media-amazon.com/images/I/51V-rBEb0PL._SL160_.jpg)

![Elastic Stack実践ガイド[Logstash/Beats編] impress top gearシリーズ](https://m.media-amazon.com/images/I/51UyZjgKQML._SL160_.jpg)
