協(xié)同過濾算法

1. 初識協(xié)同過濾

在推薦系統(tǒng)的眾多算法中匪燕,基于內(nèi)容的推薦與基于領(lǐng)域的推薦在實踐中得到了最廣泛的應(yīng)用帽驯。

其中基于領(lǐng)域的算法又分為兩大類龟再,

一類是基于用戶的協(xié)同過濾算法,這種算法從用戶的興趣相似出發(fā)尼变,給用戶推薦與其興趣相似的其他用戶喜歡的物品利凑;

另一類是基于物品的協(xié)同過濾算法,這種算法更容易理解嫌术,就是直接給用戶推薦和他之前喜歡的物品相似的物品哀澈。

協(xié)同過濾的核心思想:

通過計算物品或用戶的之間的相似度,找出相似度最高的TopN個度气,作為推薦的結(jié)果割按;

2. 基于用戶的協(xié)同過濾(User-based CF)

基于用戶對物品的偏好找到鄰居用戶(相似用戶),然后將鄰居用戶(相似用戶)喜歡的東西推薦給當前用戶蚯嫌。

主要分為兩個步驟:

  1. 找到相似的用戶
  2. 將相似用戶喜歡的(但該用戶A沒有發(fā)現(xiàn)或沒看過的)物品推薦給該用戶A

2.1 計算兩個用戶相似度

2.1.1 杰卡德(Jaccard)相似系數(shù)

這個是衡量兩個集合的相似度一種指標哲虾。兩個用戶 uu 和 vv 交互商品交集的數(shù)量占這兩個用戶交互商品并集的數(shù)量的比例,稱為兩個集合的杰卡德相似系數(shù)择示,用符號 simuvsimuv 表示束凑,其中 N(u),N(v)N(u),N(v) 分別表示用戶 uu 和用戶 vv 交互商品的集合。
sim_{uv}=\frac{|N(u)| \cap |N(v)|}{|N(u)|\cup|N(v)|}
由于杰卡德相似系數(shù)一般無法反映具體用戶的評分喜好信息栅盲, 所以常用來評估用戶是否會對某商品進行打分汪诉, 而不是預(yù)估用戶會對某商品打多少分。

2.1.2 余弦相似度

余弦相似度衡量了兩個向量的夾角谈秫,夾角越小越相似扒寄。首先從集合的角度描述余弦相似度,相比于Jaccard公式來說就是分母有差異拟烫,不是兩個用戶交互商品的并集的數(shù)量该编,而是兩個用戶分別交互的商品數(shù)量的乘積,公式如下:
sim_{uv}=\frac{|N(u)| \cap |N(v)|}{\sqrt{|N(u)|\cdot|N(v)|}}
其中N (u) 表示用戶 u 購買物品的數(shù)量硕淑, N (v) 表示用戶 v 購買物品的數(shù)量课竣, N (u)\cap N(v) 表示用戶α 和b 購買相同物品的數(shù)量嘉赎。

從向量的角度進行描述,令矩陣 AA 為用戶-商品交互矩陣(因為是TopN推薦并不需要用戶對物品的評分于樟,只需要知道用戶對商品是否有交互就行)公条,即矩陣的每一行表示一個用戶對所有商品的交互情況,有交互的商品值為1沒有交互的商品值為0迂曲,矩陣的列表示所有商品靶橱。若用戶和商品數(shù)量分別為 m,nm,n 的話,交互矩陣 AA 就是一個 mm 行 nn 列的矩陣路捧。此時用戶的相似度可以表示為(其中 u?vu?v 指的是向量點積):
sim_{uv} = cos(u,v) =\frac{u\cdot v}{|u|\cdot |v|}
其中关霸,sim_{uv} 表示用戶u和用戶v的相似度;u 表示用戶u喜歡的物品集合鬓长;v 表示用戶v喜歡的物品集合谒拴;

上述用戶-商品交互矩陣在現(xiàn)實情況下是非常的稀疏了,為了避免存儲這么大的稀疏矩陣涉波,在計算用戶相似度的時候一般會采用集合的方式進行計算。

from sklearn.metrics.pairwise import cosine_similarity
i = [1, 0, 0, 0]
j = [1, 0.5, 0.5, 0]
cosine_similarity([i, j])

2.1.3 皮爾遜相關(guān)系數(shù)

皮爾遜相關(guān)系數(shù)的公式與余弦相似度的計算公式非常的類似炭序,首先對于上述的余弦相似度的計算公式寫成求和的形式,其中 rui,rvirui,rvi 分別表示用戶 uu 和用戶 vv 對商品 ii 是否有交互(或者具體的評分值):
sim_{uv} = \frac{\sum_i r_{ui}*r_{vi}}{\sqrt{\sum_i r_{ui}^2}\sqrt{\sum_i r_{vi}^2}}
下面是皮爾遜相關(guān)系數(shù)計算公式啤覆,其中 rui,rvirui,rvi 分別表示用戶 uu 和用戶 vv 對商品 ii 是否有交互(或者具體的評分值), ˉru,ˉrvrˉu,rˉv 分別表示用戶 uu 和用戶 vv 交互的所有商品交互數(shù)量或者具體評分的平均值惭聂。
sim(u,v)=\frac{\sum_{i\in I}(r_{ui}-\bar r_u)(r_{vi}-\bar r_v)}{\sqrt{\sum_{i\in I }(r_{ui}-\bar r_u)^2}\sqrt{\sum_{i\in I }(r_{vi}-\bar r_v)^2}}
所以相比余弦相似度窗声,皮爾遜相關(guān)系數(shù)通過使用用戶的平均分對各獨立評分進行修正,減小了用戶評分偏置的影響辜纲。具體實現(xiàn)笨觅, 我們也是可以調(diào)包, 這個計算方式很多耕腾, 下面是其中的一種:

from scipy.stats import pearsonr

i = [1, 0, 0, 0]
j = [1, 0.5, 0.5, 0]
pearsonr(i, j)

2.2 找到最相似的K個用戶见剩,進行評分預(yù)測

有了用戶的相似數(shù)據(jù),針對用戶U 挑選K 個最相似的用戶扫俺,把他們購買過的物品中苍苞, U未購買過的物品推薦給用戶U 即可。如果有評分數(shù)據(jù)狼纬,可以針對這些物品進一步打分羹呵,打分的原理與基于物品的推薦原理類似,公式如下:
p_{\mathrm{u}, \mathrm{i}}=\sum_{N(u) \cap S(u,k)}\left(sim_{\mathrm{u}, \mathrm{v}} \cdot r_{\mathrm{v}, \mathrm{i}}\right)
其中是N( i )物品 i 被購買的用戶集合疗琉, S (u, k )是用戶u 的相似用戶集合冈欢,挑選最相似的用戶k 個,將重合的用戶u 在物品 i 上的得分r_{\mathrm{v}, \mathrm{i}}乘以用戶u 和u 的相似度盈简,累加后得到用戶u 對于物品 i 的得分凑耻。

2.3 實現(xiàn)邏輯

基于物品的協(xié)同過濾的原理是用戶U 購買了A 物品太示,推薦給用戶U 和A 相似的物品B 、C 拳话、D 先匪。而基于用戶的協(xié)同過濾,是先計算用戶U 與其他的用戶的相似度弃衍,然后取和U 最相似的幾個用戶呀非,把他們購買過的物品推薦給用戶U。

具體用戶-物品數(shù)據(jù)如下:

用戶-物品數(shù)據(jù)

2.3.1 item倒排

為了計算用戶相似度镜盯,我們首先要把用戶購買過物品的索引數(shù)據(jù)轉(zhuǎn)化成物品被用戶購買過的索引數(shù)據(jù)岸裙,即物品的倒排索引;

如下圖所示:

對用戶-物品的倒排

2.3.2 計算相似度

A B C D
A 1/\sqrt{3*2} 1/\sqrt{3*2} 1/\sqrt{3*3}
B 1/\sqrt{3*2} 1/\sqrt{3*2}
C 1/\sqrt{3*2} 1/\sqrt{3*2}
D 1/\sqrt{3*3} 1/\sqrt{3*2} 1/\sqrt{3*2}

2.3.3 計算評分

假設(shè),用戶A的相似用戶是B速缆、C降允、D;

用戶B艺糜、C剧董、D之前瀏覽過的物品但是用戶A沒有瀏覽過的物品是c、e破停,所以用戶A對物品c翅楼、e的評分:

P(A,c) = sim(A,B) * r(B,c) + sim(A,D) * r(D,c)

? = (1/\sqrt{3*2} ) * 4 + (1/\sqrt{3*3}) * 5

P(A,e) = sim(A,C) * r(C,e) + sim(A,D) * r(D,e)

? = (1/\sqrt{3*2} ) * 4 + (1/\sqrt{3*3}) * 4

2.3.4 代碼實現(xiàn)

import time
import math

dataset = [('A', 'a', 5), ('A', 'b', 4), ('A', 'd', 3)
          ,('B', 'a', 4), ('B', 'c', 4)
          ,('C', 'b', 3), ('C', 'e', 4)
          ,('D', 'c', 5), ('D', 'd', 3), ('D', 'e', 4)
        ]
test = ['A']

def get_scores(dataset):
    scores={}
    for u,i,score in dataset:
        scores[tuple([u,i])]=score
    return scores

def score(scores,u,item):
    s=scores[tuple([u,item])]
    return s

def toDict(dataset):
    train, test = [], []
    for user, item, _ in dataset:
        train.append((user, item))
    trainDict=ToDict(train)
    return trainDict

# 倒排
def Inverse(train):
    item_users = {}
    for user in train:
        for item in train[user]:
            if item not in item_users:
                item_users[item] = []
            item_users[item].append(user)
    return item_users

#計算用戶相似度矩陣 {u:(v,dict)}
def  simCosUser(item_users) :
    """
    item_users:商品-用戶(倒排結(jié)果)
    """
    # 計算用戶相似度矩陣
    sim = {} # 2個用戶同時對商品的關(guān)注數(shù)量
    num = {} # 存放用戶對商品關(guān)注的數(shù)量
    for item in item_users:
        users = item_users[item]
        for i in range(len(users)):
            u = users[i]
            if u not in num:
                num[u] = 0
            num[u] += 1  #計算每個用戶關(guān)注item數(shù)量
            if u not in sim:
                sim[u] = {}
            for j in range(len(users)):
                if j == i:
                    continue
                else:
                    v = users[j]
                    if v not in sim[u]:
                        sim[u][v] = 0  # 計算用戶u和用戶v關(guān)注item數(shù)量相同的商品數(shù)
                    sim[u][v] += 1
    for u in sim:
        for v in sim[u]:
            sim[u][v] /= math.sqrt(num[u] * num[v])   # sim[u][v]用戶u和用戶v的相似度 
    # 按照相似度排序
    sorted_user_sim = {k: list(sorted(v.items(),  key=lambda x: x[1], reverse=True)) for k, v in sim.items()}
    return sorted_user_sim

# 用戶做推薦
def GetUserRecommendation(train,user,simUV,K,N,scores):  
    """
    train: 訓(xùn)練集數(shù)據(jù)
    user: 給用戶id推薦
    simUV:用戶間相似計算
    K:選擇距離最近的K個用戶
    N:推薦item的數(shù)量
    """
    items = {}
    seen_items = set(train[user])
    topK=simUV[user][:K] # 用戶user最相似的K個用戶
    for u,sim in topK:
        for item in train[u]:
            # 將用戶過去沒有看過的,但其相似用戶看過的item真慢,給用戶推薦
            if item not in seen_items: # 去掉用戶已經(jīng)看過的
                if item not in items:
                    items[item] = 0 
                items[item] += sim*score(scores,u,item) # 相似用戶對物品的評分 score(u,v)))]
    recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]
    return recs

K = 1
N = 10
train = toDict(dataset)
scores = get_scores(dataset)
print("-----------1.倒排序------------")
item_users=Inverse(train)  # 商品-用戶id
print("-----------2.計算相似度-----------")
simUV=simCosUser(item_users) 
print(simUV)
print("-----------3.推薦的item-----------")
recs=RecFunc(train,test,simUV,K,N,scores) 
print(recs)
-----------1.倒排序------------
-----------2.計算相似度-----------
{'A': [('B', 0.4082482904638631), ('C', 0.4082482904638631), ('D', 0.3333333333333333)], 'B': [('A', 0.4082482904638631), ('D', 0.4082482904638631)], 'D': [('B', 0.4082482904638631), ('C', 0.4082482904638631), ('A', 0.3333333333333333)], 'C': [('A', 0.4082482904638631), ('D', 0.4082482904638631)]}
-----------3.推薦的item-----------
{'A': [('c', 3.2996598285221186), ('e', 2.9663264951887856)]}

2.4 UserCF優(yōu)缺點

User-based算法存在兩個重大問題:

  1. 數(shù)據(jù)稀疏性毅臊。
    一個大型的電子商務(wù)推薦系統(tǒng)一般有非常多的物品,用戶可能買的其中不到1%的物品黑界,不同用戶之間買的物品重疊性較低管嬉,導(dǎo)致算法無法找到一個用戶的鄰居,即偏好相似的用戶朗鸠。這導(dǎo)致UserCF不適用于那些正反饋獲取較困難的
    應(yīng)用場景(如酒店預(yù)訂蚯撩, 大件商品購買等低頻應(yīng)用)

  2. 算法擴展性。
    基于用戶的協(xié)同過濾需要維護用戶相似度矩陣以便快速的找出Topn相似用戶童社, 該矩陣的存儲開銷非常大求厕,存儲空間隨
    著用戶數(shù)量的增加而增加,不適合用戶數(shù)據(jù)量大的情況使用扰楼。

3. 基于物品的協(xié)同過濾(Item-based CF)

基于物品的協(xié)同過濾算法的核心思想:給用戶推薦那些和他們之前喜歡的物品相似的物品;

主要分為兩個步驟:

第一步:計算兩個物品用戶相似度呀癣;

這里取的是余弦相似度:
w_{ij}=\frac{|N(i)| \cap |N(j)|}{\sqrt{|N(i)|\cdot|N(j)|}}
其中,N(i) — 喜歡物品i的用戶列表弦赖,N(j) —喜歡物品j的用戶列表

第二步:找到最相似的k個物品项栏,分別對k個物品評分;
p_{\mathrm{u}, \mathrm{j}}=\sum_{i\in N(u) , j\in S(i,k)}\left(w_{\mathrm{j}, \mathrm{i}} \cdot r_{\mathrm{u}, \mathrm{i}}\right)
其中蹬竖,N(u)表示用戶喜歡的物品列表沼沈,S(j,k)表示用戶u的歷史興趣物品列表中物品 i 最相似的 k 個物品流酬;

3.1 實現(xiàn)邏輯

計算相似度的方法同上面(User-based CF)介紹的那幾種方法;

注意:

物品的相似度列另,要把物品A和物品B共有的相似物品C的相似度相加芽腾,算作物品C的相似度;

物品-用戶

3.2 代碼實現(xiàn)

import time
import math

dataset = [('A', 'a', 5), ('A', 'b', 4), ('A', 'd', 3)
          ,('B', 'a', 4), ('B', 'c', 4), ('E', 'e', 5)
          ,('C', 'c', 3), ('C', 'd', 4)
          ,('D', 'b', 5), ('D', 'c', 3), ('D', 'd', 4)
          ,('E', 'a', 5), ('E', 'd', 3)
        ]
test = ['A']

def get_scores(dataset):
    scores={}
    for u,i,score in dataset:
        scores[tuple([u,i])]=score
    return scores

def score(scores,u,item):
    s=scores[tuple([u,item])]
    return s

def toDict(dataset):
    train, test = [], []
    for user, item, _ in dataset:
        train.append((user, item))
    trainDict=ToDict(train)
    return trainDict

def ToDict(data):
    data_dict = {}
    for user, item in data:
        if user not in data_dict:
            data_dict[user] = set()
        data_dict[user].add(item)
    data_dict = {k: list(data_dict[k]) for k in data_dict}
    return data_dict

#計算商品相似度矩陣 
def simCosItem(train) :
    sim = {}
    num = {}
    for user, items in train.items():
        for i in items:
            if i not in num.keys():
                num[i] = 0
            num[i] += 1
            for j in items:
                if i == j: continue
                if i not in sim.keys():
                    sim[i]={}
                if j not in sim[i].keys():
                    sim[i][j] = 0
                # 當用戶同時購買了i和j 
                sim[i][j] += 1
    item_sim = {}
    for i, related_items in sim.items():
        item_sim[i] = {}
        for j, ij in related_items.items():
            item_sim[i][j] = ij / math.sqrt(num[i] * num[j])
    # 按照相似度排序
    sorted_item_sim = {}
    norm_item_sim = {}
    for k, v in item_sim.items():
        sorted_item_sim[k] = sorted(v.items(), key=lambda x: x[1], reverse=True)
        itme_sim_max = sorted_item_sim[k][0][1]
        norm_item_sim[k] = [(itemsim[0],itemsim[1]/itme_sim_max) for itemsim in sorted_item_sim[k]] 
    return norm_item_sim

# 推薦
def GetUserRecommendation(train,user,simIT,K,N,scores):  # item=itme(test中的item)
    """
    train: 訓(xùn)練集數(shù)據(jù)
    item: 給item推薦
    simIT:item間相似計算
    K:選擇距離最近的K個item
    N:推薦item的數(shù)量
    """
    rec_items = {}
    seen_items = set(train[user])
    for item_i in train[user]:
        for item_j,sim in simIT[item_i][:K]:
            # 測試集test的item要在訓(xùn)練集train出現(xiàn)過
            if item_j not in seen_items:
                if item_j not in rec_items:
                    rec_items[item_j] = 0 
                rec_items[item_j] += score(scores,user,item_i)*sim 
    recs = list(sorted(rec_items.items(), key=lambda x: x[1], reverse=True))[:N]
    return recs

def RecFunc(train,test,simIT,K,N,scores):
    """
    給測試集合的用戶推薦页衙,并記錄推薦的結(jié)果存放在字典中
    train: 訓(xùn)練集數(shù)據(jù)
    test:測試集數(shù)據(jù)
    user: 給用戶id推薦
    simIT:用戶間相似計算
    K:選擇距離最近的K個item
    N:推薦item的數(shù)量
    """
    recs={}            
    for user in test:
        recList=GetUserRecommendation(train,user,simIT,K,N,scores)
        recs[user] = recList
    return recs


K=1
N=10
train = toDict(dataset)
print("------------------------1摊滔、計算商品相似度--------------------------------")
simIT = simCosItem(train)   #商品間相似度
print(simIT)
print("------------------------2、根據(jù)用戶A喜歡的商品的商品相似度計算推薦商品----------------")
scores = get_scores(dataset)
recs=RecFunc(train,test,simIT,K,N,scores) 
print(recs)
------------------------1店乐、計算相似度--------------------------------
{'d': [('b', 1.0), ('a', 0.8164965809277263), ('c', 0.8164965809277263), ('e', 0.7071067811865476)], 'a': [('d', 1.0), ('e', 1.0), ('b', 0.7071067811865476), ('c', 0.5773502691896256)], 'b': [('d', 1.0), ('a', 0.5773502691896258), ('c', 0.5773502691896258)], 'c': [('d', 1.0), ('b', 0.7071067811865476), ('a', 0.5773502691896256)], 'e': [('a', 1.0), ('d', 0.8660254037844385)]}
------------------------2艰躺、根據(jù)商品相似度計算推薦商品----------------
{'A': [('c', 7.645642165489811), ('e', 7.121320343559643)]}

4. 總結(jié)

4.1 UserCF vs. ItemCF

基于用戶協(xié)同(User-based CF) 基于物品協(xié)同(Item-based CF)
原理 用戶喜歡那些和他有相似愛好的用戶喜歡的東西 用戶喜歡跟他過去喜歡的物品相似的物品
適用范圍 適用于用戶量較小的場合,如果用戶很多眨八,計算相似度代價高 適用于物品數(shù)量明顯小于用戶數(shù)量的場合腺兴,如果物品很多(新聞/視頻),計算物品相似度代價高
優(yōu)點 較其他算法新穎度更高對復(fù)雜的數(shù)據(jù)不感冒廉侧,視頻/音頻/圖片 可以推薦出更有深度的內(nèi)容對長尾商品相對更友好對復(fù)雜的數(shù)據(jù)不感冒页响,視頻/音頻/圖片
缺點 用戶冷啟動問題(新用戶沒有行為)可解釋性弱 物品冷啟動(新物品行為少)可解釋性比較UserCF強

4.2 基于用戶協(xié)同和基于物品協(xié)同的優(yōu)缺點

4.2.1 推薦的場景

UserCF :是利用用戶間的相似性來推薦的,所以假如物品的數(shù)量遠遠超過用戶的數(shù)量段誊,那么可以考慮使用User CF 拘泞,

? UserCF 是推薦用戶所在興趣小組中的熱點,更注重社會化枕扫,

適用場景:新聞、博客或者微內(nèi)容的推薦系統(tǒng)辱魁,

? 因為其內(nèi)容更新頻率非常高烟瞧,特別是在社交網(wǎng)絡(luò)中, UserCF可以增加用戶對推薦解釋的信服程度染簇。

Item CF :是利用物品間的相似性來推薦的参滴,所以假如用戶的數(shù)量遠遠超過物品的數(shù)量,那么可以考慮使用Item CF 锻弓,

? ItemCF 則是根據(jù)用戶歷史行為推薦相似物品砾赔,更注重個性化。

適用場景:比如購物網(wǎng)站青灼,

? 因其物品的數(shù)據(jù)相對穩(wěn)定暴心,因此計算物品的相似度時不但計算量較小,而且不必頻繁更新杂拨;

4.2.2 多樣性(覆蓋率)

覆蓋率专普,指一個推薦系統(tǒng)能否給用戶提供多種選擇;

一般來說弹沽,Item CF 的多樣性要遠遠好于UserCF 檀夹,因為UserCF 會更傾向于推薦熱門的物品筋粗。

也就是說, ItemCF 的推薦有很好的新穎性炸渡,容易發(fā)現(xiàn)并推薦長尾里的物品娜亿。

所以大多數(shù)情況, ItemCF 的精度稍微小于UserCF 蚌堵,但是如果考慮多樣性买决, UserCF 卻比ItemCF要好很多。

UserCF 經(jīng)常推薦熱門物品辰斋,所以它在推薦長尾里的項目方面的能力不足策州;而Item CF 只推薦A 領(lǐng)域給用戶,這樣它有限的推薦列表中就可能包含了一定數(shù)量的非熱門的長尾物品宫仗。ItemCF 的推薦對單個用戶而言够挂,顯然多樣性不足,但是對整個系統(tǒng)而言藕夫,因為不同的用戶的主要興趣點不同孽糖,所以系統(tǒng)的覆蓋率會比較好。

4.2.3 用戶特點

用戶特點對推薦算法影響的比較大毅贮。

對于UserCF 办悟,推薦的原則是假設(shè)用戶會喜歡那些和他有相同喜好的用戶喜歡的東西,但是假如用戶暫時找不到興趣相投的鄰居滩褥,那
么UserCF 的推薦效果就會大打折扣病蛉,因此用戶是否適應(yīng)UserCF 算法跟他有多少鄰居是成正比關(guān)系的。

同理瑰煎,對于ItemCF 铺然,基于物品的協(xié)同過濾算法也是有一定前提的,即用戶喜歡和他以前購買過的物品相同類型的物品酒甸,那么我們可以計算一個用戶喜歡的物品的自相似度魄健。一個用戶喜歡物品的自相似度大,就說明他喜歡的東西都是比較相似的插勤,即這個用戶比較符合ItemCF 方法的基本假設(shè)沽瘦,那么他對ItemCF 的適應(yīng)度自然比較好, 反之农尖,如果自相似度小析恋,就說明這個用戶的喜好習慣并不滿足ItemCF 方法的基本假設(shè), 那么用ItemCF 方法所做出的推薦對于這種用戶來說卤橄,其推薦效果可能不是很好绿满。

4.2.4 泛化能力差

協(xié)同過濾無法將兩個物品相似的信息推廣到其他物品的相似性上。 導(dǎo)致的問題是熱門物品具有很強的頭部效應(yīng)窟扑, 容易跟大量物品產(chǎn)生相似喇颁, 而尾部物品由于特征向量稀疏漏健, 導(dǎo)致很少被推薦

j簡單來說就是橘霎,兩個不同領(lǐng)域的最熱門物品之間往往具有比較高的相似度蔫浆。這個時候,僅僅靠用戶行為數(shù)據(jù)是不能解決這個問題的姐叁,因為用戶的行為表示這種物品之間應(yīng)該相似度很高瓦盛。此時,我們只能依靠引入物品的內(nèi)容數(shù)據(jù)解決這個問題,比如對不同領(lǐng)域的物品降低權(quán)重等。

4.2.5 協(xié)同過濾算法的權(quán)重改進

協(xié)同過濾算法的權(quán)重改進
  • 基礎(chǔ)算法
    圖1為最簡單的計算物品相關(guān)度的公式坝锰, 分子為同時喜好itemi和itemj的用戶數(shù)
  • 對熱門物品的懲罰
    圖1存在一個問題, 如果 item-j 是很熱門的商品嘱吗,導(dǎo)致很多喜歡 item-i 的用戶都喜歡 item-j,這時 wij 就會非常大滔驾。同樣谒麦,幾乎所有的物品都和 item-j 的相關(guān)度非常高,這顯然是不合理的哆致。所以圖2中分母通過引入 N(j) 來對 item-j 的熱度進行懲罰绕德。如果物品很熱門, 那么 N(j) 就會越大摊阀, 對應(yīng)的權(quán)重就會變小耻蛇。
  • 對熱門物品的進一步懲罰
    如果 item-j 極度熱門,上面的算法還是不夠的胞此。舉個例子城丧,《Harry Potter》非常火豌鹤,買任何一本書的人都會購買它,即使通過圖2的方法對它進行了懲罰枝缔,但是《Harry Potter》仍然會獲得很高的相似度布疙。這就是推薦系統(tǒng)領(lǐng)域著名的 Harry Potter Problem。
    如果需要進一步對熱門物品懲罰愿卸,可以繼續(xù)修改公式為如圖3所示灵临,通過調(diào)節(jié)參數(shù) α , α 越大趴荸,懲罰力度越大儒溉,熱門物品的相似度越低,整體結(jié)果的平均熱門程度越低发钝。
  • 對活躍用戶的懲罰
    同樣的顿涣,Item-based CF 也需要考慮活躍用戶(即一個活躍用戶(專門做刷單)可能買了非常多的物品)的影響波闹,活躍用戶對物品相似度的貢獻應(yīng)該小于不活躍用戶。圖4為集合了該權(quán)重的算法涛碑。

4.2.6 綜上小結(jié)

  • 基于用戶協(xié)同過濾

    1)根據(jù)不同用戶關(guān)注的同一個商品精堕,去計算這些不同用戶之間的相似度;

    2)用戶A的相似用戶B對商品a的評分= 用戶A與用戶B之間的相似度 x 用戶B對商品b的評分

  • 基于物品協(xié)同過濾

    1)根據(jù)同一個用戶關(guān)注的不同商品蒲障,去計算這些不同商品之間的相似度歹篓;

    2)用戶A對商品a的相似商品b的評分 = 用戶A對商品a的評分 x 商品a與商品b之間相似度

UserCF:適于用戶少,但有較多相同興趣揉阎, 物品多庄撮, 時效性較強的場合, 比如新聞推薦場景毙籽,

ItemCF:更適用于興趣變化較為穩(wěn)定的應(yīng)用洞斯, 更接近于個性化的推薦, 適合物品少惧财,用戶多巡扇,用戶興趣固定持久, 物品更新速度不是太快的場合垮衷, 比如推薦藝術(shù)品厅翔, 音樂, 電影搀突。

4.3 其他知識點;

4.3.1 相似度計算方法的優(yōu)缺點

cosine相似度還是比較常用的刀闷, 一般效果也不會太差, 但是對于評分數(shù)據(jù)不規(guī)范的時候仰迁, 也就是說甸昏, 存在有的用戶喜歡打高分, 有的用戶喜歡打低分情況的時候徐许,有的用戶喜歡亂打分的情況施蜜, 這時候consine相似度算出來的結(jié)果可能就不是那么準確了, 比如下面這種情況:

評分數(shù)據(jù)不規(guī)范

這時候雌隅, 如果用余弦相似度進行計算翻默, 會發(fā)現(xiàn)用戶d和用戶f比較相似, 而實際上恰起, 如果看這個商品喜好的一個趨勢的話修械, 其實d和e比較相近, 只不過e比較喜歡打低分检盼, d比較喜歡打高分肯污。 所以對于這種用戶評分偏置的情況, 余弦相似度就不是那么好了, 可以考慮使用下面的皮爾遜相關(guān)系數(shù)蹦渣。

4.3.2 協(xié)同過濾的缺點及解決思路

協(xié)同過濾的特點就是完全沒有利用到物品本身或者是用戶自身的屬性哄芜, 僅僅利用了用戶與物品的交互信息就可以實現(xiàn)推薦,比較簡單高效剂桥, 但這也是它的一個短板所在忠烛, 由于無法有效的引入用戶年齡, 性別权逗,商品描述美尸,商品分類,當前時間斟薇,地點等一系列用戶特征师坎、物品特征和上下文特征, 這就造成了有效信息的遺漏堪滨,不能充分利用其它特征數(shù)據(jù)胯陋。

為了解決這個問題, 在推薦模型中引用更多的特征袱箱,推薦系統(tǒng)慢慢的從以協(xié)同過濾為核心到了以邏輯回歸模型為核心遏乔, 提出了能夠綜合不同類型特征的機器學(xué)習模型。

參考資料:

《推薦系統(tǒng)實踐》

《推薦系統(tǒng)與深度學(xué)習》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末发笔,一起剝皮案震驚了整個濱河市盟萨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌了讨,老刑警劉巖捻激,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異前计,居然都是意外死亡胞谭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門男杈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丈屹,“玉大人,你說我怎么就攤上這事伶棒∪埃” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵苞冯,是天一觀的道長。 經(jīng)常有香客問我侧巨,道長舅锄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮皇忿,結(jié)果婚禮上畴蹭,老公的妹妹穿的比我還像新娘。我一直安慰自己鳍烁,他們只是感情好叨襟,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幔荒,像睡著了一般糊闽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爹梁,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天右犹,我揣著相機與錄音,去河邊找鬼姚垃。 笑死念链,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的积糯。 我是一名探鬼主播掂墓,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼看成!你這毒婦竟也來了君编?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤绍昂,失蹤者是張志新(化名)和其女友劉穎啦粹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窘游,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡唠椭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了忍饰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贪嫂。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艾蓝,靈堂內(nèi)的尸體忽然破棺而出力崇,到底是詐尸還是另有隱情,我是刑警寧澤赢织,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布亮靴,位于F島的核電站,受9級特大地震影響于置,放射性物質(zhì)發(fā)生泄漏茧吊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搓侄。 院中可真熱鬧瞄桨,春花似錦、人聲如沸讶踪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乳讥。三九已至柱查,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雏婶,已是汗流浹背物赶。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留留晚,地道東北人酵紫。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像错维,于是被迫代替她去往敵國和親奖地。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345