<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【推薦系統(tǒng)】手寫ItemCF/UserCF代碼,你會嗎?

          共 3655字,需瀏覽 8分鐘

           ·

          2021-02-02 20:49

          前言

          之前朋友說有同學(xué)在面字節(jié)算法實(shí)習(xí)時讓復(fù)現(xiàn)DeepFM算法(包括訓(xùn)練),然后就懵了。因此最近在整理傳統(tǒng)推薦算法的一些內(nèi)容時,大概是這樣的:

          就想到「基于鄰域的協(xié)同過濾(UserCF與ItemCF),除了了解原理、應(yīng)用場景的區(qū)別外,如果現(xiàn)場寫實(shí)現(xiàn)偽代碼你會么?」 有很多文章在講協(xié)同過濾的原理,很少具體到代碼,所以這次把以前寫的CF代碼優(yōu)化下進(jìn)行分享。
          本文約1.7k字,預(yù)計(jì)閱讀5分鐘.

          概要

          協(xié)同過濾是「基于用戶行為」設(shè)計(jì)的推薦算法,具體來說,是「通過群體的行為來找到某種相似性」(用戶之間的相似性或者物品之間的相似性),通過相似性來為用戶做決策和推薦。當(dāng)然,協(xié)同過濾有基于鄰域的、隱語義模型等,這里我們主要指的是基于鄰域的ItemCF和UserCF。具體的原理就不多做解釋了,見下圖:

          ItemCF與UserCF的代碼其實(shí)很相近,因此以ItemCF為例,兩個算法的具體代碼可以在github:https://github.com/ZiyaoGeng/SimpleCF(閱讀原文)中找到。

          ItemCF

          對于ItemCF算法的實(shí)踐,我采用類的方式進(jìn)行建立,主要內(nèi)容包括:

          1. 模型的輸入;
          2. 初始化【計(jì)算相似度矩陣】;
          3. 對單個用戶進(jìn)行推薦;
          4. 對測試集的所有內(nèi)容進(jìn)行推薦;

          因此大體框架為:

          class ItemCF:
          def __init__(self, user_item_dict, item_hot_list, sim_item_topK, topN, i2i_sim=None):
          """
          Item-based collaborative filtering
          :param user_item_dict: A dict. {user1: [(item1, score),...], user2: ...}
          :param item_hot_list: A list. The popular movies list.
          :param sim_item_topK: A scalar. Choose topK items for calculate.
          :param topN: A scalar. The number of recommender list.
          :param i2i_sim: dict. If None, the model should calculate similarity matrix.
          """

          def __get_item_sim(self):
          """
          calculate item similarity weight matrix
          :return: i2i_sim
          """

          def recommend(self, user_id):

          def recommend_all(self, test):

          輸入

          • user_item_dict:首先最重要的是建立user-item共現(xiàn)矩陣作為「輸入」,當(dāng)然在實(shí)際應(yīng)用中,我們采用字典的形式減少不必要的空間。對于ItemCF,需要user-item-dict字典,而對于UserCF,需要user-item-dictitem-user-dict兩個字典:

            item-user-dict:
            user-item-dict:

            【注】元組部分score可以去除或者替換為其他內(nèi)容;


          • item_hot_list:熱門物品的列表,主要是當(dāng)推薦物品數(shù)量不夠時(冷啟動等),用熱門物品進(jìn)行填充,計(jì)算也比較簡單;

          • sim_item_topK:選取某個物品最相似的TopK個物品,不然選擇所有物品會產(chǎn)生很大的計(jì)算量;

          • topN:推薦列表的大?。?/p>

          • i2i_sim:物品相似度矩陣。一般計(jì)算相似度矩陣后會在本地進(jìn)行保存,因此如果之前計(jì)算過,則只需讀取,不用重復(fù)計(jì)算;

          物品相似度矩陣

          ItemCF算法認(rèn)為「物品A和物品B具有很大的相似度是因?yàn)橄矚g物品A的用戶也大多喜歡物品B」,因此需要計(jì)算物品相似度矩陣,主要分為兩步:

          1. 統(tǒng)計(jì)兩兩物品之間的共現(xiàn)次數(shù),即「用戶同時喜歡兩個物品」;
          2. 通過Jaccard距離、余弦相似度等方式計(jì)算兩個物品的相似性;

          當(dāng)然對于1來說,需要對于活躍的用戶進(jìn)行懲罰,通過增加IUF(Inverse User Frequence),用戶活躍度對數(shù)倒數(shù)的參數(shù),對應(yīng)代碼中:

          i2i_sim[i][j]?+=?1?/?math.log(len(items)?+?1)

          在2中,通過余弦相似度的計(jì)算可以降低熱門物品會和很多物品相似的可能性,因?yàn)榛谖锲返耐扑]主要是挖掘長尾信息。

          i2i_sim[i][j]?=?wij?/?math.sqrt(item_cnt[i]?*?item_cnt[j])?

          具體代碼如下:

          ????def?__get_item_sim(self):
          ????????"""
          ????????calculate?item?similarity?weight?matrix
          ????????:return:?i2i_sim
          ????????"""

          ????????i2i_sim?=?dict()
          ????????item_cnt?=?defaultdict(int)??#?Count?the?number?of?visits?to?the?item
          ????????for?user,?items?in?tqdm(self.user_item_dict.items()):
          ????????????for?i,?score_i?in?items:
          ????????????????item_cnt[i]?+=?1
          ????????????????i2i_sim.setdefault(i,?{})
          ????????????????for?j,?score_j?in?items:
          ????????????????????if?i?==?j:
          ????????????????????????continue
          ????????????????????i2i_sim[i].setdefault(j,?0)
          ????????????????????i2i_sim[i][j]?+=?1?/?math.log(len(items)?+?1)??
          ????????for?i,?related_items?in?i2i_sim.items():
          ????????????for?j,?wij?in?related_items.items():
          ????????????????i2i_sim[i][j]?=?wij?/?math.sqrt(item_cnt[i]?*?item_cnt[j])??
          ????????return?i2i_sim

          推薦

          使用之前計(jì)算的相似度矩陣對每個用戶進(jìn)行推薦。主要分為兩步:

          1. 獲取推薦用戶的歷史行為,在相似度矩陣中選取每個歷史物品(遍歷)最相似的topk個物品來計(jì)算每個物品(未出現(xiàn)在歷史行為中)的「累積權(quán)重」
          2. 若1中所有物品數(shù)量小于推薦列表,則采用其他策略進(jìn)行填充,如選擇熱門物品,但權(quán)重分?jǐn)?shù)是最小的,可以為負(fù)數(shù)。然后對權(quán)重列表進(jìn)行排序,選取權(quán)重分?jǐn)?shù)最高的TopN個物品;

          具體代碼如下:

          ????def?recommend(self,?user_id):
          ????????"""
          ????????recommend?one?user
          ????????:param?user_id:?user's?ID
          ????????:return:
          ????????"""

          ????????item_rank?=?dict()
          ????????user_hist_items?=?self.user_item_dict[user_id]
          ????????for?i,?score_i?in?user_hist_items:
          ????????????for?j,?wij?in?sorted(self.i2i_sim[i].items(),?key=lambda?x:?x[1],?reverse=True)[:self.sim_item_topK]:
          ????????????????if?j?in?user_hist_items:
          ????????????????????continue

          ????????????????item_rank.setdefault(j,?0)
          ????????????????item_rank[j]?+=?1?*?wij

          ????????if?len(item_rank)?????????????for?i,?item?in?enumerate(self.item_hot_list):
          ????????????????if?item?in?item_rank:
          ????????????????????continue
          ????????????????item_rank[item]?=?-?i?-?1??#?rank?score?
          ????????????????if?len(item_rank)?==?self.topN:
          ????????????????????break
          ????????item_rank?=?sorted(item_rank.items(),?key=lambda?x:?x[1],?reverse=True)[:self.topN]

          ????????return?[i?for?i,?score?in?item_rank]

          【注】在計(jì)算每個物品的權(quán)重時,選擇了1 * wij,并沒有用到分?jǐn)?shù)和其他信息。

          評估

          「數(shù)據(jù)集」:ml-1m,當(dāng)然也可以選擇其它。預(yù)處理主要包括:

          1. 選擇評分大于x的作為正樣本(當(dāng)然可以直接將所有交互過的物品都作為正樣本,將評分融入推薦時權(quán)重分?jǐn)?shù)的計(jì)算);
          2. 選取每個用戶的最后一次發(fā)生交互的物品作為測試集(所以評估的結(jié)果會比項(xiàng)亮《推薦系統(tǒng)實(shí)戰(zhàn)》的結(jié)果差很多);
          3. 建立user-itemitem-user字典;

          「評估指標(biāo)」

          HR(點(diǎn)擊率)與NDCG,當(dāng)每個用戶真實(shí)的交互物品只有一個時,HR等價于Recall;

          評估代碼如下:

          def?evaluate_model(model,?test):
          ????"""
          ????evaluate?model
          ????:param?model:?model?of?CF
          ????:param?test:?dict.
          ????:return:?hit?rate,?ndcg
          ????"""

          ????hit,?ndcg?=?0,?0
          ????for?user_id,?item_id?in?tqdm(test.items()):
          ????????item_rank?=?model.recommend(user_id)
          ????????if?item_id?in?item_rank:
          ????????????hit?+=?1
          ????????????ndcg?+=?1?/?np.log2(item_rank.index(item_id)?+?2)
          ????return?hit?/?len(test),?ndcg?/?len(test)

          實(shí)驗(yàn)

          對于ItemCF算法,超參數(shù):

          • sim_item_topK = 20;
          • topN = 20;

          使用自己的筆記本,結(jié)果如下:

          數(shù)據(jù)讀?。?s;

          模型建立(計(jì)算相似度矩陣):3min52s;

          模型評估:19min47s,HR = 0.065232, NDCG = 0.024265;

          總結(jié)

          之前參考《推薦算法實(shí)踐》進(jìn)行過復(fù)現(xiàn),然后這次結(jié)合了Datawhale中新聞推薦的Baseline進(jìn)行優(yōu)化,確實(shí)對算法中如何懲罰熱門物品與活躍用戶有了更深的認(rèn)識。所有代碼在github “https://github.com/ZiyaoGeng/SimpleCF”中,如果存在一些Bug或者更好的優(yōu)化(評估時間太長),歡迎提出Issues。

          往期精彩回顧





          本站知識星球“黃博的機(jī)器學(xué)習(xí)圈子”(92416895)

          本站qq群704220115。

          加入微信群請掃碼:


          瀏覽 48
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费观看欧美成人网站 | 国产一级电影在线看 | 女人在线视频 | 国产又爽 又黄 A片 | 亚洲一区欧美国产日韩 云播 |