推荐系统实践笔记(二)

  • 第八章
# coding=utf-8
'''
推荐系统实践:第八章 评分预测问题
    评分预测算法
'''
import random
import math

class Cluster:
    def __init__(self,records):
        self.group = dict()
    def GetGroup(self, i):
        return 0
class IdCluster(Cluster):
    def __init__(self, records):
        Cluster.__init__(self, records)
    def GetGroup(self, i):
        return i

class UserActivityCluster(Cluster):
    def __init__(self, records):
        Cluster.__init__(self, records)
        activity = dict()
        for r in records:
            if r.test != 0:
                continue
            basic.AddToDict(activity, r.user, 1)
        k = 0
        for user, n in sorted(activity.items(),key=itemgetter(1),reverse=False):
            c = int((k*5)/(1.0 * len(activity)))
            self.group[user] = c
            k += 1

    def GetGroup(self, uid):
        if uid not in self.group:
            return -1
        else:
            return self.group[uid]

class ItemPopularityCluster(Cluster):
    def __init__(self, records):
        Cluster.__init__(self, records)
        popularity = dict()
        for r in records:
            if r.test != 0:
                continue
            basic.AddToDict(popularity, r.item, 1)
        k = 0
        for item, n in sorted(popularity.items(), key=itemgetter(1), reverse=False):
            c = int((k*5)/(1.0*len(popularity)))
            self.group[item] = c
            k += 1
    def GetGroup(self, item):
        if item not in self.group:
            return -1
        else:
            return self.group[item]

class UserVoteCluster(Cluster):
    def __init__(selfl,records):
        Cluster.__init__(self, records)
        vote = dict()
        count = dict()
        for r in records:
            if r.test != 0:
                continue
            basic.AddToDict(vote, r.user, r.vote)
            basic.AddToDict(count, r.user, 1)
        k = 0
        for user, v in vote.items():
            ave = v / (count[user] * 1.0)
            c = int(ave *2)
            self.group[user] = c

        def GetGroup(self, uid):
            if uid not in self.group:
                return -1
            else:
                return self.group[uid]

class ItemVoteCluster(Cluster):
    def __init__(self, records):
        Cluster.__init__(self, records)
        vote = dict()
        count = dict()
        for r in records:
            if r.test != 0:
                continue
            basic.AddToDict(vote, r.item, r.vote)
            basic.AddToDict(count, r.item, 1)
        k = 0
        for item, v in vote.items():
            ave = v/(count[item]*1.0)
            c = int(ave*2)
            self.group[item] = c

    def GetGroup(self, item):
        if item not in self.group:
            return -1
        else:
            return self.group[item]
#基于类类平均值预测
def PredictAll(records,user_clouster,item_cluster):
    total = dict()
    count = dict()
    for r in records:
        if r.test != 0:
            continue
        gu = user_clouster.GetGroup(r.user)
        gi = item_cluster.GetGroup(r.item)
        basic.AddToMat(total, gu, gi, r.vote)
        basic.AddToMat(count, gu, gi, 1)
    for r in records:
        gu = user_clouster.GetGroup(r.user)
        gi = item_cluster.GetGroup(r.item)
        average = total[gu][gi] / (1.0*count[gu][gi]+1.0)
        r.predict = average

#基于邻域的方法
def UserSimilarity(records):
    item_users = dict()
    ave_vote = dict()
    activity = dict()
    for r in records:
        addToMat(item_users, r.item, r.user, r.value)
        addToVec(ave_vote, r.user, r.value)
        addToVec(activity, r.user, 1)
    ave_vote = {x:y/activity[x] for x,y in ave_vote.items()}
    nu = dict()
    W = dict()
    for i,ri in item_users.items():
        for u, rui in ri.items():
            addToVec(nu, u, (rui - ave_vote[u])*(rui - ave_vote[u]))
            for v, rvi in ri.items():
                if u == v:
                    continue
                addToMat(W, u, v, (rui - ave_vote[u])*(rvi - ave_vote[u]))
    for u in W:
        W[u] = {x:y/math.sqrt(nu[x]*nu[u]) for x,y in W[u].items()}
    return W

def PredictAll(records, test, ave_vote, W, K):
    user_items = dict()
    for r in records:
        addToMat(user_items, r.user, r.item, r.value)
    for r in test:
        r.predict = 0
        norm = 0
        for v,wuv in sorted(W[r.user].items(), key = itemgetter(1), reverse = True )[0 : K]:
            if r.item in user_items[v]:
                rvi = user_items[v][r.item]
                r.predict += wuv * (rvi - ave_vote[v])
                norm += abs(wuv)
            if norm > 0:
                r.predict /= norm
            r.predict += ave_vote[r.user]

# LFM模型迭代过程
def LearningLFM(train, F, n, alpha, lamda):
    [p,q] = InitLFM(train, F)
    for step in range(0,n):
        for u, i, rui in train.items():
            pui = Predict(u, i, p, q)
            eui = rui - pui 
            for f in range(0,F):
                p[u][k] += alpha * (q[i][k]*eui - lamda * p[u][k])
                q[i][k] += alpha * (p[u][k]*eui - lamda * q[i][k])
        alpha *= 0.9
    return list(p,q)

# 初始化 p,q
def InitLFM(train, F):
    p = dict()
    q = dict()
    for u, i, rui in train.items():
        if u not in p:
            p[u] = [random.random()/math.sqrt(F) for x in range(0,F)]
        if i not in q:
            q[i] = [random.random()/math.sqrt(F) for x in range(0,F)]
    return list(p,q)

#加入偏执项的LFM -> BiasLFM
def LearningBiasLFM(train, F, n, alpha, lamda, mu):
    [bu, bi, p, q] = InitLFM(train, F)
    for step in range(0, n):
        for u, i, rui in train.items():
            pui = Predict(u, i, p, q, bu, bi, mu)
            eui = rui - pui
            bu[u] += alpha * (eui - lamda * bu[u])
            bi[i] += alpha * (eui - lamda * bi[i])
            for f in range(0, F):
                p[u][k] += alpha * (q[i][k] * eui - lamda * p[u][k])
                q[i][k] += alpha * (p[u][k] * eui - lamda * q[i][k])
        alpha *= 0.9
    return list(bu, bi, p, q)

if __name__ == '__main__':
    pass
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值