Python使用字典计算向量余弦相似度结果异常问题排查
问题根源
代码的核心逻辑错误是计算点积前没有对齐两个字典对应的向量维度,直接提取values()转列表计算,完全忽略了字典键和向量维度的对应关系:
- Python 3.7+的字典虽然保留插入顺序,但测试用例里两个字典的键顺序、键集合都不一致:
dict_1键为a、b、c,直接取值得到[1,2,3];dict_2键为b、c、d,直接取值得到[4,5,6]。点积计算时错误将a维度值和b维度值相乘、b和c相乘、c和d相乘,维度完全错位。 - 两个字典的独有键(
dict_1的a、dict_2的d)没有按稀疏向量规则补0,进一步导致计算错误。
你得到的0.97就是错位点积的结果:错位点积值为1*4 + 2*5 +3*6 = 32,除以两个向量的范数乘积≈32.83,四舍五入就是0.97,和正确逻辑下的结果偏差很大。
正确计算逻辑下,两个向量只有b、c两个共有维度有非零值,点积为2*4 + 3*5 = 23,除以范数乘积后结果约为0.7,和预期一致。
修正后代码
import math from numpy import dot def norma(vec_dict): sqr_sum = 0.0 for x in vec_dict: sqr_sum += vec_dict[x] * vec_dict[x] return math.sqrt(sqr_sum) def cosine_similarity(dict_1, dict_2): # 取两个字典所有键的并集,统一维度顺序 all_keys = set(dict_1.keys()).union(set(dict_2.keys())) # 按统一键序取值,缺失键补0 List1 = [dict_1.get(k, 0) for k in all_keys] List2 = [dict_2.get(k, 0) for k in all_keys] similarity = dot(List1, List2) / (norma(dict_1) * norma(dict_2)) return round(similarity, 2) if __name__ == '__main__': print(cosine_similarity({"a": 1, "b": 2, "c": 3}, {"b": 4, "c": 5, "d": 6}))
运行上述代码输出结果为0.7,符合预期。
注:不要用dict作为函数参数名,会覆盖Python内置的字典类型,属于不好的编码习惯,修正版里已经将参数名改为vec_dict。
内容的提问来源于stack exchange,提问作者user18067246
相关产品推荐
相关产品推荐

