python-3.x - 余弦相似度很慢
问题描述
我有一组句子,使用句子编码器将其编码为向量,我想找出与传入查询最相似的句子。
搜索功能如下所示:
def semantic_search(cleaned_query, data, vectors):
query_vec = get_features(cleaned_query)[0].ravel()
res = []
for i, d in enumerate(data):
qvec = vectors[i].ravel()
sim = cosine_similarity(query_vec, qvec)
if sim > 0.5:
res.append((format(sim * 100, '.2f'), data[i]))
return sorted(res, key=lambda x: x[0], reverse=True)[:15]
其中cleaned_query
是一个字符串形式的预处理查询,data
是一个包含所有句子(总共 300 个)的列表,并且vectors
包含维度 (300,500) 的数据中每个句子的编码向量。
当我向我的服务发送查询时,处理一个查询大约需要 10-12 秒,我认为这太慢了。我做了一些调试,意识到问题出在cosine_similarity
功能上,实现如下:
import numpy as np
def cosine_similarity(v1, v2):
mag1 = np.linalg.norm(v1)
mag2 = np.linalg.norm(v2)
if (not mag1) or (not mag2):
return 0
return np.dot(v1, v2) / (mag1 * mag2)
我试图研究不同的实现,并发现一些使用 numba - 运行得非常快nb_cosine
,但它提供的结果并不好,这意味着cosine_similarity
上面的 提供了更正确和更有意义的结果。这是使用 numba 的实现:
import numba as nb
import numpy as np
@nb.jit(nopython=True, fastmath=True)
def nb_cosine(x, y):
xx,yy,xy=0.0,0.0,0.0
for i in range(len(x)):
xx+=x[i]*x[i]
yy+=y[i]*y[i]
xy+=x[i]*y[i]
return 1.0-xy/np.sqrt(xx*yy)
任何人都可以建议,我怎样才能优化我的cosine_similarity
功能以更快地工作?300 句话总是一样的。以防万一,如果需要,下面是get_features
函数:
def get_features(texts):
if type(texts) is str:
texts = [texts]
with tf.Session(graph=graph) as sess:
sess.run([tf.global_variables_initializer(), tf.tables_initializer()])
return sess.run(embed(texts))
解决方案
我不确定您是否在那里正确计算余弦相似度;你可能想检查你得到的一些值并确保它们有意义。
无论如何,加快速度的一种方法是预先计算并存储 300 个句子的每个向量的大小,并预先计算query_vec
. 就像现在的代码一样,您在每次调用时重新计算每个句子的量级,并计算query_vec
300 次的量级。
推荐阅读
- java - JPA - 插入后的 PK 属性问题
- sql - 在控制台上出现以下错误“150”外键约束格式不正确“”
- android - Glide 没有将“joeschmoe”头像加载到 ImageView 中
- git - Git 有一些很重的文件,我想清理一下
- python - 如何使用 python selenium 点击第一个谷歌搜索结果?
- java - gson : 将空字符串视为 null
- javascript - JS函数设置addEventListeners太多
- swift - 如何在 swift mac 应用程序中订阅全局触控板触摸事件?
- python - python中的变量扩展可以像变量的shell扩展一样工作吗
- django - 带有多个外键表单的页面