Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)

       本文在 Python推荐系统学习笔记(2)基于协同过滤的个性化推荐算法实战---ItemCF算法 一文的基础上,对其基本的ItemCF算法做出改进。

一、相关概念

1、ItemCF中,基于行为(喜好)的相似性度量公式原始形式:

        Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第1张图片

        s i,j 代表物品 i 和 j 的相似度;u(i) 和 u(j) 代表含有物品 或者物品 行为的用户集合;分子表示既行为过 i 又行为过物品 的用户个数的绝对值;分母代表行为过物品 以及行为过物品 的用户的数量的乘积的平方根。

2、ItemCF中,基于行为(喜好)的相似性度量公式改进形式1:

        改进意义:活跃用户应该被降低在相似度公式中的贡献度,如批发商用户会购置多项物品。

        Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第2张图片

         N(u) 代表用户行为过的物品总数。

3、ItemCF中,基于行为(喜好)的相似性度量公式改进形式2:

       改进意义:用户在不同时间对物品的操作应给予时间衰减惩罚,如在很多场景中,用户的兴趣会随时间发生变化,需要基于时间衰减进行加权。

          Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第3张图片            其中,Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第4张图片

       △t 是行为差异时间,α 是权重。

二、ItemCF推荐改进实战:

1、第一种改进形式:

      Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第5张图片

     只需将原始的base_contribute_score()函数定义更改为以下形式:

def update_one_contribute_score(user_total_click_num):
    return  1/math.log10(1+user_total_click_num)

     调用处也改为以下形式:

#第一处
co_appear[itemid_i][itemid_j]+=update_one_contribute_score(len(itemlist))
#第二处
co_appear[itemid_j][itemid_i]+=update_one_contribute_score(len(itemlist))

2、第二种改进形式:

    Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第6张图片  其中,Python推荐系统学习笔记(3)基于协同过滤的个性化推荐算法实战---ItemCF算法(下)_第7张图片

    (1)需要更改信息读取工具模块reader.py中的get_user_click函数,增加时间戳信息的获取:

#获得用户的点击序列,改进
def get_user_click(rating_file):
    #如果路径不存在,返回空数据
    if not os.path.exists(rating_file):
        return {},{}
    #打开文件
    fp=open(rating_file)
    num=0
    #用于传回的数据
    user_click={}

    #*改进,加入时间戳
    user_click_time={}


    #循环数据
    for line in fp:
        #第一行是表头,需要跳过处理
        if num==0:
            num+=1
            continue
        #根据逗号提取每个项目
        item=line.strip().split(',')
        if len(item)<4:
            continue
        [userid,itemid,rating,timestamp]=item

        #*改进处
        if userid+"_"+itemid not in user_click_time:
            #存储用户点击的电影的时间戳
            user_click_time[userid+"_"+itemid]=int(timestamp)


        if float(rating)<3.0:  #如果评分低于3分,则视为该用户不喜欢该电影
            continue
        #将单一用户的点击序列添加至返回数据
        if userid not in user_click:
            user_click[userid]=[]
        user_click[userid].append(itemid)
    fp.close()
    return user_click,user_click_time

    (2)更改核心算法中的主函数main_flow():

def main_flow():
    #获取用户的点击序列数据,改进,加入时间戳数据获取
    user_click,user_click_time=reader2.get_user_click("../data/ratings.csv")

    #获取电影信息数据
    item_info=reader2.get_item_info("../data/movies.csv")

    #计算各个物品之间的相似度,改进,加入时间戳因子
    sim_info=cal_item_sim(user_click,user_click_time)

    #计算每个用户的推荐(与喜好电影相似度较高的)电影
    recom_result=cal_recom_result(sim_info,user_click)
    #print(recom_result["1"])
    #根据用户id推荐电影,此处为1
    debug_recomresult(recom_result, item_info,"1")

    (3)更改原始的base_contribute_score()函数:

def update_two_contribute_score(click_time_one,click_time_two):
    delata_time=abs(click_time_one-click_time_two)
    #将时间戳单位换算为天
    total_sec=60*60*24
    delata_time=delata_time/total_sec
    return 1/(1+delata_time)  # α 此处取1

   (4)各个电影间的相似度计算函数更改,增加时间戳因子的获取与计算:

#计算各个电影间的相似度,改进
def cal_item_sim(user_click,user_click_time):
    #相似度数据
    co_appear={}
    #用于统计每个电影的行为用户数量
    item_user_click_time={}
    #循环点击序列数据,user是每用户的id,itemlist是每个用户的点击序列
    for user,itemlist in user_click.items():
        #循环每个用户的点击序列的索引
        for index_i in range(0,len(itemlist)):
            #计算每个item的被用户点击数量
            itemid_i=itemlist[index_i]
            item_user_click_time.setdefault(itemid_i,0) #setdefault方法可以对不存在的键做初值设定(初始化)
            item_user_click_time[itemid_i]+=1

            #计算每个电影id和其他电影id共同出现在一个用户的点击序列中的数值
            for index_j in range(index_i+1,len(itemlist)):
                itemid_j=itemlist[index_j]

                #改进处
                if user+"_"+itemid_i not in user_click_time:
                    click_time_one=0
                else:
                    click_time_one=user_click_time[user+"_"+itemid_i]
                if user + "_" + itemid_j not in user_click_time:
                    click_time_two = 0
                else:
                    click_time_two = user_click_time[user + "_" + itemid_j]


                #计算所有电影id中,两两id的共同出现次数
                co_appear.setdefault(itemid_i,{})
                co_appear[itemid_i].setdefault(itemid_j,0)
                
                #调用处的改进
                co_appear[itemid_i][itemid_j] +=update_two_contribute_score(click_time_one,click_time_two)

                co_appear.setdefault(itemid_j,{})
                co_appear[itemid_j].setdefault(itemid_i,0)

                #调用处的改进
                co_appear[itemid_j][itemid_i]+=update_two_contribute_score(click_time_one,click_time_two)

    #计算相似度
    item_sim_score={}
    item_sim_score_sorted={}
    for itemid_i,relate_item in co_appear.items():
        for itemid_j,co_time in relate_item.items():
            #相似度计算公式
            sim_score=co_time/math.sqrt(item_user_click_time[itemid_i]*item_user_click_time[itemid_j])
            #存储相似度
            item_sim_score.setdefault(itemid_i,{})
            item_sim_score[itemid_i][itemid_j]=sim_score
    #对相似度进行排序
    for itemid in item_sim_score:
        item_sim_score_sorted[itemid]=sorted(item_sim_score[itemid].items(),key=operator.itemgetter(1),reverse=True)

    return item_sim_score_sorted

三、参考资料:

 

1、https://www.imooc.com/learn/1029

2、https://www.imooc.com/learn/990

3、https://blog.csdn.net/yimingsilence/article/details/54934302

4、https://blog.csdn.net/xiaokang123456kao/article/details/74735992

5、项亮. 推荐系统实践[M]. 人民邮电出版社, 2012.

你可能感兴趣的:(Python,Python,ItemCF,协同过滤,个性化推荐,推荐系统)