(数据挖掘-入门-5)基于内容的协同过滤与分类

1、动机

2、基于内容的分类器

3、python实现

一、动机

在前面的文章中介绍了基于用户和基于物品的协同过滤推荐方法,其实无论是基于用户还是基于物品,都是通过群体效应来进行推荐,因为衡量相似度的向量都是基于一定群体用户的评分,所以推荐出来的物品都是热门的流行的物品,对于一些冷门物品可能就无法收到亲睐。

而一个好的推荐系统,不仅能为用户发现热门流行的感兴趣物品,也能为用户提供自己也不了解的但也会感兴趣的物品,即冷门的物品,这样既有益于用户,也照顾了内容提供商。

因此,本文将介绍一种基于内容即物品属性的分类方法来进行推荐,在机器学习中,称为有监督学习的方法。

二、基于内容(物品属性)的分类器

1、特征向量

与基于物品的协同顾虑类似,需要一个能够描述物品的特征向量,只是这里的特征向量与用户无关,只与物品的自身属性相关,如:

歌曲的属性:

   

2、相似性度量

相似性度量方法与前面的介绍的一样,基本上采用距离公式,如曼哈顿距离,欧几里得距离等

有个问题在于不同特征属性的尺度不同,这样会导致距离的计算由某些特征主导,解决方法有两种:

A. 归一化

将特征属性都归一到[0,1]或[-1,1]之间

B. 标准化

将特征属性标准化为均值为0的高斯分布或其他分布

        

采用上面的标准化方法容易受离群点或奇异点(outliers)影响,因此一般采用如下方法:

将均值替换为中值,将标准差的计算方法替换为绝对标准差,如下:

3、分类器

有了特征向量和相似度衡量方法,那么如何进行分类呢?

假设有一些用户和物品数据,我们知道用户听过一些音乐,知道他喜欢哪些,不喜欢哪些,那么来了一首新的歌曲,我们如何判断用户是否喜欢呢?这就是一个简单的分类问题,两个类别:喜欢or不喜欢。

其实很简单,这里介绍一种最简单的,前面也介绍过的方法,那就是最近邻分类或k近邻分类。

我们有了物品数据,即有了物品的特征向量,那么我们就可以在用户听过的歌曲中找到跟新歌曲相似度最高的歌曲,如果用户喜欢该歌曲,那么我们将猜测也喜欢这首新歌,否则反之。

总结一下:分类器就是利用一些已经标注过类别的物品数据,来预测新物品的类别。

4、训练集与测试集

训练集:用来训练模型参数的数据

测试集:用来测试模型好坏的数据

三、python实现

数据集下载:

代码:

##   Each line of the file contains tab separated fields.
##   The first line of the file describes how those fields (columns) should
##   be interpreted. The descriptors in the fields of the first line are:
##
##        comment   -  this field should be interpreted as a comment
##        class     -  this field describes the class of the field
##        num       -  this field describes an integer attribute that should
##                     be included in the computation.
##
##        more to be described as needed
##
##
##    So, for example, if our file describes athletes and is of the form:
##    Shavonte Zellous   basketball  70  155
##    The first line might be:
##    comment   class  num   num
##
##    Meaning the first column (name of the player) should be considered a comment;
##    the next column represents the class of the entry (the sport);
##    and the next 2 represent attributes to use in the calculations.
##
##    The classifer reads this file into the list called data.
##    The format of each entry in that list is a tuple
##
##    (class, normalized attribute-list, comment-list)
##
##    so, for example
##
##   [(‘basketball‘, [1.28, 1.71], [‘Brittainey Raven‘]),
##    (‘basketball‘, [0.89, 1.47], [‘Shavonte Zellous‘]),
##    (‘gymnastics‘, [-1.68, -0.75], [‘Shawn Johnson‘]),
##    (‘gymnastics‘, [-2.27, -1.2], [‘Ksenia Semenova‘]),
##    (‘track‘, [0.09, -0.06], [‘Blake Russell‘])]
##

class Classifier:

    def __init__(self, filename):

        self.medianAndDeviation = []

        # reading the data in from the file
        f = open(filename)
        lines = f.readlines()
        f.close()
        self.format = lines[0].strip().split(‘\t‘)
        self.data = []
        for line in lines[1:]:
            fields = line.strip().split(‘\t‘)
            ignore = []
            vector = []
            for i in range(len(fields)):
                if self.format[i] == ‘num‘:
                    vector.append(float(fields[i]))
                elif self.format[i] == ‘comment‘:
                    ignore.append(fields[i])
                elif self.format[i] == ‘class‘:
                    classification = fields[i]
            self.data.append((classification, vector, ignore))
        self.rawData = list(self.data)
        # get length of instance vector
        self.vlen = len(self.data[0][1])
        # now normalize the data
        for i in range(self.vlen):
            self.normalizeColumn(i)

    ##################################################
    ###
    ###  CODE TO COMPUTE THE MODIFIED STANDARD SCORE

    def getMedian(self, alist):
        """return median of alist"""
        if alist == []:
            return []
        blist = sorted(alist)
        length = len(alist)
        if length % 2 == 1:
            # length of list is odd so return middle element
            return blist[int(((length + 1) / 2) -  1)]
        else:
            # length of list is even so compute midpoint
            v1 = blist[int(length / 2)]
            v2 =blist[(int(length / 2) - 1)]
            return (v1 + v2) / 2.0

    def getAbsoluteStandardDeviation(self, alist, median):
        """given alist and median return absolute standard deviation"""
        sum = 0
        for item in alist:
            sum += abs(item - median)
        return sum / len(alist)

    def normalizeColumn(self, columnNumber):
       """given a column number, normalize that column in self.data"""
       # first extract values to list
       col = [v[1][columnNumber] for v in self.data]
       median = self.getMedian(col)
       asd = self.getAbsoluteStandardDeviation(col, median)
       #print("Median: %f   ASD = %f" % (median, asd))
       self.medianAndDeviation.append((median, asd))
       for v in self.data:
           v[1][columnNumber] = (v[1][columnNumber] - median) / asd

    def normalizeVector(self, v):
        """We have stored the median and asd for each column.
        We now use them to normalize vector v"""
        vector = list(v)
        for i in range(len(vector)):
            (median, asd) = self.medianAndDeviation[i]
            vector[i] = (vector[i] - median) / asd
        return vector

    ###
    ### END NORMALIZATION
    ##################################################

    def manhattan(self, vector1, vector2):
        """Computes the Manhattan distance."""
        return sum(map(lambda v1, v2: abs(v1 - v2), vector1, vector2))

    def nearestNeighbor(self, itemVector):
        """return nearest neighbor to itemVector"""
        return min([ (self.manhattan(itemVector, item[1]), item)
                     for item in self.data])

    def classify(self, itemVector):
        """Return class we think item Vector is in"""
        return(self.nearestNeighbor(self.normalizeVector(itemVector))[1][0])

def unitTest():
    classifier = Classifier(‘athletesTrainingSet.txt‘)
    br = (‘Basketball‘, [72, 162], [‘Brittainey Raven‘])
    nl = (‘Gymnastics‘, [61, 76], [‘Viktoria Komova‘])
    cl = ("Basketball", [74, 190], [‘Crystal Langhorne‘])
    # first check normalize function
    brNorm = classifier.normalizeVector(br[1])
    nlNorm = classifier.normalizeVector(nl[1])
    clNorm = classifier.normalizeVector(cl[1])
    assert(brNorm == classifier.data[1][1])
    assert(nlNorm == classifier.data[-1][1])
    print(‘normalizeVector fn OK‘)
    # check distance
    assert (round(classifier.manhattan(clNorm, classifier.data[1][1]), 5) == 1.16823)
    assert(classifier.manhattan(brNorm, classifier.data[1][1]) == 0)
    assert(classifier.manhattan(nlNorm, classifier.data[-1][1]) == 0)
    print(‘Manhattan distance fn OK‘)
    # Brittainey Raven‘s nearest neighbor should be herself
    result = classifier.nearestNeighbor(brNorm)
    assert(result[1][2]== br[2])
    # Nastia Liukin‘s nearest neighbor should be herself
    result = classifier.nearestNeighbor(nlNorm)
    assert(result[1][2]== nl[2])
    # Crystal Langhorne‘s nearest neighbor is Jennifer Lacy"
    assert(classifier.nearestNeighbor(clNorm)[1][2][0] == "Jennifer Lacy")
    print("Nearest Neighbor fn OK")
    # Check if classify correctly identifies sports
    assert(classifier.classify(br[1]) == ‘Basketball‘)
    assert(classifier.classify(cl[1]) == ‘Basketball‘)
    assert(classifier.classify(nl[1]) == ‘Gymnastics‘)
    print(‘Classify fn OK‘)

def test(training_filename, test_filename):
    """Test the classifier on a test set of data"""
    classifier = Classifier(training_filename)
    f = open(test_filename)
    lines = f.readlines()
    f.close()
    numCorrect = 0.0
    for line in lines:
        data = line.strip().split(‘\t‘)
        vector = []
        classInColumn = -1
        for i in range(len(classifier.format)):
              if classifier.format[i] == ‘num‘:
                  vector.append(float(data[i]))
              elif classifier.format[i] == ‘class‘:
                  classInColumn = i
        theClass= classifier.classify(vector)
        prefix = ‘-‘
        if theClass == data[classInColumn]:
            # it is correct
            numCorrect += 1
            prefix = ‘+‘
        print("%s  %12s  %s" % (prefix, theClass, line))
    print("%4.2f%% correct" % (numCorrect * 100/ len(lines)))

##
##  Here are examples of how the classifier is used on different data sets
##  in the book.
#  test(‘athletesTrainingSet.txt‘, ‘athletesTestSet.txt‘)
#  test("irisTrainingSet.data", "irisTestSet.data")
#  test("mpgTrainingSet.txt", "mpgTestSet.txt")

if __name__ == ‘__main__‘:
    # unitTest
    print ("-------------------UnitTest----------------")
    unitTest()

    print ("-------------------Athletes Test----------------")
    test("athletesTrainingSet.txt","athletesTestSet.txt")

    print ("-------------------Irises Data Test----------------")
    test("irisTrainingSet.data","irisTestSet.data")

    print ("-------------------mpg Test----------------")
    test("mpgTrainingSet.txt","mpgTestSet.txt")
时间: 2024-10-17 09:30:05

(数据挖掘-入门-5)基于内容的协同过滤与分类的相关文章

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

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

推荐算法简介:基于用户的协同过滤、基于物品的协同过滤、基于内容的推荐

参考来源: https://blog.csdn.net/u011748319/article/details/90269818 1.推荐算法 1.1.协同过滤 协同过滤是目前应用最广泛的推荐算法,它仅仅通过了解用户与物品之间的关系进行推荐,而根本不会考虑到物品本身的属性. 可分成两类: 1.基于用户(user-based)的协同过滤 2.基于商品(item-based)的协同过滤 1.1.1.基于用户的协同过滤 基本思想: 基于用户对物品的偏好找到邻居用户(相似用户),然后将邻居用户(相似用户)

推荐算法之基于物品的协同过滤算法

基于物品的协同过滤算法(ItemCF)是业界应用最多的算法,主要思想是利用用户之前有过的行为,给用户推荐和之前物品类似的物品. 基于物品的协同过滤算法主要分为两步: 1)计算物品之间的相似度. 2)依据物品的相似度和用户的历史行为给用户生成推荐列表. 第一步的关键点在于计算物品之间的相似度,这里并不採用基于内容的相似性,而是去计算在喜欢物品i的用户中有多少是喜欢物品j的,这样计算的前提是用户的兴趣爱好通常是比較确定的,不easy变,那么当一个用户对两个物品都喜欢的时候,我们往往能够觉得这两个物品

基于物品的协同过滤算法ItemCF算法实现

基于物品的协同过滤算法(ItemCF)的基本思想是:给用户推荐那些和他们之前喜欢的物品相似的物品. 比如,该算法会因为你购买过<Java从入门到精通>而给你推荐<Java并发编程实战>.不过,基于物品的协同过滤算法并不利用物品的内容属性计算物品之间的相似度,二是通过分析用户的行为数据计算物品之间的相似度.该算法认为,物品A和物品B具有很大的相似度是因为喜欢物品A的用户大都也喜欢物品B. 实现代码: # -*- coding=utf-8 -*- from operator impor

基于用户的协同过滤

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

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

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

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

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

推荐算法之基于物品的协同过滤

基于物品的协同过滤( item-based collaborative filtering )算法是此前业界应用较多的算法.无论是亚马逊网,还是Netflix .Hulu . YouTube ,其推荐算法的基础都是该算法.为行文方便,下文以英文简称ItemCF表示.本文将从其基础算法讲起,一步步进行改进并基于MovieLens 数据集给出代码实现,带你领略这一经典算法的美. 1.基本原理 前面我们简单讲解了一下基于用户的协同过滤推荐(UserCF),并且给出了实现代码.还不了解的朋友可以转到链接

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

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