自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

500行SQL快速實(shí)現(xiàn)UCF

開(kāi)發(fā) 前端
UCF通常是User-base Collaborative Filter的簡(jiǎn)寫;大體的算法思路是根據(jù)用戶行為計(jì)算相似群體(鄰居),為用戶推薦其鄰居喜好的內(nèi)容;感覺(jué)是不是很簡(jiǎn)單、那廢話不多說(shuō)先擼個(gè)SQL。

[[381092]]

寫在前面話

UCF通常是User-base Collaborative Filter的簡(jiǎn)寫;大體的算法思路是根據(jù)用戶行為計(jì)算相似群體(鄰居),為用戶推薦其鄰居喜好的內(nèi)容;感覺(jué)是不是很簡(jiǎn)單、那廢話不多說(shuō)先擼個(gè)SQL。

SQL

  1. select uid1,uid2,sim 
  2. from ( 
  3.     select uid1 
  4.         ,uid2 
  5.         ,cnt12 / sqrt(cnt1*cnt2) sim 
  6.         ,row_number() over(partition by uid1 order by cnt12 / sqrt(cnt1*cnt2) desc) sim_rn 
  7.     from ( 
  8.         select a.uid uid1 
  9.             ,b.uid uid2 
  10.             ,count(a.iid) cnt12  
  11.         from tb_behavior a 
  12.         join tb_behavior b 
  13.         on a.iid = b.iid 
  14.         where a.uid <> b.uid 
  15.         group by a.uid,b.uid 
  16.     ) a12 
  17.     join (select uid,count(iid) cnt1 from tb_behavior group by uid) a1 
  18.     on a12.uid1 = a1.uid 
  19.     join (select uid,count(iid) cnt2 from tb_behavior group by uid) a2 
  20.     on a12.uid1 = a2.uid 
  21. ) tb_neighbour 
  22. where sim > 0.1 and sim_rn <= 30 

讀者實(shí)現(xiàn)的話只需要把上面的tb_behavior表替換成自己業(yè)務(wù)的用戶行為即可;iid,uid分別對(duì)應(yīng)物品id和用戶id;

根據(jù)共現(xiàn)相似度,即共同喜好的物品個(gè)數(shù)比上各自喜好物品總數(shù)乘積取平方;最后截?cái)嘤脩糇钕嗨频那?0個(gè)鄰居作為推薦的依據(jù)。

上面構(gòu)造了鄰居表,下面就是根據(jù)鄰居的喜好為用戶推薦了,具體sql如下:

  1. select uid1,iid 
  2. from ( 
  3.     select uid1 
  4.         ,iid 
  5.         ,max(sim) score 
  6.         ,row_number() over(partition by uid1 order by max(sim) desc) user_rn 
  7.     from tb_neighbour a12 
  8.     join (select uid,iid from tb_behavior) a2 
  9.     on a12.uid2 = a2.uid 
  10.     join (select uid,collect_set(iid) iids1 from tb_behavior group by uid) a1 
  11.     on a12.uid1 = a1.uid 
  12.     where not array_contaions(iids1,a2.iid) 
  13.     group by uid1,iid 
  14. ) tb_rec 
  15. where user_rn <= 500 

這里說(shuō)明下包括上面的top30鄰居和用戶top500的最大推薦列表都是工程優(yōu)化,截?cái)喙?jié)約些存儲(chǔ);具體讀者可以根據(jù)自己業(yè)務(wù)需要進(jìn)行設(shè)置;

然后大概說(shuō)下各個(gè)表的含義:a1表是用戶已消費(fèi)過(guò)的物品,a2表是用戶每個(gè)鄰居喜好的物品;那么也就是說(shuō)從鄰居喜好的物品中過(guò)濾掉已經(jīng)消費(fèi)的

物品整體根據(jù)共現(xiàn)相似度進(jìn)行排序。

思考

但思路很簡(jiǎn)單、實(shí)際作者開(kāi)發(fā)中總會(huì)遇到各種各樣的問(wèn)題,下面就撿幾個(gè)主要的和大家一起討論下:

  • 1.join引起的數(shù)據(jù)傾斜問(wèn)題:tb_neighbour表很大,往往熱點(diǎn)物品會(huì)占據(jù)80%的曝光和消費(fèi)記錄,如何解決?
  • 2.增量更新問(wèn)題:上面的框架,tb_behavior表每次都是全量計(jì)算,是否能改造成增量更新鄰居表和推薦結(jié)果,并減少計(jì)算時(shí)間呢?

join引起的數(shù)據(jù)傾斜問(wèn)題

先思考問(wèn)題1,既然我們目的是求相似鄰居,物品join只是為了關(guān)聯(lián)上一組用戶對(duì),那自然的想法是可以根據(jù)feed做近似采樣、相似度精度也幾乎無(wú)損失。

下面我試著實(shí)現(xiàn)下這種思路:

  1. with tb_behavior_sample as ( 
  2.     select uid,iid  
  3.     from ( 
  4.         select uid 
  5.             ,iid 
  6.             ,row_number() over(partition by iid order by rand()) feed_rn 
  7.         from tb_behavior 
  8.     ) bh 
  9.     where feed_rn <= 50000 
  10. )  
  11.  
  12. select uid1,uid2,sim 
  13. from ( 
  14.     select uid1 
  15.         ,uid2 
  16.         ,cnt12 / sqrt(cnt1*cnt2) sim 
  17.         ,row_number() over(partition by uid1 order by cnt12 / sqrt(cnt1*cnt2) desc) sim_rn 
  18.     from ( 
  19.         select a.uid uid1 
  20.             ,b.uid uid2 
  21.             ,count(a.iid) cnt12  
  22.         from tb_behavior_sample a 
  23.         join tb_behavior_sample b 
  24.         on a.iid = b.iid 
  25.         where a.uid <> b.uid 
  26.         group by a.uid,b.uid 
  27.     ) a12 
  28.     join (select uid,count(iid) cnt1 from tb_behavior group by uid) a1 
  29.     on a12.uid1 = a1.uid 
  30.     join (select uid,count(iid) cnt2 from tb_behavior group by uid) a2 
  31.     on a12.uid1 = a2.uid 
  32. ) tb_neighbour 
  33. where sim > 0.1 and sim_rn <= 30 

這里用了hive的with as語(yǔ)法,讀者可自行查閱,篇幅有限,就不展開(kāi)了;feed_rn就是隨機(jī)采樣了50000條,實(shí)際操作時(shí)讀者可以先統(tǒng)計(jì)下item的分布、大概找到一個(gè)閾值;

比如取top10的item的出現(xiàn)次數(shù)作為閾值;那計(jì)算相似度時(shí)分子最多減小10,分母不變。這對(duì)大多數(shù)情況精度應(yīng)該足夠了,而且因?yàn)楸苊饬藬?shù)據(jù)傾斜,大大降低了計(jì)算時(shí)間。

增量更新問(wèn)題

問(wèn)題2是一個(gè)工程問(wèn)題,lambda架構(gòu)能使初始結(jié)果效果不錯(cuò),可直接上線灰度了;在此基礎(chǔ)上再加小時(shí)或者天增量;kappa架構(gòu)相對(duì)就比較繁瑣、需要一開(kāi)始就設(shè)計(jì)增量流程。

精度方面也需要一定的累積;不過(guò)如何選擇,讀者可以根據(jù)自己的數(shù)據(jù)量和熟悉程度自行選擇;作者這里僅以kappa架構(gòu)說(shuō)明。

重新review上面sql,我們發(fā)現(xiàn)我們僅需要記錄下cnt12,cnt1,cnt2,iids1這些計(jì)算關(guān)鍵即可,其中iids2是用戶鄰居喜好的物品數(shù)組;數(shù)值類型可累加更新、

數(shù)組類型合并起來(lái)比較麻煩,一種解決方案是注冊(cè)UDF;這里采取另一種這種的方案:把iids1合并成字符串,過(guò)濾的時(shí)候再分割為字符串?dāng)?shù)組。

  1. with tb_behavior_sample_incr as ( 
  2.     select uid,iid  
  3.     from ( 
  4.         select uid 
  5.             ,iid 
  6.             ,row_number() over(partition by iid order by rand()) feed_rn 
  7.         from tb_behavior_incr 
  8.     ) bh 
  9.     where feed_rn <= 50000 
  10. )  
  11.  
  12. insert overwrite table tb_neighbour 
  13. select uid1,uid2,sim 
  14. from ( 
  15.     select uid1 
  16.         ,uid2 
  17.         ,sum(cnt12) / sqrt(sum(cnt1)*sum(cnt2)) sim 
  18.         ,row_number() over(partition by uid1 order by sum(cnt12) / sqrt(sum(cnt1)*sum(cnt2)) desc) sim_rn 
  19.     from ( 
  20.         select uid1,uid2,cnt12,cnt1,cnt2 
  21.         from tb_neighbour 
  22.         union all 
  23.         select a.uid uid1 
  24.             ,b.uid uid2 
  25.             ,count(a.iid) cnt12  
  26.             ,cnt1 
  27.             ,cnt2 
  28.         from tb_behavior_sample_incr a 
  29.         join tb_behavior_sample_incr b 
  30.         on a.iid = b.iid 
  31.         where a.uid <> b.uid 
  32.         group by a.uid,b.uid  
  33.     ) a12 
  34.     join (select uid,count(iid) cnt1 from tb_behavior_incr group by uid) a1 
  35.     on a12.uid1 = a1.uid 
  36.     join (select uid,count(iid) cnt2 from tb_behavior_incr group by uid) a2 
  37.     on a12.uid1 = a2.uid 
  38.     group by uid1,uid2 
  39. ) tb_neighbour 
  40. where sim > 0.1 and sim_rn <= 30 

其中tb_behavior_sample_incr,tb_behavior_incr是相應(yīng)tb_behavior_sample,tb_behavior的增量表;使用union all和group by聚合相同用戶對(duì)的結(jié)果

kappa架構(gòu)初次計(jì)算即是增量,不斷累積每次增量的結(jié)果更新tb_neighbour;相當(dāng)于lambda初始全量計(jì)算的一種回放,直至追到最新的時(shí)間分區(qū)。

  1. insert overwrite table tb_user_consume 
  2. select uid,substring_index(concat_ws(",",collect_list(iids1)),",",10000) iids1  
  3. from ( 
  4.     select uid,concat_ws(",",collect_set(cast(iid as string))) iids1 
  5.     from tb_behavior_incr 
  6.     union all 
  7.     select uid,iids1 
  8.     from tb_user_consume 
  9. ) a 
  10. group by uid 
  11.  
  12. select uid1,iid 
  13. from ( 
  14.     select uid1 
  15.         ,iid 
  16.         ,max(sim) score 
  17.         ,row_number() over(partition by uid1 order by max(sim) desc) user_rn 
  18.     from tb_neighbour a12 
  19.     join (select uid,cast(iid as string) iid from tb_behavior_incr) a2 
  20.     on a12.uid2 = a2.uid 
  21.     join (select uid,split(iids1,",") iids1 from tb_user_consume) a1 
  22.     on a12.uid1 = a1.uid 
  23.     where not array_contaions(iids1,a2.iid) 
  24.     group by uid1,iid 
  25. ) tb_rec 
  26. where user_rn <= 500 

使用tb_user_consume緩存用戶最近消費(fèi)的前10000條記錄,將用戶鄰居最新喜好物品推薦給用戶。

寫在后面的話

呼!終于寫完了;雖然說(shuō)有了上面這一套操作,UCF推薦基本完成;但有沒(méi)有更好的方式呢?我想應(yīng)該就是embedding大法了吧;比如item2vec對(duì)用戶聚類,根據(jù)聚類

推薦;再或者根據(jù)好友關(guān)系,推薦好友喜好的物品。前者表征更細(xì)致,值得一說(shuō)的是其也有負(fù)采樣策略和checkpoint增量更新;后者好友信任度更高,解釋性更強(qiáng)。

責(zé)任編輯:張燕妮 來(lái)源: 博客園
相關(guān)推薦

2021-06-28 16:05:19

數(shù)據(jù)庫(kù)代碼技術(shù)

2009-09-14 13:17:51

LINQ to SQLLINQ to SQL

2021-06-30 13:45:49

SQL數(shù)據(jù)庫(kù)LSM

2022-10-28 10:18:53

代碼績(jī)效Java

2021-12-16 22:59:21

SQL報(bào)表應(yīng)用

2019-10-17 21:37:28

微信飛機(jī)大戰(zhàn)Python

2014-05-15 09:45:58

Python解析器

2010-11-16 16:02:08

曙光天河星云

2011-05-16 09:15:22

SQL語(yǔ)言

2011-05-16 09:22:28

SQL語(yǔ)言

2022-08-19 07:13:45

SQL方法編程

2009-11-17 09:47:54

Oracle SQL語(yǔ)

2010-09-01 15:30:24

SQL刪除

2019-06-03 08:52:39

打卡考勤數(shù)據(jù)庫(kù)

2011-11-30 09:46:32

超算TOP500超級(jí)計(jì)算機(jī)

2010-05-19 16:45:59

信息安全網(wǎng)絡(luò)安全管理任子行網(wǎng)絡(luò)

2020-05-21 14:50:48

代碼機(jī)器學(xué)習(xí)圖像

2010-09-01 17:19:49

SQL刪除TABLE

2024-10-16 21:17:59

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)