矢量数据库简单介绍:在 Postgres使用 pg_vector

作为向人工智能大规模转变的一部分,矢量数据库越来越受欢迎。它们也称为矢量化数据库,在人工智能领域发挥着至关重要的作用,因此了解它们的工作原理非常重要。为此,我们首先需要了解什么是向量。

什么是向量?

向量是表示文本或图像等 非结构化数据 的数字数组。

例如,让我们将这些句子表示为向量:

s1 = “I love data”
s2 = “I love candy”

我们可以采用所有单词并创建具有四个维度(每个术语一个)的所谓“词袋”(BoW)模型:

BoW 的问题在于,它们依赖于词频,并且假设每个单词独立于其他单词出现,这是不切实际的假设。这是一个显着的简化,因为在自然语言中,上下文和含义通常在很大程度上取决于词序和词之间的关系。例如,“not good”和“good”在 BoW 模型中被视为相同的两个单词,即使由于“not”的存在而导致它们的含义相反。

为了解决这些限制,开发了更先进的技术。其中包括诸如词嵌入(或嵌入)之类的模型,它们通过考虑单词出现的上下文来捕获更多语义信息。

什么是嵌入(Embedding)?

由神经网络创建的具有大量维度的向量,这些向量是通过预测每个单词的相邻单词可能是什么来创建的。

下面是使用 200 个维度的 Word2Vec 模型生成的嵌入的可视化。您可以使用 Tensorflow Projector 进行模拟.

这个想法是将这些嵌入保存到数据库中以便快速检索。

什么是矢量索引与矢量数据库?

“索引”是一种提高数据库表数据检索操作速度的数据结构。

矢量索引是一种用于根据矢量内容有效地组织和检索矢量的机制。

矢量数据库是一种专门为高效处理和存储矢量数据而设计的数据库。它是一个数据库,包含旨在管理矢量数据的功能,包括存储、检索和查询处理。它可以利用向量索引作为其高效面向向量操作策略的一部分。

什么是 pg_vector?

Postgres 的开源矢量相似性搜索。如果您现在拥有或使用 Postgres,则可以安装 pg_vector 扩展以向 Postgres 添加矢量数据库功能。转到项目GitHub - pgvector/pgvector: Open-source vector similarity search for Postgres以获取安装说明。

pg_vector 入门

要在 Postgres 中启用它,只需执行以下命令:

CREATE EXTENSION IF NOT EXISTS vector;

接下来,创建一个表来保存嵌入向量。在此示例中,我们将把图像转换为嵌入向量并将它们存储在 Postgres 的图像表中。

DROP TABLE IF EXISTS images;
CREATE TABLE images (
    id bigserial PRIMARY KEY,
    path varchar(64),
    embedding vector(512)
)

请注意,有一个embedding列,它有 512 个维度。

现在,我们可以添加向量索引。

添加向量索引

pg_vector 有两个向量索引:HNSW 和 IVFFLAT。下面的示例使用 HNSW。

CREATE INDEX ON images USING hnsw (embedding vector_l2_ops);

向向量列添加索引时,必须提供距离算法。 pg_vector 带有三种不同的距离算法:

  • L2距离(欧氏距离)

  • Inner product 内积

  • Cosine distance 余弦距离

距离算法决定点周围的半径。半径内的任何记录都被视为在该距离内。

这将有助于有效地在图像表中找到相似的嵌入向量。

现在我们有一个表,其中包含用索引定义的embedding列,我们如何将图像转换为嵌入以将其插入到images表中?

Embeddings Model

为了将图像转换为嵌入,我们将使用 CLIP 模型(由 Hugging Face 提供)和 Python psycopg 连接 Postgres数据库。

import psycopg
from sentence_transformers import SentenceTransformer
from PIL import Image

image_path = './my_image.png'
model = SentenceTransformer('clip-ViT-B-32')
img_emb = model.encode(Image.open(image_path))

conn = psycopg.connect(dbname="postgres", autocommit=True)
cur.execute('INSERT INTO images (embedding, path) VALUES (%s,%s)', (img_emb.tolist(), image_path))

请注意,我们已在表中添加了一个path列。重要的是要知道embedding不包含图像本身,因此一旦找到相似的记录,我们需要一种方法来查找图像。这在本文后面将变得更加重要。

相似性搜索

下面的 Python 代码执行以下操作:

  • 让用户描述她想要查看的图像。

  • 将用户描述转换为embedding。

  • 对embedding描述的图像表执行 select 语句并返回结果。

  • 显示找到的图像以及与描述embedding的距离。

from matplotlib import pyplot as plt
from matplotlib import image as mpimg

query_string = input("What image to you want to see:")
text_emb = model.encode(query_string)

cur = conn.cursor()
cur.execute("""
    SELECT id, path, embedding <-> %s AS distance
    FROM images ORDER BY embedding::vector(512) <-> %s
    """,
    (str(text_emb.tolist()),str(text_emb.tolist())))

rows = cur.fetchall()
path = rows[0][1]
distance = rows[0][2]

plt.title(f'{path} {distance}')
image = mpimg.imread(path)
plt.imshow(image)
plt.show()

换句话说,假设此应用程序询问您想要查看什么图像,然后您输入:

“a white bike in front of a red brick wall”

矢量数据库返回如下图像:

总之:

  • 拍摄图像 → 使用 CLIP 模型从图像生成嵌入 → 将它们插入到 启用pg_vector的 Postgres 中。

  • 获取图像的描述(文本)→ 使用 SAME CLIP 模型从文本生成embedding。

  • 使用 SQL 生成 select 语句,并使用文本嵌入在图像表中搜索相似的embedding。

我们正在比较图像嵌入和文本嵌入!!!!!!

pg_vector 进行相似性搜索以查找与图像描述最相似的图像path。

原文地址

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐