1、KNN分类算法
KNN分类算法(K-Nearest-Neighbors Classification),又叫K近邻算法,是一个概念极其简单,而分类效果又很优秀的分类算法。
他的核心思想就是,要确定测试样本属于哪一类,就寻找所有训练样本中与该测试样本“距离”最近的前K个样本,然后看这K个样本大部分属于哪一类,那么就认为这个测试样本也属于哪一类。简单的说就是让最相似的K个样本来投票决定。
KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的 权值(weight),如权值与距离成反比。 该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。
该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知 样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于 样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
实现 K 近邻算法时,主要考虑的问题是如何对训练数据进行快速 K 近邻搜索,这在特征空间维数大及训练数据容量大时非常必要。
2、数据集介绍
machine-learning-databases/iris 点击打开链接
数据集信息:
这也许是最著名的数据库模式识别文献中被发现。 费舍尔的论文是一个典型的,经常被引用。 (见杜达&哈特,例如)。 50个实例的数据集包含3类,其中
每个类是指一种虹膜。 一个类是线性可分的从其他2;后者不是线性可分的。
预测属性:类的虹膜。
UCI中的Iris(鸢尾属植物)数据集。Iris数据包含150条样本记录,分剐取自三种不同的鸢尾属植物setosa、versic010r和virginica的花朵样本,每一
类各50条记录,其中每条记录有4个属性:萼片长度(sepal length)、萼片宽度sepalwidth)、花瓣长度(petal length)和花瓣宽度(petal width)。
这是一个极其简单的域。
3、完整源码
#-*- coding: UTF-8 -*-
'''''
Created on 2016/7/17
@author: chen
'''
import csv #用于处理csv文件
import random #用于随机数
import math
import operator #
from sklearn import neighbors
#加载数据集
def loadDataset(filename,split,trainingSet=[],testSet = []):
with open(filename,"rb") as csvfile:
lines = csv.reader(csvfile)
dataset = list(lines)
for x in range(len(dataset)-1):
for y in range(4):
dataset[x][y] = float(dataset[x][y])
if random.random()<split:
trainingSet.append(dataset[x])
else:
testSet.append(dataset[y])
#计算距离
def euclideanDistance(instance1,instance2,length):
distance = 0
for x in range(length):
distance += pow((instance1[x] - instance2[x]),2)
return math.sqrt(distance)
#返回K个最近邻
def getNeighbors(trainingSet,testInstance,k):
distances = []
length = len(testInstance) -1
#计算每一个测试实例到训练集实例的距离
for x in range(len(trainingSet)):
dist = euclideanDistance(testInstance, trainingSet[x], length)
distances.append((trainingSet[x],dist))
#对所有的距离进行排序
distances.sort(key=operator.itemgetter(1))
neighbors = []
#返回k个最近邻
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
#对k个近邻进行合并,返回value最大的key
def getResponse(neighbors):
classVotes = {}
for x in range(len(neighbors)):
response = neighbors[x][-1]
if response in classVotes:
classVotes[response]+=1
else:
classVotes[response] = 1
#排序
sortedVotes = sorted(classVotes.iteritems(),key = operator.itemgetter(1),reverse =True)
return sortedVotes[0][0]
#计算准确率
def getAccuracy(testSet,predictions):
correct = 0
for x in range(len(testSet)):
if testSet[x][-1] == predictions[x]:
correct+=1
return (correct/float(len(testSet))) * 100.0
def main():
trainingSet = [] #训练数据集
testSet = [] #测试数据集
split = 0.67 #分割的比例
loadDataset(r"../data/iris.txt", split, trainingSet, testSet)
print "Train set :" + repr(len(trainingSet))
print "Test set :" + repr(len(testSet))
predictions = []
k = 3
for x in range(len(testSet)):
neighbors = getNeighbors(trainingSet, testSet[x], k)
result = getResponse(neighbors)
predictions.append(result)
print ">predicted = " + repr(result) + ",actual = " + repr(testSet[x][-1])
accuracy = getAccuracy(testSet, predictions)
print "Accuracy:" + repr(accuracy) + "%"
if __name__ =="__main__":
main()
为了检验上述程序是否正确,编写一下代码,测试只需上面的代码。
#coding:utf-8
'''''
Created on 2016年7月17日
@author: chen
'''
from sklearn.datasets import load_iris
from sklearn import neighbors
import sklearn
#查看iris数据集
iris = load_iris()
print iris
knn = neighbors.KNeighborsClassifier()
#训练数据集
knn.fit(iris.data, iris.target)
#预测
predict = knn.predict([[0.1,0.2,0.3,0.4]])
print predict
print iris.target_names[predict]
结果如下
Train set :92
Test set :39
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
>predicted = 'Iris-setosa',actual = 'Iris-setosa'
Accuracy:100.0%
[Finished in 1.4s]