1.作业题目
原生python实现knn分类算法,用鸢尾花数据集
2.算法设计
KNN算法设计思路:
算法涉及3个主要因素:
- 训练数据集
- 距离或相似度的计算衡量
- k的大小
对于确定未知类别:
1.计算已知类别数据集中的点与当前点的距离(距离的计算一般使用欧氏距离或曼哈顿距离)
2.按照距离依次排序
3.选取与当前点距离最小的K个点
4.确定前K个点所在类别的出现概率
5.返回前K个点出现频率最高的类别作为当前点预测分类
3.有注释的源代码
数据分类.py:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
def train_test_split(X,y,test_ratio=0.2,seed=None):
"""将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""
assert X.shape[0]==y.shape[0]
assert 0.0<=test_ratio<=1.0
if seed:
np.random.seed(seed)
shuffle_indexes = np.random.permutation(len(X))
test_size = int(len(X)*test_ratio)
test_indexes = shuffle_indexes[:test_size]
train_indexes = shuffle_indexes[test_size:]
X_train = X[train_indexes]
y_train = y[train_indexes]
X_test = X[test_indexes]
y_test = y[test_indexes]
return X_train,X_test,y_train,y_test
鸢尾花KNN算法实现:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as py
import operator
from 数据分类 import train_test_split
import pandas as pd
from sklearn import datasets
'''载入鸢尾花数据集'''
iris = pd.read_csv('iris.data', header=None)
X = iris.iloc[0:150, 0:4].values
y = iris.iloc[0:150, 4].values
X_train, X_test, y_train, y_test = train_test_split(X,y)
#knn算法
def knn(trainSet,label,testSet,k):
# 求差的平方和---注意:数组可以做加减,此处均为数组
distance=(trainSet-testSet)**2
# 对数组的每一行求和,axis=1为对行求和,axis=0为对每列求和
distanceLine=distance.sum(axis=1)
finalDistance=distanceLine**0.5
# 获得排序后原始下角标
sortedIndex=finalDistance.argsort()
# 获得距离最小的前k个下角标
index=sortedIndex[:k]
# 字典 key为标签,value为标签出现的次数
labelCount={}
for i in index:
tempLabel=label[i]
labelCount[tempLabel]=labelCount.get(tempLabel,0)+1
# operator.itemgetter(1)意思是按照value值排序,即按照欧氏距离排序
sortedCount=sorted(list(labelCount.items()),key=operator.itemgetter(1),reverse=True)
return sortedCount[0][0]#输出标签出现最多的那个
#预测正确率
def predict(trainSet,trainLabel,testSet,k):
total=len(testSet)
trueCount=0
for i in range(len(testSet)):
label=knn(trainSet,trainLabel,testSet[i],k)
if label in testLabel[i]:
trueCount=trueCount+1
return "预测准确率为:{}".format(float(trueCount)/float(total))
if __name__=='__main__':
trainSet,trainLabel=X_train, y_train#训练数据以及标签
testSet, testLabel = X_test, y_test #测试数据以及标签
print((predict(trainSet,trainLabel,testSet,3)))
4.测试用例设计及调试过程截屏
测试用例设计:
输入数据:
鸢尾花数据集(‘iris.data’,保存在Python工程中,可直接运行)中每个样本x包含了花萼长度(sepal length)、花萼宽度(sepal width)、花瓣长度(petal length)、花瓣宽度(petal width)四个特征。样本标签y共有三类,分别是Setosa,Versicolor和Virginica。Iris数据集总共包含150个样本,每个类别由50个样本,整体构成一个150行5列的二维表,80%为训练集,20%为测试集。
预期结果:90%以上。
调试过程:
设置断点,只用训练数据进行训练和测试,结果为1即100%。
设置断点,用训练数据做训练集,测试数据做测试集,此时结果发生变化,准确率降低。
鸢尾花KNN算法代码运行结果:
准确率约为96.67%,说明训练模型比较可信。
5.总结
这次的作业总的来说完成度还可以,将鸢尾花数据集放在Python工程中,然后在运用时通过文件名进行直接调用,没有利用库中原本就有的函数,但遗憾的是参考了网上的部分代码,然后进行理解,对KNN算法也有了一定程度的理解,在运行过程中发现运行速度较慢,鸢尾花数据集为150个数据,运行时间约为0.00398922s。其中,遇到的问题是怎么将鸢尾花的数据分为训练集和测试集,将数据分类截取,一部分作为训练集,一部分作为测试集,这里占比为80%和20%,然后再结合KNN算法的思路完善程序。
KNN的特点:
优点
(1)监督学习:可以看到,kNN算法首先需要一个训练样本集,这个集合中含有分类信息,因此它属于监督学习。
(2)通过计算距离来衡量样本之间相似度,算法简单,易于理解和实现。
缺点
(1)需要设定k值,结果会受到k值的影响,通过上面的例子可以看到,不同的k值,最后得到的分类结果不尽相同。k一般不超过20。
(2)计算量大,需要计算样本集中每个样本的距离,才能得到k个最近的数据样本。
(3)训练样本集不平衡导致结果不准确问题。当样本集中主要是某个分类,该分类数量太大,导致近邻的k个样本总是该类,而不接近目标分类。
6.参考文献:
https://zhuanlan.zhihu.com/p/80036967