【笔记5】用pandas实现矩阵数据格式的推荐算法 (基于物品的协同)

'''
基于物品的协同推荐

矩阵数据

说明:
1.修正的余弦相似度是一种基于模型的协同过滤算法。我们前面提过,这种算法的优势之
一是扩展性好,对于大数据量而言,运算速度快、占用内存少。

2.用户的评价标准是不同的,比如喜欢一个歌手时有些人会打4分,有些打5分;不喜欢时
有人会打3分,有些则会只给1分。修正的余弦相似度计算时会将用户对物品的评分减去
用户所有评分的均值,从而解决这个问题。
'''

import pandas as pd
from io import StringIO

#数据类型一:csv矩阵(用户-商品)(适用于小数据量)
csv_txt = '''"user","Blues Traveler","Broken Bells","Deadmau5","Norah Jones","Phoenix","Slightly Stoopid","The Strokes","Vampire Weekend"
"Angelica",3.5,2.0,,4.5,5.0,1.5,2.5,2.0
"Bill",2.0,3.5,4.0,,2.0,3.5,,3.0
"Chan",5.0,1.0,1.0,3.0,5,1.0,,
"Dan",3.0,4.0,4.5,,3.0,4.5,4.0,2.0
"Hailey",,4.0,1.0,4.0,,,4.0,1.0
"Jordyn",,4.5,4.0,5.0,5.0,4.5,4.0,4.0
"Sam",5.0,2.0,,3.0,5.0,4.0,5.0,
"Veronica",3.0,,,5.0,4.0,2.5,3.0,'''

#数据类型一:csv矩阵(用户-商品)(适用于小数据量)
csv_txt2 = '''"user","Kacey Musgraves","Imagine Dragons","Daft Punk","Lorde","Fall Out Boy"
"David",,3,5,4,1
"Matt",,3,4,4,1
"Ben",4,3,,3,1
"Chris",4,4,4,3,1
"Tori",5,4,5,,3'''

#数据类型一:csv矩阵(用户-商品)(适用于小数据量)
#根据《data minning guide》第85页的users2数据
csv_txt3 = '''"user","Taylor Swift","PSY","Whitney Houston"
"Amy",4,3,4
"Ben",5,2,
"Clara",,3.5,4
"Daisy",5,,3'''

df = None

#方式一:加载csv数据
def load_csv_txt():
    global df, csv_txt, csv_txt2, csv_txt3
    df = pd.read_csv(StringIO(csv_txt3), header=0, index_col="user")

#测试:读取数据
load_csv_txt()

#=======================================
# 注意:不需要build_xy
#=======================================

# 计算两个物品相似度
def computeSimilarity(goods1, goods2):
    '''根据《data minning guide》第71页的公式s(i,j)'''
    # 每行的用户评分都减去了该用户的平均评分
    df2 = df[[goods1, goods2]].sub(df.mean(axis=1), axis=0).dropna(axis=0) #黑科技

    # 返回修正的余弦相似度
    return sum(df2[goods1] * df2[goods2]) / (sum(df2[goods1]**2) * sum(df2[goods2]**2))**0.5

# csv_txt
#print('\n测试:计算Blues Traveler与Broken Bells的相似度')
#print(computeSimilarity("Blues Traveler","Broken Bells"))

# csv_txt2
#print('\n测试:计算Kacey Musgraves与Imagine Dragons的相似度')
#print(computeSimilarity("Kacey Musgraves","Imagine Dragons"))

# 计算给定用户对物品的可能评分
def p(user, goods):
    '''根据《data minning guide》第75页的公式p(u,i)'''
    assert pd.isnull(df.ix[user, goods]) # 必须用户对给定物品尚未评分

    s1 = df.ix[user, df.ix[user].notnull()] #用户对已打分物品的打分数据

    s2 = s1.index.to_series().apply(lambda x:computeSimilarity(x, goods)) #打分物品分别与给定物品的相似度

    return sum(s1 * s2) / sum(abs(s2))

# csv_txt2
#print('\n测试:计算David对Kacey Musgraves的可能打分')
#print(p("David","Kacey Musgraves"))

#为了让公式的计算效果更佳,对物品的评价分值最好介于-1和1之间
def rate2newrate(rate):
    '''根据《data minning guide》第76页的公式NR(u,N)'''
    ma, mi = df.max().max(), df.min().min()
    return (2*(rate - mi) - (ma - mi))/(ma - mi)

#已知rate2newrate求newrate2rate
def newrate2rate(new_rate):
    '''根据《data minning guide》第76页的公式R(u,N)'''
    ma, mi = df.max().max(), df.min().min()
    return (0.5 * (new_rate + 1) * (ma - mi)) + mi

print('\n测试:计算3的new_rate值')
print(rate2newrate(3))

print('\n测试:计算0.5的rate值')
print(newrate2rate(0.5))

# 计算给定用户对物品的可能评分(对评分进行了修正/还原)
def p2(user, goods):
    '''根据《data minning guide》第75页的公式p(u,i)'''
    assert pd.isnull(df.ix[user, goods]) # 必须用户对给定物品尚未评分

    s1 = df.ix[user, df.ix[user].notnull()] #用户对已打分物品的打分数据
    s1 = s1.apply(lambda x:rate2newrate(x)) #修正
    s2 = s1.index.to_series().apply(lambda x:computeSimilarity(x, goods)) #已打分物品分别与给定物品的相似度

    return newrate2rate(sum(s1 * s2) / sum(abs(s2)))#还原

# csv_txt2
#print('\n测试:计算David对Kacey Musgraves的可能打分(修正)')
#print(p2("David","Kacey Musgraves"))

#==================================
# 下面是Slope One算法
#
# 两个步骤:
# 1. 计算差值
# 2. 预测用户对尚未评分物品的评分
#==================================

# 1.计算两物品之间的差异
def dev(goods1, goods2):
    '''根据《data minning guide》第80页的公式dev(i,j)'''
    s = (df[goods1] - df[goods2]).dropna()
    d = sum(s) / s.size
    return d, s.size #返回差异值,及权值(同时对两个物品打分的人数)

# csv_txt2
#print('\n测试:计算Kacey Musgraves与Imagine Dragons的分数差异')
#print(dev("Kacey Musgraves","Imagine Dragons"))

#计算所有两两物品之间的评分差异,得到方阵pd.DataFrame(行对列)
def get_dev_table():
    '''根据《data minning guide》第87页的表'''
    goods_names = df.columns.tolist()
    df2 = pd.DataFrame(.0, index=goods_names, columns=goods_names) #零方阵

    for i,goods1 in enumerate(goods_names):
        for goods2 in goods_names[i+1:]:
            d, _ = dev(goods1, goods2) # 注意:只取了物品差异值
            df2.ix[goods1, goods2] = d
            df2.ix[goods2, goods1] = -d # 对称的位置取反

    return df2

print('\n测试:计算所有两两物品之间的评分差异表')
print(get_dev_table())

#预测某用户对给定物品的评分
# 加权Slope One算法
def slopeone(user, goods):
    '''根据《data minning guide》第82页的公式p(u,j)'''
    s1 = df.ix[user].dropna() #用户对已打分物品的打分数据

    s2 = s1.index.to_series().apply(lambda x:dev(goods, x)) #待打分物品与已打分物品的差异值及权值
    s3 = s2.apply(lambda x:x[0]) #差异值
    s4 = s2.apply(lambda x:x[1]) #权值
    #print(s1, s3, s4)

    return sum((s1 + s3) * s4)/sum(s4)

print('\n测试:预测用户Ben对物品Whitney Houston的评分')
print(slopeone('Ben', 'Whitney Houston')) # 3.375

时间: 2024-07-31 02:51:50

【笔记5】用pandas实现矩阵数据格式的推荐算法 (基于物品的协同)的相关文章

【笔记6】用pandas实现条目数据格式的推荐算法 (基于物品的协同)

''' 基于物品的协同推荐 矩阵数据 说明: 1.修正的余弦相似度是一种基于模型的协同过滤算法.我们前面提过,这种算法的优势之 一是扩展性好,对于大数据量而言,运算速度快.占用内存少. 2.用户的评价标准是不同的,比如喜欢一个歌手时有些人会打4分,有些打5分:不喜欢时 有人会打3分,有些则会只给1分.修正的余弦相似度计算时会将用户对物品的评分减去 用户所有评分的均值,从而解决这个问题. 如何预测用户对给定物品的打分? 一.基于用户协同 方法1:用户之间的距离/相似度(K近邻算法) 二.基于物品协

【笔记3】用pandas实现矩阵数据格式的推荐算法 (基于用户的协同)

原书作者使用字典dict实现推荐算法,并且惊叹于18行代码实现了向量的余弦夹角公式. 我用pandas实现相同的公式只要3行. 特别说明:本篇笔记是针对矩阵数据,下篇笔记是针对条目数据. ''' 基于用户的协同推荐 矩阵数据 ''' import pandas as pd from io import StringIO import json #数据类型一:csv矩阵(用户-商品)(适用于小数据量) csv_txt = '''"user","Blues Traveler&qu

【笔记4】用pandas实现条目数据格式的推荐算法 (基于用户的协同)

''' 基于用户的协同推荐 条目数据 ''' import pandas as pd from io import StringIO import json #数据类型一:条目(用户.商品.打分)(避免巨型稀疏矩阵) csv_txt = '''"Angelica","Blues Traveler",3.5 "Angelica","Broken Bells",2.0 "Angelica","Nora

用Spark学习矩阵分解推荐算法

在矩阵分解在协同过滤推荐算法中的应用中,我们对矩阵分解在推荐算法中的应用原理做了总结,这里我们就从实践的角度来用Spark学习矩阵分解推荐算法. 1. Spark推荐算法概述 在Spark MLlib中,推荐算法这块只实现了基于矩阵分解的协同过滤推荐算法.而基于的算法是FunkSVD算法,即将m个用户和n个物品对应的评分矩阵M分解为两个低维的矩阵: 其中k为分解成低维的维数,一般远比m和n小.如果大家对FunkSVD算法不熟悉,可以复习对应的原理篇. 2. Spark推荐算法类库介绍 在Spar

【笔记2】推荐算法中的数据格式

设计推荐算法时,首先要考虑数据格式. 由于数据是关于用户对商品的评分,其具有三个要素:用户.商品.评分 所以,数据格式有三种形式: 1. json格式(json文本) #数据格式:json数据(用户.商品.打分) json_txt = '''{"Angelica": {"Blues Traveler": 3.5, "Broken Bells": 2.0, "Norah Jones": 4.5, "Phoenix&qu

矩阵连乘的算法问题

写给自己的话: 有时候虽然一道题懂做了,但是发现写解题报告时,要清楚把自己的思路描述出来却挺难的.做解题报告 不仅可以巩固.梳理知识,还可以加深理解.现在我还做得很不好, 一定要坚持! 加油! 矩阵链乘问题: 例子: (下面第二个{P1应该是P2) void MatrixChain() { int i, j, k, t; for(i = 1; i <= n; i++) m[i][i] = 0; //对角线赋值为0,是因为1个矩阵需做0次相乘 for(r=2; r<=n; ++r){ for(i

『 读书笔记 』4月读书总结|博文推荐

原文链接:『 读书笔记 』4月读书总结|博文推荐 写在前面 计划是每月读 5-10 本书,书籍类型大概是三个方面的:金融,技术,管理.之所以选择这三个方面,一方面是因为自己对这三个方面都很有兴趣,其次是被 linkedin 创始人 Hoffman 的 ABZ 理论 深度影响.建议大家都看看 abz 理论那篇文章,如果我有空,也会整理一些常用的这类理论模型到博客里的. 月底读书总结的形式都很简单,只是简单的一个列表和简单的书评,对觉得比较好的书会有单独的读书笔记.另外推荐大家用 excel 来做一

Ajax学习笔记---3种Ajax的实现方法【推荐】_AJAX相关

Ajax:  Asynchronous JavaScript and Xml , 异步js脚本和xml , 常用来实现页面局部的异步刷新, 对提高用户体验有很大帮助. Xml在多语言时较有优势, 但Ajax技术实际上较多采用Json对象而不是Xml来处理数据. (一) Ajax历史....了解性知识 Ajax归属于Web前端开发技术, 与javascript有着异常紧密的联系. Ajax就是一种实现异步通信无刷新的技术, 而这种技术可以有很多种实现方式. 浏览器的鼻祖网景(NetScape)公司

Ajax学习笔记---3种Ajax的实现方法【推荐】

Ajax:  Asynchronous JavaScript and Xml , 异步js脚本和xml , 常用来实现页面局部的异步刷新, 对提高用户体验有很大帮助. Xml在多语言时较有优势, 但Ajax技术实际上较多采用Json对象而不是Xml来处理数据. (一) Ajax历史....了解性知识 Ajax归属于Web前端开发技术, 与javascript有着异常紧密的联系. Ajax就是一种实现异步通信无刷新的技术, 而这种技术可以有很多种实现方式. 浏览器的鼻祖网景(NetScape)公司