在人工智能迅猛发展和数据量不断膨胀的当下,传统数据库在面对高维度和大规模的数据处理时早已力不从心。为应对这一挑战,拓数派团队凭借在分布式数据库领域的深厚积累,打造了云原生向量数据库 PieCloudVector。本系列将分为三篇,分别以图片、音频、文本三种典型非结构化数据类型为例,为大家介绍 PieCloudVector 的应用。
拓数派旗下云原生向量数据库 PieCloudVector 采用了将业界成熟开源算法实现与自研的基于 postgres 内核的关系型数据库对接起来的技术路线,能够存储和管理原始数据的向量表示,同时支持精确查询与模糊查询功能,用户可以通过 Postgres 客户端进行高效的相似性搜索。
PieCloudVector 利用其分布式架构显著提升了向量计算的效率,并在此基础上提供了一整套上下游工具。在技术架构上,PieCloudVector 按照向量数据的实际应用流程划分为五个核心层级:原始数据存储、嵌入(Embedding)、索引构建、向量检索以及数据应用。这些层级分别对应于向量数据处理和分析过程中的不同应用场景,构成了一个完整的技术框架,如下图所示:
PieCloudVector 整体技术框架
本文为《PieCloudVector 进阶系列》的第一篇,将以图片数据为例,一步步展示如何使用 PieCloudVector 构建商品推荐系统,深入探讨数据向量化的关键步骤,包括 Embedding 计算、将向量写入数据库,以及相似性搜索。 (本文演示数据均来自 Hugging Face)
基于图片数据打造商品推荐系统
向量数据库在执行相似性查询任务中扮演着关键角色,以服装行业的应用场景为例,通过结合商品图片的向量表示与 K-最近邻(KNN)算法,PieCloudVector 能够帮助系统有效地在现有商品库中检索并推荐与目标商品相似的候选商品。整体框架如下图:
系统整体流程框架
接下来,本文将从「数据集准备」、「数据向量化处理」、「向量数据存储」以及「相似性搜索」四个关键环节,详细阐述利用 PieCloudVector 搭建商品推荐系统的整个流程。
1.数据集准备
首先,从 Hugging face 下载 fashion mnist 数据,该数据集包含了服装图片、类型等数据,详见 fashion_mnist[1]。
这里,我们选取训练集中前 1000 条数据作为演示数据。
from datasets import load_dataset
dataset = load_dataset("fashion_mnist", split="train[:1000]")
下载数据中包含以下信息:
print(dataset.features)
{'image': Image(decode=True, id=None),
'label': CtassLabel(names=['T - shirt / top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'],
id=None)}
2.数据向量化处理
接下来,对数据进行向量化处理,运用合适的模型将其转换为数值数组,从而生成能够代表原始数据特征的嵌入向量。
以第一条数据为例,目的是找到前 10 个与其相似的服装作为推荐商品,其对应的图片如下图所示,类型为 Ankle boot(短靴)。
调用 imgbeddings[2] 库将图片数据转换为向量,该库采用了以 OpenAI 的 CLIP 模型为基础的模型,轻量且计算速度快(在 CPU 计算的情况下),非常适合 fashion mnist 这样只展示商品、图片内容并不复杂的数据集。
import numpy as np
from imgbeddings import imgbeddings
ibed = imgbeddings()
以第一条数据为例,基于图片生成向量。
embedding_0 = ibed.to_embeddings(dataset['image'][0])
imgbeddings 会生成一个长度为 768 的向量,如下所示。
In: embedding_0.shape
(1, 768)
embedding [0]
array([-2.11191326e-01, 2.07909331e-01, -6.71815038e-01, -1.66335583e+00,
-1.57210135e+00, -5.19429862e-01, -8.80079985e-01, 2.29999766e-01,
1.67191553e+00, -9.89815831e-01, 6.54723167e-01, -2.75861591e-01,
5.89815438e-01, 2.61584610e-01, 8.86729777e-01, 5.67858696e-01,
4.75497782e-01, 3.40062588e-01, -4.25924629e-01, 8.74885023e-01,
-3.10492903e-01, 2.72458225e-01, -3.28680307e-01, -4.51324023e-02,
-6.83538735e-01, -2.32427925e-01, 5.95779240e-01, 5.50612807e-01,
7.26937175e-01, 6.75487295e-02, -7.40724325e-01, -2.07319453e-01,
1.37214720e-01, 1.55591702e+00, 1.24170937e-01, -3.53575408e-01,
-7.43186593e-01, 9.77323204e-02, 4.97219563e-02, 1.00773001e+00,
1.24602437e+00, -1.76177248e-01, 5.85671842e-01, -4.85404104e-01,
-5.25022328e-01, -1.84076607e-01, -4.65092547e-02, 7.65870810e-01,
1.27615702e+00, 7.38422930e-01, 2.59102374e-01, 5.86230934e-01,
-1.34280175e-01, -4.21402991e-01, 1.31635904e-01, 6.08720705e-02,
3.83820683e-01, 9.36180592e-01, 4.59356755e-02, 3.50226104e-01,
-5.04337013e-01, -5.55240333e-01, -7.46359229e-02, 3.54337037e-01,
-6.38039052e-01, 8.85763526e-01, -2.85562664e-01, 9.87186372e-01,
1.74211636-01, -4.21855748e-02, 2.725174430-01, -3.59927297e-01
...
然后,将除第一条数据以外的数据进行向量化处理。
embedding = ibed.to_embeddings(dataset['image'][1:])
3.向量数据存储
数据处理完毕后,下一步是将向量存储到数据库中。写入之前,我们需要先在数据库中为这些向量创建目标表。
需注意的是,在定义向量字段时,维度并不是必须的参数。如果给定了维度,那么后续写入的数据必须参照该维度,其他维度的向量则无法写入该表。若没有给定维度,一旦数据写入了表中,那么后续的向量维度必须与表中已存在的向量一致;但若将表中的数据清空,在没有给定维度的情况下,其他维度的向量也可写入该表,后续加入的数据须则参照新的维度,否则无法写入。无论哪种情况,表中若有向量字段,那么该字段中所有向量的维度都必须一致。
CREATE TABLE pictures (id bigserial PRIMARY KEY, embedding vector(768));
向量表创建完成后,将向量数据依次写入数据库中。
import psycopg2
conn = psycopg2.connect('postgresql://usr:pswd@192.138.***.***:5432/db')
cur = conn.cursor()
embedding_lst = embedding.tolist()
for i in range(len(embedding_lst)):
cur.execute('INSERT INTO pictures (embedding) values (%s)', (embedding_lst[i],))
conn.commit()
conn.close()
4.相似性搜索
写入完成后,即可利用 PieCloudVector 通过 K-最近邻(K-Nearest Neighbour, KNN)算法检索与目标向量最为相似的数据。目前,有三种不同的距离度量方法可供选择:L2 距离、内积(Inner Product)和余弦相似度(Cosine Similarity),可根据具体的应用场景、数据的特性以及对搜索结果精确度的要求,灵活选择最合适的距离计算算法。
在先前的步骤中已将目标数据(原数据集中第一条数据,一双短靴)进行向量化处理,这里可以直接通过 Python 向数据库发送 query 来查询最相似(与目标数据向量距离最近)的 10 个单品,使用的距离算法为 L2 Distance。
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('postgresql://usr:pswd@192.138.***.***:5432/db', echo=False)
img_id = pd.read_sql('select id from pictures where id != 1 order by embedding <-> ' + "'" + str(embedding_0.tolist()[0]) + "'" + ' limit 10',
con=engine)
找到这些单品后,可以调取它们的图片来展示相似查询的结果。
id_lst = img_id['id'].to_list()
for i in id_lst[:5]:
display(dataset['image'][i])
结果如下图:
此外,也可通过其他相似图片的服装类别来判断目标图片的类别,这样的信息也可作为辅助,对推荐结果进行优化。
def most_common(lst):
return max(set(lst), key=lst.count)
label = most_common([dataset['label'][i] for i in id_lst])
print(dataset.features["label"].int2str(label))
可以看到,最终的推荐结果为短靴,系统可以将靴子这一类的产品作为推荐提供给消费者。
dataset.features["label"].int2str(label)
'Ankle boot'
这就是如何使用 PieCloudVector 来构建一个基于图片数据的商品推荐系统的全部过程。通过向量化处理和相似性搜索,系统能够高效地找到与目标商品相似的推荐项,既提高了推荐的准确性,也增强了用户体验。在下篇文章中,我们将继续探索如何使用 PieCloudVector 来处理音频数据,实现音频内容识别。 欢迎关注!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。