《机器学习实战》--KNN

一、瞎扯

   先拉一下仇恨,这篇文章是在喝着走亲戚时带来的饮料,单曲循环着成龙版本的《拯救》的情况下完成的,哈哈,过年难免有些活的太潇洒,于是还是需要写些代码,看些书来收收心,另外新的一年开始了,也该对“懒”开刀了,准备养成写博客这一及其装逼的技能,祝各位同行新年快乐!(开始写的的时候还是大年初一,发布的时候过期了可别怪我)

KNN是机器学习中最简单,最基础的算法之一,算法实现起来没什么难度,但是它的使用范围依然十分广泛,比如书中提到的电影的分类,婚姻网站的配偶分类,手写识别系统,和轨迹预处理中选择候选轨迹等。

二、KNN介绍

   2.1监督学习和非监督学习
    监督学习:利用一组已知类别的样本调整分类器的参数,使其达到所要求性能的过程,也称为监督训练或有教师学习
    举个例子,教婴儿学习的时候,过来一只鸡,就让他叫鸡,过来一只鸭子的时候就让他叫鸭子,教会了一会,随便找一些鸡和鸭子他就能分辨了。这就是监督学习

    无监督学习:其中很重要的一类叫聚类
    举个例子,过来两种动物(假设还是鸡和鸭子,但是婴儿不知道),然后他根据动物的相像程度把动物分成两群

   2.2欧几里得距离
   这个在论文中经常能见到,它是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点之间的实际距离。

   n维下的两个点的欧氏距离:
    两个点 A = (a[1],a[2],…,a[n]) 和 B = (b[1],b[2],…,b[n]) 之间的距离 ρ(A,B) 
     定义为下面的公式:ρ(A,B) =√ [ ∑( a[i] - b[i] )^2 ] (i = 1,2,…,n) 

  2维下就是最常见的距离公式了 sqrt( (x1-x2)^2+(y1-y2)^2 )了

   2.3KNN算法介绍
   KNN属于监督学习,他需要一个训练集来训练,然后才能对后面给出的东西(测试集)进行分类。
   
   通俗的过程:
   1.通过训练集训练它,如上图,红色和蓝色就是训练集,他们的类别是已知的,于是现在来了一个未知的东西
   (标为绿色),希望通过knn来给它分类,看应该是属于蓝色的还是红色的。
   2.计算所有红色点和蓝色点到绿点的距离
   3.排序找到最近的k个,上图中实线表示k取3(即取距离最近的三个点),同理虚线表示k取5
   4.这k个里面哪个类别的东西多,就判断这个绿色点是属于哪一类的。如果上图看实线,红的比蓝的多那么
   绿点画为红的,如果是虚线,则标为蓝的

三、代码

代码我自己用了C++风格的python写了一遍,也就是说不用矩阵计算,那些矩阵被我当作多维数组来用了,代码写的很粗糙,未优化,望见谅。

另外还要再说明一个知识点–归一化 
这个很常见,数学课上也讲过就是把数值缩小到0-1之间,这里是把训练集中的样本数据归一化,使用的公式是newValue=(oldValue-min)/(max-min)

  1  # -*- coding: UTF-8 -*-   
  2 from numpy import *
  3 from math import *
  4 
  5 
  6 #定义类
  7 class Student(object):
  8   
  9     def __init__(self, distance, label):
 10         self.distance = distance
 11         self.label = label
 12 
 13 #KNN算法
 14 def classify0(inX, dataSet, labels, k):
 15     size=shape(dataSet)
 16     line=size[0]
 17     column=size[1]
 18     # print (inX)
 19     if(len(inX)!=column):
 20         print("unequal!!")
 21         return
 22 
 23 #计算当前项inX与其余训练集的欧氏距离
 24     sum=0.0000000000
 25     disList=[]
 26     for i in range(line):
 27         for j in range(column):
 28             sum+=(inX[j]-dataSet[i,j])**2
 29         tmp=Student(sqrt(sum),labels[i])
 30         disList.append(tmp)
 31         sum=0.0000000000
 32 #排序:欧氏距离从小到大
 33     disList.sort(lambda x,y:cmp(x.distance,y.distance)) 
 34 
 35 #取k项判断分类
 36     dict={}
 37     index=0
 38     for item in disList:
 39         if(index==k):
 40             break
 41         index+=1
 42         if(dict.has_key(item.label)):
 43             dict[item.label]+=1
 44         else:
 45             dict[item.label]=1
 46 
 47     dict=sorted(dict.iteritems(),key=lambda d:d[1],reverse=True)
 48     #返回最可能的值
 49     return dict[0][0]
 50 
 51 # def classify0(inX, dataSet, labels, k):
 52 #     dataSetSize = dataSet.shape[0]
 53 #     diffMat = tile(inX, (dataSetSize,1)) - dataSet
 54 #     sqDiffMat = diffMat**2
 55 #     sqDistances = sqDiffMat.sum(axis=1)
 56 #     distances = sqDistances**0.5
 57 #     sortedDistIndicies = distances.argsort()     
 58 #     classCount={}          
 59 #     for i in range(k):
 60 #         voteIlabel = labels[sortedDistIndicies[i]]
 61 #         classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
 62 #     sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
 63 #     print sortedClassCount[0][0]
 64 #     return sortedClassCount[0][0]
 65 
 66 
 67 #读取数据
 68 def file2matrix (filename):
 69     fr=open(filename)
 70     lines=fr.readlines()
 71     totalCnt=len(lines)
 72     totalCol=len(lines[0].strip().split('\t'))
 73 
 74     resultMatrix=zeros((totalCnt,totalCol-1))
 75     labelMatrix=[]
 76     index=0
 77     for line in lines:
 78         tmp=line.strip().split('\t')
 79         resultMatrix[index,:]=tmp[0:totalCol-1]
 80         labelMatrix.append((tmp[-1]))
 81         index+=1
 82     return resultMatrix,labelMatrix
 83 
 84 
 85 
 86 # def file2matrix(filename):
 87 #     fr=open(filename)
 88 #     arrayOlines=fr.readlines()
 89 #     numberOfLines=len(arrayOlines)
 90 #     returnMat=zeros((numberOfLines,3))
 91 #     classLabelVector=[]
 92 #     index=0
 93 #     for line in arrayOlines:
 94 #         line=line.strip()
 95 #         listFromLine=line.split('\t')
 96 #         returnMat[index,:]=listFromLine[0:3];
 97 #         classLabelVector.append((listFromLine[-1]))
 98 #         index+=1
 99 #     return returnMat,classLabelVector
100 
101 
102 #归一化处理  newValue=(oldValue-min)/(max-min)
103 def autoNorm(dataSet):
104     size=shape(dataSet)
105     line=size[0]
106     column=size[1]
107 
108     min=zeros((1,column))
109     max=zeros((1,column))
110     # print min
111     index=0
112     for value in dataSet[0,:]:
113         min[0,index]=value
114         max[0,index]=value
115         index+=1
116 #求每一列的最小值和最大值
117     for i in range(line):
118         for j in range(column):
119             if(i==0 and j==0): 
120                 continue        
121             if(dataSet[i,j]>max[0,j]):
122                 max[0,j]=dataSet[i,j]
123             if(dataSet[i,j]<min[0,j]):
124                 min[0,j]=dataSet[i,j]
125 
126     ranges = max-min
127     # print ranges
128     result=zeros((line,column))
129 
130     for i in range(line):
131         for j in range(column):
132             result[i,j]=(dataSet[i,j]-min[0,j])/ranges[0,j]
133 
134     return result,ranges,min
135     
136 
137 # def autoNorm(dataSet):
138 #     minVals = dataSet.min(0)
139 #     maxVals = dataSet.max(0)
140 #     ranges = maxVals - minVals
141 #     print ranges
142 #     normDataSet = zeros(shape(dataSet))
143 #     m = dataSet.shape[0]
144 #     normDataSet = dataSet - tile(minVals, (m,1))
145 #     normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
146 #     return normDataSet, ranges, minVals
147 
148 
149 
150 def datingClassTest():
151     hoRatio = 0.50      #hold out 10%
152     datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
153     normMat, ranges, minVals = autoNorm(datingDataMat)
154     m = normMat.shape[0]
155     numTestVecs = int(m*hoRatio)
156     errorCount = 0.0
157     for i in range(numTestVecs):
158         classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
159         print "the classifier came back with: %s, the real answer is: %s" % (classifierResult, datingLabels[i])
160         if (classifierResult != datingLabels[i]): errorCount += 1.0
161     print "the total error rate is: %f" % (errorCount/float(numTestVecs))
162     print errorCount
163 
164 
165 datingClassTest()

 

四、代码以及测试数据的下载

github:   https://github.com/wlmnzf/Machine-Learning-train/tree/master/KNN

五、感谢

1.《机器学习实战》这本书写的不错,值得学习
2.百度百科提供的图片和解释也不能忘
3.[《什么是无监督学习》 知乎](http://www.zhihu.com/question/23194489)
4.感谢 网易云音乐 《拯救》-成龙  深夜相伴

 

  扫码或者搜索 “会打代码的扫地王大爷” 关注公众号


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值