(数据挖掘-入门-3)基于用户的协同过滤之k近邻

主要内容:

1、k近邻

2、python实现

1、什么是k近邻(KNN)

在入门-1中,简单地实现了基于用户协同过滤的最近邻算法,所谓最近邻,就是找到距离最近或最相似的用户,将他的物品推荐出来。

而这里,k近邻(K Nearest Neighbor)的意思就是,找出最近或最相似的k个用户,将他们的评分(相似度权重求和)最高的几个物品进行推荐。

2、python实现

代码中有两个数据集,

一个是直接写在的代码中的users;

一个是在BX-Books.csv文件中;(下载地址:http://www.guidetodatamining.com/assets/data/BX-Dump.zip)

运行方式:

数据集1:

数据集2:

import codecs
from math import sqrt

users = {"Angelica": {"Blues Traveler": 3.5, "Broken Bells": 2.0,
                      "Norah Jones": 4.5, "Phoenix": 5.0,
                      "Slightly Stoopid": 1.5,
                      "The Strokes": 2.5, "Vampire Weekend": 2.0},

         "Bill":{"Blues Traveler": 2.0, "Broken Bells": 3.5,
                 "Deadmau5": 4.0, "Phoenix": 2.0,
                 "Slightly Stoopid": 3.5, "Vampire Weekend": 3.0},

         "Chan": {"Blues Traveler": 5.0, "Broken Bells": 1.0,
                  "Deadmau5": 1.0, "Norah Jones": 3.0, "Phoenix": 5,
                  "Slightly Stoopid": 1.0},

         "Dan": {"Blues Traveler": 3.0, "Broken Bells": 4.0,
                 "Deadmau5": 4.5, "Phoenix": 3.0,
                 "Slightly Stoopid": 4.5, "The Strokes": 4.0,
                 "Vampire Weekend": 2.0},

         "Hailey": {"Broken Bells": 4.0, "Deadmau5": 1.0,
                    "Norah Jones": 4.0, "The Strokes": 4.0,
                    "Vampire Weekend": 1.0},

         "Jordyn":  {"Broken Bells": 4.5, "Deadmau5": 4.0,
                     "Norah Jones": 5.0, "Phoenix": 5.0,
                     "Slightly Stoopid": 4.5, "The Strokes": 4.0,
                     "Vampire Weekend": 4.0},

         "Sam": {"Blues Traveler": 5.0, "Broken Bells": 2.0,
                 "Norah Jones": 3.0, "Phoenix": 5.0,
                 "Slightly Stoopid": 4.0, "The Strokes": 5.0},

         "Veronica": {"Blues Traveler": 3.0, "Norah Jones": 5.0,
                      "Phoenix": 4.0, "Slightly Stoopid": 2.5,
                      "The Strokes": 3.0}
        }

class recommender:

    def __init__(self, data, k=1, metric=‘pearson‘, n=5):
        """ initialize recommender
        currently, if data is dictionary the recommender is initialized
        to it.
        For all other data types of data, no initialization occurs
        k is the k value for k nearest neighbor
        metric is which distance formula to use
        n is the maximum number of recommendations to make"""
        self.k = k
        self.n = n
        self.username2id = {}
        self.userid2name = {}
        self.productid2name = {}
        # for some reason I want to save the name of the metric
        self.metric = metric
        if self.metric == ‘pearson‘:
            self.fn = self.pearson
        #
        # if data is dictionary set recommender data to it
        #
        if type(data).__name__ == ‘dict‘:
            self.data = data

    def convertProductID2name(self, id):
        """Given product id number return product name"""
        if id in self.productid2name:
            return self.productid2name[id]
        else:
            return id

    def userRatings(self, id, n):
        """Return n top ratings for user with id"""
        print ("Ratings for " + self.userid2name[id])
        ratings = self.data[id]
        print(len(ratings))
        ratings = list(ratings.items())
        ratings = [(self.convertProductID2name(k), v)
                   for (k, v) in ratings]
        # finally sort and return
        ratings.sort(key=lambda artistTuple: artistTuple[1],
                     reverse = True)
        ratings = ratings[:n]
        for rating in ratings:
            print("%s\t%i" % (rating[0], rating[1]))

    def loadBookDB(self, path=‘‘):
        """loads the BX book dataset. Path is where the BX files are
        located"""
        self.data = {}
        i = 0
        #
        # First load book ratings into self.data
        #
        f = codecs.open(path + "BX-Book-Ratings.csv", ‘r‘, ‘utf8‘)
        for line in f:
            i += 1
            #separate line into fields
            fields = line.split(‘;‘)
            user = fields[0].strip(‘"‘)
            book = fields[1].strip(‘"‘)
            rating = int(fields[2].strip().strip(‘"‘))
            if user in self.data:
                currentRatings = self.data[user]
            else:
                currentRatings = {}
            currentRatings[book] = rating
            self.data[user] = currentRatings
        f.close()
        #
        # Now load books into self.productid2name
        # Books contains isbn, title, and author among other fields
        #
        f = codecs.open(path + "BX-Books.csv", ‘r‘, ‘utf8‘)
        for line in f:
            i += 1
            #separate line into fields
            fields = line.split(‘;‘)
            isbn = fields[0].strip(‘"‘)
            title = fields[1].strip(‘"‘)
            author = fields[2].strip().strip(‘"‘)
            title = title + ‘ by ‘ + author
            self.productid2name[isbn] = title
        f.close()
        #
        #  Now load user info into both self.userid2name and
        #  self.username2id
        #
        f = codecs.open(path + "BX-Users.csv", ‘r‘, ‘utf8‘)
        for line in f:
            i += 1
            #print(line)
            #separate line into fields
            fields = line.split(‘;‘)
            userid = fields[0].strip(‘"‘)
            location = fields[1].strip(‘"‘)
            if len(fields) > 3:
                age = fields[2].strip().strip(‘"‘)
            else:
                age = ‘NULL‘
            if age != ‘NULL‘:
                value = location + ‘  (age: ‘ + age + ‘)‘
            else:
                value = location
            self.userid2name[userid] = value
            self.username2id[location] = userid
        f.close()
        print(i)

    def pearson(self, rating1, rating2):
        sum_xy = 0
        sum_x = 0
        sum_y = 0
        sum_x2 = 0
        sum_y2 = 0
        n = 0
        for key in rating1:
            if key in rating2:
                n += 1
                x = rating1[key]
                y = rating2[key]
                sum_xy += x * y
                sum_x += x
                sum_y += y
                sum_x2 += pow(x, 2)
                sum_y2 += pow(y, 2)
        if n == 0:
            return 0
        # now compute denominator
        denominator = (sqrt(sum_x2 - pow(sum_x, 2) / n)
                       * sqrt(sum_y2 - pow(sum_y, 2) / n))
        if denominator == 0:
            return 0
        else:
            return (sum_xy - (sum_x * sum_y) / n) / denominator

    def computeNearestNeighbor(self, username):
        """creates a sorted list of users based on their distance to
        username"""
        distances = []
        for instance in self.data:
            if instance != username:
                distance = self.fn(self.data[username],
                                   self.data[instance])
                distances.append((instance, distance))
        # sort based on distance -- closest first
        distances.sort(key=lambda artistTuple: artistTuple[1],
                       reverse=True)
        return distances

    def recommend(self, user):
       """Give list of recommendations"""
       recommendations = {}
       # first get list of users  ordered by nearness
       nearest = self.computeNearestNeighbor(user)
       #
       # now get the ratings for the user
       #
       userRatings = self.data[user]
       #
       # determine the total distance
       totalDistance = 0.0
       for i in range(self.k):
          totalDistance += nearest[i][1]
       # now iterate through the k nearest neighbors
       # accumulating their ratings
       for i in range(self.k):
          # compute slice of pie
          weight = nearest[i][1] / totalDistance
          # get the name of the person
          name = nearest[i][0]
          # get the ratings for this person
          neighborRatings = self.data[name]
          # get the name of the person
          # now find bands neighbor rated that user didn‘t
          for artist in neighborRatings:
             if not artist in userRatings:
                if artist not in recommendations:
                   recommendations[artist] = (neighborRatings[artist]
                                              * weight)
                else:
                   recommendations[artist] = (recommendations[artist]
                                              + neighborRatings[artist]
                                              * weight)
       # now make list from dictionary
       recommendations = list(recommendations.items())
       recommendations = [(self.convertProductID2name(k), v)
                          for (k, v) in recommendations]
       # finally sort and return
       recommendations.sort(key=lambda artistTuple: artistTuple[1],
                            reverse = True)
       # Return the first n items
       return recommendations[:self.n]
时间: 2024-12-11 05:45:31

(数据挖掘-入门-3)基于用户的协同过滤之k近邻的相关文章

(数据挖掘-入门)基于用户的协同过滤之最近邻

主要内容: 1.什么是基于用户的协同过滤 2.python实现 1.什么是基于用户协同过滤: 协同过滤:Collaborative Filtering,一般用于推荐系统,如京东,亚马逊等电商网站上的“购买该物品的用户还喜欢/购买”之类的栏目都是根据协同过滤推荐出来的. 基于用户的协同过滤:User-based CF,通过不同用户对item(物品)的评分来评测用户之间的相似性,基于用户之间的相似性做出推荐. 这里介绍一种最简单的过滤方法:最近邻,即找到与某用户最相似的用户,将该用户喜欢的物品(而某

推荐算法之基于用户的协同过滤

基于用户的的协同过滤算法是推荐统统最古老的算法,简称UserCF.该算法的诞生一定程度上标志着推荐系统的诞生.本文将对UserCF算法原理进行讲解,并且基于Movielens数据集给出实现代码供大家交流学习. 基本原理 在一个在线个性化推荐系统中,当一个用户A需要个性化推荐时,先找到和他相似兴趣的其他用户,然后把那些用户喜欢的而用户A没有听说过的物品推荐给用户A.这种方法就称为基于用户的协同过滤算法.该算法主要包括两个步骤: 找到和目标用户兴趣相似的用户集合 找到这个集合中用户喜欢的且目标用户没

Mahout实现基于用户的协同过滤算法

Mahout中对协同过滤算法进行了封装,看一个简单的基于用户的协同过滤算法. 基于用户:通过用户对物品的偏好程度来计算出用户的在喜好上的近邻,从而根据近邻的喜好推测出用户的喜好并推荐. 图片来源 程序中用到的数据都存在MySQL数据库中,计算结果也存在MySQL中的对应用户表中. package com.mahout.helloworlddemo; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.

基于用户的协同过滤算法(UserCF)

基于用户的协同过滤算法: 找到和目标用户相似的用户集合 找到这个集合中用户喜欢的但目标用户没有听过的物品 #encoding: utf-8 from Similarity import Person from Sort import select_sort file=open('user_bookmark','r') filew=open('user_bookRecommend','w') #加载训练集 trainSet={} while True: line=file.readline().s

基于用户的协同过滤推荐算法原理和实现

在推荐系统众多方法中,基于用户的协同过滤推荐算法是最早诞生的,原理也较为简单.该算法1992年提出并用于邮件过滤系统,两年后1994年被 GroupLens 用于新闻过滤.一直到2000年,该算法都是推荐系统领域最著名的算法. 本文简单介绍基于用户的协同过滤算法思想以及原理,最后基于该算法实现园友的推荐,即根据你关注的人,为你推荐博客园中其他你有可能感兴趣的人. 基本思想 俗话说"物以类聚.人以群分",拿看电影这个例子来说,如果你喜欢<蝙蝠侠>.<碟中谍>.&l

【推荐系统实战】:C++实现基于用户的协同过滤(UserCollaborativeFilter)

好早的时候就打算写这篇文章,但是还是参加阿里大数据竞赛的第一季三月份的时候实验就完成了,硬生生是拖到了十一假期,自己也是醉了...找工作不是很顺利,希望写点东西回顾一下知识,然后再攒点人品吧,只能如此了. 一.问题背景 二.基于用户的协同过滤算法介绍 三.数据结构和实验过程设计 四.代码 一.问题背景 首先介绍一下问题的背景,现在我有四个月的用户.品牌数据<user,brand>,即用户在这四个月中的某一天购买了某个品牌(当然为了简化算法模型,将购买时间省去,后面再说).即现在有这四个月的数据

基于用户的协同过滤

最近在看推荐系统.主要是看<智能web算法>和<推荐系统实战>这两本书.<智能web算法>中推荐系统只花一个章节来讲.<推荐系统实战>整本书都是在讲推荐的内容.有兴趣的朋友可以看看.在此慢慢写下笔记与诸位来宾交流交流 推荐系统应用广泛.推荐的方式也多种多样.比较常用的有三种方式.1.社会化推荐:2.协同过滤推荐:3.基于内容的推荐.而协同过滤推荐又可以分为基于用户的协同过滤推荐(UserCF)和基于物品的协同过滤推荐(ItemCF).本文写的是基于用户的协同

基于用户的协同过滤推荐算法

什么是推荐算法 推荐算法最早在1992年就提出来了,但是火起来实际上是最近这些年的事情,因为互联网的爆发,有了更大的数据量可以供我们使用,推荐算法才有了很大的用武之地. 最开始,所以我们在网上找资料,都是进yahoo,然后分门别类的点进去,找到你想要的东西,这是一个人工过程,到后来,我们用google,直接搜索自 己需要的内容,这些都可以比较精准的找到你想要的东西,但是,如果我自己都不知道自己要找什么肿么办?最典型的例子就是,如果我打开豆瓣找电影,或者我去 买说,我实际上不知道我想要买什么或者看

基于用户的协同过滤算法

基于用户的协同过滤算法-参考<推荐系统实践>一书,作者:项亮 1 import random 2 import math 3 class UserBasedCF: 4 def __init__(self,datafile = None): 5 self.datafile = datafile 6 self.readData() 7 self.splitData(3,47) 8 def readData(self,datafile = None): 9 """ 10