前一篇文章博主主要写了如何安装pgvector和timescaledb插件,那么由此引申开来,其对应的流数据和向量数据的作用是什么?这篇文章主要是博主对于结合了pgvector的embedding的一些用法思考。
其实原本主播认为向量数据就是模型的本身的参数结构特征,但是经过研究和尝试后发现并不是这样的。这里所谓的向量数据,其实是经过encoding之后的“码”,说的直白一些,万物都可为向量,只要确定了一个函数,将现实的物品的某些特征与实数映射得到的结果便是向量,而我们平常接触的向量的模式其实大部分都是经过模型转化来的。比如说用模型将图片转为向量,或是将一句中文转为向量等,那为什么要转为向量呢?答案十分明显,因为转为向量之后便是一串数字,便可以进行运算,比较。而原始的形式不足以实现这些功能,这便是向量的巨大优势。
而pgvector的特点就是可以进行相似度查询,可以找到和输入向量最相似的已存储的向量,那么其实这个作用就非常的明显:找最近->匹配最佳->最优解。
那主播也是想举个例子说明,最为典型的一个例子就是最佳词义匹配。什么意思呢?比如说:apple 这个词只有苹果的意思么?显然不是,他可以指苹果手机(重点是手机而不是苹果),苹果电脑,或是引申为宝贝(就是类似于honey,baby)的意思,在语句中同一个词代表的意思是不一样的,那么由此我输入一句话也含有apple这个词,可不可以通过向量比对来找到和这个apple意思最相近的那句话呢?
ok主播也是通过在B站上面了解了一下并进行了一个实践,我准备了以下语句:
# 示例文本
TEXTS = [
"i have an apple to eat",
"this is an apple computer",
"the apple is delicious",
"i need to find my apple phone",
"she is the apple of their eye",
"an apple a day keeps doctor away",
"you buy a new apple ! i think it is cool to use it"
]
很显然1,3,6是指吃的苹果,2,4,7指的是电子产品,5指的是宝贝,那么主播就找了一个将语句转为向量的模型,用的是 SentenceTransformers 框架下的 all-MiniLM-L6-v2 模型,将输入的文本编码成384维的语义向量(embedding)。那么之后就是这样的在数据库里面:
好,那么之后就可以用代码模拟输入一句话,通过这个模型输出384维度的向量然后进行比对得到最相似意思是向量:
def search_similar(conn, model, query_text, top_k=1):
"""查询相似文本"""
query_embedding = model.encode(query_text).tolist()
with conn.cursor() as cursor:
# 使用 1 - (<=>) 将余弦距离转换为相似度(0-1范围,越大越相似)
cursor.execute(
sql.SQL("""
SELECT text, 1 - (embedding <=> %s::vector(384)) AS similarity
FROM text_embeddings
ORDER BY similarity DESC
LIMIT %s;
"""),
(query_embedding, top_k)
)
results = cursor.fetchall()
return results
那么最后可以展示一下得到的结果:
基本上来讲就是词义匹配的还是不错的。如果对于机器学习有了解过的UU们肯定是不难看出,本质上来讲向量的相似度查询就是一个KNN的方法,那么其实KNN所适用的情况下向量相似度查询也是非常OK的。那么我们就可以引申开去:所谓的向量的作用?可以是对于某些指标的评判(类比于k近邻分类)?或者是聚类?这是横向的展开思考。从纵向而言,他不局限于文字匹配,是否可以跨种类匹配?比如声音与文字?图像与文字?地理信息与文字?从宽来说,任意一样东西只要能用向量表示就可以进行比对,当然由于数据量和维度的限制,需要考虑维数灾难,数据量太大等问题,这便需要引入降维等思想。