余弦相似度的 SQL 计算

Posted

技术标签:

【中文标题】余弦相似度的 SQL 计算【英文标题】:SQL Computation of Cosine Similarity 【发布时间】:2017-07-07 17:32:28 【问题描述】:

假设您在数据库中有一个表,构造如下:

create table data (v int, base int, w_td float);
insert into data values (99,1,4);
insert into data values (99,2,3);
insert into data values (99,3,4);
insert into data values (1234,2,5);
insert into data values (1234,3,2);    
insert into data values (1234,4,3);

要明确select * from data 应该输出:

v   |base|w_td
--------------
99  |1   |4.0
99  |2   |3.0
99  |3   |4.0
1234|2   |5.0
1234|3   |2.0
1234|4   |3.0

请注意,由于向量存储在数据库中,我们只需要存储非零条目。在这个例子中,我们在 $\mathbbR 中只有两个向量 $v_99 = (4,3,4,0)$ 和 $v_1234 = (0,5,2,3)$ ^4 美元。

这些向量的余弦相似度应该是 $\displaystyle \frac23\sqrt41 \cdot 38 = 0.5826987807288609$。

您如何几乎只使用SQL 来计算余弦相似度?

我说差不多是因为你需要sqrt 函数,基本的SQL 实现中并不总是提供它,例如它不在sqlite3 中!

【问题讨论】:

您实际上可以通过编译和使用数学扩展库在sqlite3中使用sqrt。详情请见here。 【参考方案1】:
with norms as (
    select v,
        sum(w_td * w_td) as w2
    from data
    group by v
)
select 
    x.v as ego,y.v as v,nx.w2 as x2, ny.w2 as y2,
    sum(x.w_td * y.w_td) as innerproduct,
    sum(x.w_td * y.w_td) / sqrt(nx.w2 * ny.w2) as cosinesimilarity
from data as x
join data as y
    on (x.base=y.base)
join norms as nx
    on (nx.v=x.v)
join norms as ny
    on (ny.v=y.v)
where x.v < y.v
group by 1,2,3,4
order by 6 desc

产量

ego|v   |x2  |y2  |innerproduct|cosinesimilarity
--------------------------------------------------
99 |1234|41.0|38.0|23.0        |0.5826987807288609

【讨论】:

以上是关于余弦相似度的 SQL 计算的主要内容,如果未能解决你的问题,请参考以下文章

余弦相似度计算

计算两个数组之间余弦相似度的正确方法?

在给定稀疏矩阵数据的情况下,Python 中计算余弦相似度的最快方法是啥?

SparkMLlib---基于余弦相似度的用户相似计算

余弦计算相似度理解以及计算

Spark笔记(1) :余弦相似度计算