2017-02-18 8 views
0

Предположим, у вас есть таблица в базе данных, построенной следующим образом:SQL Вычисление косинуса подобии

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 

Заметим, что так как векторы сохраняются в базы данных, нам нужно хранить только ненулевые записи. В этом примере мы имеем только два вектора $ v_ {99} = (4,3,4,0) $ и $ v_ {1234} = (0,5,2,3) $ как в $ \ mathbb {R}^4 $.

Косинус подобия этих векторов должен быть $ \ displaystyle \ frac {23} {\ sqrt {41 \ cdot 38}} = 0.5826987807288609 $.

Как вы вычисляете сходство с косинусом, используя почти только SQL?

Я говорю почти, потому что вы будете нуждаться в функции sqrt, не всегда при условии в основных SQL реализаций, например, оно не в sqlite3!

ответ

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 

 Смежные вопросы

  • Нет связанных вопросов^_^