这里是写给小白看的,大牛路过勿喷。
1 KNN算法简介
KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类对应的关系。输入没有标签的数据后,将新数据中的每个特征与样本集中数据对应的特征进行比较,提取出样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k近邻算法中k的出处,通常k是不大于20的整数。最后选择k个最相似数据中出现次数最多的分类作为新数据的分类
2 KNN算法优缺点
优点:精度高,对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
做一个简单的应用:
一种花叫做虹膜花:
from sklearn import neighbors from sklearn import datasets knn = neighbors.KNeighborsClassifier() iris = datasets.load_iris() knn.fit(iris.data, iris.target) # 当数据为0.1, 0.2, 0.3, 0.4时,预测它是什么花 predictedLabel = knn.predict([[0.1, 0.2, 0.3, 0.4]]) print(predictedLabel)
5.1,3.5,1.4,0.2,Iris-setosa 4.9,3.0,1.4,0.2,Iris-setosa 4.7,3.2,1.3,0.2,Iris-setosa 4.6,3.1,1.5,0.2,Iris-setosa 5.0,3.6,1.4,0.2,Iris-setosa 5.4,3.9,1.7,0.4,Iris-setosa 4.6,3.4,1.4,0.3,Iris-setosa 5.0,3.4,1.5,0.2,Iris-setosa
导入几个基本的库:
import csv import random import math import operator
全局定义两个集合:训练集、测试集
# 训练集 trainingSet = [] # 测试集 testSet = []
读取数据并做一些初步的处理:
传入一个分割概率,随机划分训练集和测试集
def loadDataset(filename, split): with open(filename, 'r') 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[x])
def euclideanDistance(instance1, instance2, length): distance = 0 for x in range(length): distance += pow((instance1[x] - instance2[x]), 2) return math.sqrt(distance)
从训练集中选出距离测试集中一个实例最近的k个数据:
计算训练集中每一项和该实例的欧氏距离,取最小的k个距离
def getNeighbors(k, testInstance): 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 = [] for x in range(k): neighbors.append(distances[x][0]) return neighbors
获取的这些k项未必是同一类,接下来统计类别个数,并返回出现次数最多的类作为最终的结果:
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.items(), key=operator.itemgetter(1), reverse=True) return sortedVotes[0][0]
验证精确度:
将测试集中预测的类别和测试集中真实的类别对比,得出精确度百分比:
def getAccuracy(predictions): correct = 0 for x in range(len(testSet)): if testSet[x][-1] == predictions[x]: correct += 1 return (correct / float(len(testSet))) * 100.0
主函数:
if __name__ == '__main__': main()
def main(): split = 0.70 loadDataset(r'D:\ml\irisdata.txt', split) print('Train set: ' + repr(len(trainingSet))) print('Test set: ' + repr(len(testSet)))
读取后打印下个数:
Train set: 102 Test set: 48
接下来预测:
predictions = [] k = 3 for x in range(len(testSet)): neighbors = getNeighbors(k, testSet[x]) result = getResponse(neighbors) predictions.append(result) print('>predicted=' + repr(result) + ', actual=' + repr(testSet[x][-1]))
看一下预测的一部分结果:
发现基本预测准确,测试精确度:
accuracy = getAccuracy(predictions) print('Accuracy: ' + repr(accuracy) + '%')
发现精确度很高:
由于处理数据时候采用随机划分的方式,可以反复运行测试,发现准确率基本在90%到96%,说明这个模型是合适的
小结:
KNN是简单有效的分类数据算法,在使用时必须有训练样本数据,还要计算距离,如果数据量非常大会非常消耗空间和时间。它的另一个缺陷是无法给出任何数据的基础结构信息,因此我们无法平均实例样本和典型实例样本具体特征,
来源:https://www.cnblogs.com/xuyiqing/p/8762066.html