python 实现协同过滤推荐算法

测试数据http://grouplens.org/datasets/movielens/#!/usr/bin/python3#-*-coding:utf-8-*-fromnumpyimport*importtimefromtexttableimportTexttable#协同过滤推荐算法主要分为:#1、基于用户。根据相邻用户,预测当前用户没有偏好的未涉及物

大家好,又见面了,我是你们的朋友全栈君。

测试数据
http://grouplens.org/datasets/movielens/
这里写图片描述

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from numpy import *
import time
from texttable import Texttable

# 协同过滤推荐算法主要分为:
# 1、基于用户。根据相邻用户,预测当前用户没有偏好的未涉及物品,计算得到一个排序的物品列表进行推荐
# 2、基于物品。如喜欢物品A的用户都喜欢物品C,那么可以知道物品A与物品C的相似度很高,而用户C喜欢物品A,那么可以推断出用户C也可能喜欢物品C。
# 不同的数据、不同的程序猿写出的协同过滤推荐算法不同,但其核心是一致的:
# 1、收集用户的偏好
# 1)不同行为分组
# 2)不同分组进行加权计算用户的总喜好
# 3)数据去噪和归一化
# 2、找到相似用户(基于用户)或者物品(基于物品)
# 3、计算相似度并进行排序。根据相似度为用户进行推荐
# 本次实例过程:
# 1、初始化数据
# 获取movies和ratings
# 转换成数据userDict 表示某个用户的所有电影的评分集合,并对评分除以5进行归一化
# 转换成数据ItemUser 表示某部电影参与评分的所有用户集合
# 2、计算所有用户与userId的相似度
# 找出所有观看电影与userId有交集的用户
# 对这些用户循环计算与userId的相似度
# 获取A用户与userId的并集。格式为:{'电影ID',[A用户的评分,userId的评分]},没有评分记为0
# 计算A用户与userId的余弦距离,越大越相似
# 3、根据相似度生成推荐电影列表
# 4、输出推荐列表和准确率


class CF:

    def __init__(self, movies, ratings, k=5, n=10):
        self.movies = movies
        self.ratings = ratings
        # 邻居个数
        self.k = k
        # 推荐个数
        self.n = n
        # 用户对电影的评分
        # 数据格式{'UserID:用户ID':[(MovieID:电影ID,Rating:用户对电影的评星)]}
        self.userDict = {}
        # 对某电影评分的用户
        # 数据格式:{'MovieID:电影ID',[UserID:用户ID]}
        # {'1',[1,2,3..],...}
        self.ItemUser = {}
        # 邻居的信息
        self.neighbors = []
        # 推荐列表
        self.recommandList = []
        self.cost = 0.0

    # 基于用户的推荐
    # 根据对电影的评分计算用户之间的相似度
    def recommendByUser(self, userId):
        self.formatRate()
        # 推荐个数 等于 本身评分电影个数,用户计算准确率
        self.n = len(self.userDict[userId])
        self.getNearestNeighbor(userId)
        self.getrecommandList(userId)
        self.getPrecision(userId)

    # 获取推荐列表
    def getrecommandList(self, userId):
        self.recommandList = []
        # 建立推荐字典
        recommandDict = {}
        for neighbor in self.neighbors:
            movies = self.userDict[neighbor[1]]
            for movie in movies:
                if(movie[0] in recommandDict):
                    recommandDict[movie[0]] += neighbor[0]
                else:
                    recommandDict[movie[0]] = neighbor[0]

        # 建立推荐列表
        for key in recommandDict:
            self.recommandList.append([recommandDict[key], key])
        self.recommandList.sort(reverse=True)
        self.recommandList = self.recommandList[:self.n]

    # 将ratings转换为userDict和ItemUser
    def formatRate(self):
        self.userDict = {}
        self.ItemUser = {}
        for i in self.ratings:
            # 评分最高为5 除以5 进行数据归一化
            temp = (i[1], float(i[2]) / 5)
            # 计算userDict {'1':[(1,5),(2,5)...],'2':[...]...}
            if(i[0] in self.userDict):
                self.userDict[i[0]].append(temp)
            else:
                self.userDict[i[0]] = [temp]
            # 计算ItemUser {'1',[1,2,3..],...}
            if(i[1] in self.ItemUser):
                self.ItemUser[i[1]].append(i[0])
            else:
                self.ItemUser[i[1]] = [i[0]]

    # 找到某用户的相邻用户
    def getNearestNeighbor(self, userId):
        neighbors = []
        self.neighbors = []
        # 获取userId评分的电影都有那些用户也评过分
        for i in self.userDict[userId]:
            for j in self.ItemUser[i[0]]:
                if(j != userId and j not in neighbors):
                    neighbors.append(j)
        # 计算这些用户与userId的相似度并排序
        for i in neighbors:
            dist = self.getCost(userId, i)
            self.neighbors.append([dist, i])
        # 排序默认是升序,reverse=True表示降序
        self.neighbors.sort(reverse=True)
        self.neighbors = self.neighbors[:self.k]

    # 格式化userDict数据
    def formatuserDict(self, userId, l):
        user = {}
        for i in self.userDict[userId]:
            user[i[0]] = [i[1], 0]
        for j in self.userDict[l]:
            if(j[0] not in user):
                user[j[0]] = [0, j[1]]
            else:
                user[j[0]][1] = j[1]
        return user

    # 计算余弦距离
    def getCost(self, userId, l):
        # 获取用户userId和l评分电影的并集
        # {'电影ID':[userId的评分,l的评分]} 没有评分为0
        user = self.formatuserDict(userId, l)
        x = 0.0
        y = 0.0
        z = 0.0
        for k, v in user.items():
            x += float(v[0]) * float(v[0])
            y += float(v[1]) * float(v[1])
            z += float(v[0]) * float(v[1])
        if(z == 0.0):
            return 0
        return z / sqrt(x * y)

    # 推荐的准确率
    def getPrecision(self, userId):
        user = [i[0] for i in self.userDict[userId]]
        recommand = [i[1] for i in self.recommandList]
        count = 0.0
        if(len(user) >= len(recommand)):
            for i in recommand:
                if(i in user):
                    count += 1.0
            self.cost = count / len(recommand)
        else:
            for i in user:
                if(i in recommand):
                    count += 1.0
            self.cost = count / len(user)

    # 显示推荐列表
    def showTable(self):
        neighbors_id = [i[1] for i in self.neighbors]
        table = Texttable()
        table.set_deco(Texttable.HEADER)
        table.set_cols_dtype(["t", "t", "t", "t"])
        table.set_cols_align(["l", "l", "l", "l"])
        rows = []
        rows.append([u"movie ID", u"Name", u"release", u"from userID"])
        for item in self.recommandList:
            fromID = []
            for i in self.movies:
                if i[0] == item[1]:
                    movie = i
                    break
            for i in self.ItemUser[item[1]]:
                if i in neighbors_id:
                    fromID.append(i)
            movie.append(fromID)
            rows.append(movie)
        table.add_rows(rows)
        print(table.draw())


# 获取数据
def readFile(filename):
    files = open(filename, "r", encoding="utf-8")
    # 如果读取不成功试一下
    # files = open(filename, "r", encoding="iso-8859-15")
    data = []
    for line in files.readlines():
        item = line.strip().split("::")
        data.append(item)
    return data

# -------------------------开始-------------------------------
start = time.clock()
movies = readFile("/home/hadoop/Python/CF/movies.dat")
ratings = readFile("/home/hadoop/Python/CF/ratings.dat")
demo = CF(movies, ratings, k=20)
demo.recommendByUser("100")
print("推荐列表为:")
demo.showTable()
print("处理的数据为%d条" % (len(demo.ratings)))
print("准确率: %.2f %%" % (demo.cost * 100))
end = time.clock()
print("耗费时间: %f s" % (end - start))

这里写图片描述
这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127311.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 基于单片机的毕业设计选题_环艺毕业设计选题

    基于单片机的毕业设计选题_环艺毕业设计选题单片机毕业设计-选题推荐

  • linux0.11_linux常用命令

    linux0.11_linux常用命令前言所有的UnixLike系统都会内建vi文书编辑器,其他的文书编辑器则不一定会存在。但是目前我们使用比较多的是vim编辑器。vim具有程序编辑的能力,可以主动的以字体颜色辨别语法的

  • mysql第一二三范式_第一范式、第二范式、第三范式[通俗易懂]

    mysql第一二三范式_第一范式、第二范式、第三范式[通俗易懂]第一范式、第二范式、第三范式第一范式如果一个关系模式R的所有属性都是不可分的基本数据项,则R1NF(即R符合第一范式)。两点:一、每个字段都只能存放单一值课程有两个值,不符合第一范式,可改为如下二、每笔记录都要能利用一个惟一的主键来加以识别第一范式、第二范式、第三范式第一范式如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF(即R符合第一范式)。两点:一、每个字段都只能存…

  • 考哪些证书国家有补贴_提交书证申请书范本

    考哪些证书国家有补贴_提交书证申请书范本当下的互联网应用如果是外网访问,一般都是https方式访问,需申请https证书目录Whyhttps?Whatishttps?Howtocreatehttps?Whyhttps?http明文传输不安全,因此需要进行加密处理,加密后端http就是httpsWhatishttps?https涉及很多概念,对称非对称加密、CA、数字签名、证书等等。有兴趣查看这里漫画解说https这里简要总结:A(客户端浏览器)——通过https://www.

  • 微信公众平台定时群发系统(小懒人定时精灵篇)

    微信公众平台定时群发系统(小懒人定时精灵篇)  所谓微信公众平台定时群发系统就是在你一个时间内把你所要发布的文章都填好,然后在选择群发时间段。我最近在使用“小懒人定时精灵”,使用步骤方便,省了我好大部分的时间,听他们官方说现在正在丰富内容,期待以后有更多的功能。“小懒人定时精灵“解救了那些傻傻地守在电脑旁发送微信的人们,现在微信公众平台的推送也能定时群发了。预先到微信后台编辑一条包括文字、图片、语音、视频、图集,然后到小懒…

  • html5div居中属性,html怎样让div居中

    html5div居中属性,html怎样让div居中html让div居中的方法:1、通过加“内容”标签让div居中;2、在div中加入“margin:0auto属性;”自动调节居中。本文操作环境:windows7系统、HTML5&&CSS3版、DellG3电脑。DIV居中提供两个方法:1、简单快捷方法就是加内容标签。示例:center居中我要居中啦2、div中加入margin:0auto属性;自动调节居中。示例2:margin…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号