Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

数据挖掘学习札记之KNN算法(二)

$
0
0

数据挖掘学习札记之KNN算法(一)里,使用sklearn模块对例子进行了求解,但是并不清楚k的取值。

下面是我写的一个Python代码,程序采用“小题大做”的方式,一方面可以熟悉算法,另一方面练习Python编程,可以看到,当k取1,2,3,4,5时,knn算法预测未知电影的类型都是R,即Romance。

说明:

1. 距离使用欧氏距离;

2. k近邻搜索使用线性扫描;

3. 未知电影对象调用label方法,得到预测类型;


from math import sqrt
class Movie:
    ''' Represents a movie '''
    lib=[]
    total=0 # Number of movies
    def __init__(self,nk,nf,tg):
        ''' Initialize a movie '''
        self.nkiss=nk
        self.nfight=nf
        self.tag=tg
        self.index=len(self.lib)+1
        Movie.lib.append(self)# initialize a movie and add it to the library
        Movie.total+=1
        self.print()

    def distance(self,movie):
        ''' Distance to another movie '''
        if type(movie)!=type(self):
            raise TypeError('requires a %s, given a %s'% (type(self),type(movie)))
        else:            
            dis=(self.nkiss-movie.nkiss)**2
            dis=dis+(self.nfight-movie.nfight)**2
            dis=sqrt(dis)
        return dis

    def get(self,k):
        ''' Get the kth movie'''
        if k>self.total:
            raise IndexError('out of range')
        else:
            for m in self.lib:
                if k==m.index:
                    return m

    def neighbors(self,k):
        '''Find its k neighbors '''
        dis=[]
        movie_many=[]
        for movie in self.lib:
            dis.append((movie.index,self.distance(movie)))
        dis.sort(key=lambda dis:dis[1]) # sort according to distances
        for i in range(1,k+1):
            movie_many.append(self.get(dis[i][0]))
        self.print(movie_many)
        return movie_many


    def print(self,movies=None):
        ''' Print the information of a movie or a set of movies '''
        if movies==None:
            print((self.index,self.nkiss,self.nfight,self.tag))
        else:
            for m in movies:
                m.print()

    def label(self,k=1):
        '''From its k nearest neihbors to determin its tag: R or A ?'''
        if self.tag=='unknown':
            movie_many=self.neighbors(k)
            nR=0
            nA=0
            for movie in movie_many:
                if movie.tag=='R':
                    nR+=1
                elif movie.tag=='A':
                    nA+=1
                else:
                    raise TypeError('The movie with label %d is not a training data'%movie.label())
            else:
                if nR>nA:
                    tag='R'
                elif nR<nR:
                    tag='A'
                else:
                    tag='unknown'
        return tag

Movie(3,104,'R')
Movie(2,100,'R')
Movie(1,81,'R')
Movie(101,10,'A')
Movie(99,5,'A')
Movie(98,2,'A')
test=Movie(18,90,'unknown')


计算结果如下:


>>> test.label(1)
(2, 2, 100, 'R')
'R'
>>> test.label(2)
(2, 2, 100, 'R')
(3, 1, 81, 'R')
'R'
>>> test.label(3)
(2, 2, 100, 'R')
(3, 1, 81, 'R')
(1, 3, 104, 'R')
'R'
>>> test.label(4)
(2, 2, 100, 'R')
(3, 1, 81, 'R')
(1, 3, 104, 'R')
(4, 101, 10, 'A')
'R'
>>> test.label(5)
(2, 2, 100, 'R')
(3, 1, 81, 'R')
(1, 3, 104, 'R')
(4, 101, 10, 'A')
(5, 99, 5, 'A')
'R'
>>> test.label(6)
(2, 2, 100, 'R')
(3, 1, 81, 'R')
(1, 3, 104, 'R')
(4, 101, 10, 'A')
(5, 99, 5, 'A')
(6, 98, 2, 'A')
'unknown'
>>> 



上面的运行如下解释,
首先,初始化6个电影对象,代表6个实例,第7个是未知电影test,它的类型tag未知。然后调用label方法, test.label(2),表示利用test的最近的两个邻居来预测,test电影的类型。在运行中,我们打印出了,该未知电影的k个近邻。

知识点:
1. 使用sort进行排序时,可以指定key,使得按指定方式排序,上面的代码key=lambda dis:dis[1]使用每个元素(二元组)的第二个为键进行排序,因为第二元组的第一个是电影的序号,第二个是距离;
2. 虽然Python没有函数重载,但是可以使用默认参数达到同样的目的,比如print函数,既可以打印一个电影,也可以打印一个电影列表。关于Python的函数重载问题,网上有评论,比如这里。



作者:zhaoyl03 发表于2013-3-15 19:21:38 原文链接
阅读:19 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>