KNN算法,也就是对应的最近邻规则算法
KNN算法的优缺点,
是对K的选择是敏感的。
算法优点是容易实现,简单,通过的对k的选择具备丢噪音的健壮性的过程的。
缺点:
空间复杂度是比较高的(因为存在大量的计算的过程的。)
我们在选择k的时候总是选择奇数,因为我们这样总是能够以少数服从多数的方式,采用的投票的方式来决定类别的
当我们数据集分布不是平衡的时候,比如其中一类样本量过大时候,新的未知样本是容易被归为这个主导类样本的。
其中KNN最主要的过程是
首先是取K的,然后是找相应的要预测点,通过预测的点与现有全部的点计算相应的距离,按照距离从小到大进行排列,比如这里的距离我们是可以采用欧式距离,曼哈顿距离等的,得到相应的距离以后,找到k个最近的距离,看是什么类别,在以少数服从多数的方式,把最终想要预测的值,来进行相应的分类的过程的。
步骤:计算测试数据和各个训练数据之间所对应的距离
按照距离递增的关系进行排序
选取距离最小的k个点
确定前k个点类别出现的频率
返回前K个点中出现频率最高的点所对应的类别就是测试数据所对应的类别的
对于iris这个数据集我们是可以得到相应的
特征:萼片长度,萼片宽度,花瓣长度,花瓣宽度
这个特征就是对应的他的属性的
然后是来通过相应的属性,这样在来得到相应的花的类别的
iris sectors,lris versicolor,lris virginica
## KNN具体实现
import csv # 这读取数据用的。
import random # 进行随机变量的运算的过程的。
import math
import operator #
from IPython import embed
# 首先是要把用的数据集给装载进来的。
# split是可以来把原始的数据集,来分为两个部分,一部分是trianSet,一部分是testset
# split把原始数据集分为train和test数据集的过程的。
def loadDataset(filename,split,trainingSet=[],testSet=[]):
with open(filename,'rt') as csvfile:
lines = csv.reader(csvfile) # 这里是来把数据转换成为一行一行,所对应的数据
dataset = list(lines) # 然后这里是来把数据集,列表的方式进行输出的['1 5.1 3.5 1.4 0.2 "setosa"']
# 这里总共是对应的150行数据的
for x in range(len(dataset)-1):
for y in range(4):
dataset[x][y] = float(dataset[x][y])
if random.random() < split: # 这里是来对应的随机量是小于这个split的值的时候,那么我们就认为把
# 这一行数据给加入到trainingSet数据集中,反之则是加入到testSet所对应的数据集中的。
trainingSet.append(dataset[x])
else:
testSet.append(dataset[x])
# 这里是来传入两个实例,以及他所对应的维度。
# 传入是相应的测试实例,和相应训练的实例,特征的长度是对应的为4
def euclideanDistance(intstance1,instance2,length):
distance = 0
for x in range(length):
distance += pow((intstance1[x]-instance2[x]),2) # 然后是对应的每个维度相减后,所对应的平方值。最后是把这几个维度来进行求和
return math.sqrt(distance) # 开方值的过程的。这样就是来最后是返回相应的开方值的过程的。
# 这个是来返回测试实例中的,最近的k实例在训练集中的过程的
# 是来对应的训练数据集,和相应的测试数据集,和对应的相应的k近邻
def getNeighbors(trainingSet,testInstance,k):
distances = [] #定义一个容器,来装所有距离的过程的。
length = len(testInstance)-1 # 测试的维度
for x in range(len(trainingSet)):
dist = euclideanDistance(testInstance,trainingSet[x],length) # 然后是来计算出相应的欧式距离
# ([5.1, 3.5, 1.4, 0.2, 'Iris-setosa'], 0.09999999999999964)是来得到相应的训练集的特征
# 得到与测试样列之间,所对应的距离的。
distances.append((trainingSet[x],dist)) # 每一次算出的距离加入,
distances.sort(key=operator.itemgetter(1)) # 对距离进行排序
neighbors = []
for x in range(k):
neighbors.append(distances[x][0]) # 找出相应的最小的k个作为相应的邻居的
return neighbors
# 统计每一个分类的投票的多少,投票得到最多的模块,的分类
def getResponse(neighbors):
classVotes = {} # 根据这k实例来进行投票法则的
for x in range(len(neighbors)):
response = neighbors[x][-1] # 这里来返回,最后所对应的种类标签的。
if response in classVotes:
classVotes[response] += 1
else:
classVotes[response] = 1 # 首先是来把标签进行加入后,
sortedVotes = sorted(classVotes.items(),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]: # -1是取最后一个值。如果是预测的结果与测试结果是相同的。
correct += 1 # 那么就是correct+1
return (correct/float(len(testSet))) * 100.0 # 这样最后就是可以得到相应的准确性了
def main():
trainingSet = [] # 这里是来对应的相应的训练数据集
testSet = [] # 这里是来对应相应的测试数据集的过程的。
split = 0.67 # 按照两份和1份的方式来对相应的数据集,进行划分的过程的。
# r当成是原始的字符串进行对待,忽略出特殊字符的过程的。
loadDataset(r'D:\Pratice Code\MLeaning\data\Iris数据集\1.txt',split,trainingSet,testSet)
print("train set:" + repr(len(trainingSet)))
print('Test set:' + repr(len(testSet)))
# generate predictions是来表示生成相应的预测值的过程的
predictions = []
k = 3 # 其中是k是等于3来表示相应的分类的过程的。
for x in range(len(testSet)):
# 然后是来首先是对每一个测试数据集进行输入
neighbors = getNeighbors(trainingSet,testSet[x],k) # 这里是来返回每个实例对应的最近的k个实例的
result = getResponse(neighbors) #归类的值,
predictions.append(result) # 得到相应的全部的预测结果。
# >predicted='Iris-setosa',actual='Iris-setosa'
print('>predicted='+repr(result)+',actual='+repr(testSet[x][-1]))
accuracy = getAccuracy(testSet,predictions)
print('Accuracy:'+repr(accuracy)+'%')
if __name__ == '__main__':