机器学习算法之KNN算法

本文用来记录机器学习经典算法,所有代码均使用sklearn实现,仅用于自学参考。

1.KNN算法原理

KNN,全称k-NearestNeighbor。
KNN算法的核心思想是:未标记样本的类别由距离其最近的K个邻居投票来决定。KNN算法可解决分类或者回归问题。由其思想可以看出,KNN是通过计算不同特征值之间的距离进行分类,而且在决策样本类别时,只参考样本周围k个“邻居”样本的所属类别。因此比较适合处理样本集存在较多重叠的场景,KNN算法主要用于聚类分析、预测分析、文本分类、降维等,也常被认为是简单数据挖掘算法的分类技术之一。

2.算法优缺点

优点:
①简单,易于理解,易于实现,无需参数估计,无需训练;
②精度高,对异常值不敏感(个别噪音数据对结果的影响不是很大);
③适合对稀有事件进行分类;
④特别适合于多分类问题(multi-modal,对象具有多个类别标签),KNN要比SVM表现要好。
缺点:
①对测试样本分类时的计算量大,空间开销大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本;
②可解释性差,无法给出决策树那样的规则;(黑盒模型)
③最大的缺点是当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进;
④消极学习方法。

3.算法代码

3.1sklearn实现

备注:数据集使用sklearn中的鸢尾花数据集

# -*- coding:utf8 -*-
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier 
import numpy as np
#设置随机种子,不设置的话默认是按系统时间作为参数,
#因此每次调用随机模块时产生的随机数都不一样设置后每次产生的一样
np.random.seed(0)

#1.导入鸢尾花的数据集
iris = datasets.load_iris()
#样本数据150*4二维数据,代表150个样本,
#每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
#长150的一维数组,样本数据的标签
iris_y = iris.target
#permutation接收一个数作为参数(150),产生一个0-149一维数组,
#只不过是随机打乱的,
#当然也可以接收一个一维数组作为参数,结果是直接对这个数组打乱
indices = np.random.permutation(len(iris_x))

#选取140个数据作为训练集
iris_x_train = iris_x[indices[:-10]]
iris_y_train = iris_y[indices[:-10]]
#选择10个数据作为测试集
iris_x_test = iris_x[indices[-10:]]
iris_y_test = iris_y[indices[-10:]]

#定义一个KNN分类器对象
knn = KNeighborsClassifier(n_neighbors=3)
#调用该对象的训练方法,主要接收两个参数:训练数据集及其样本标签
knn.fit(iris_x_train,iris_y_train)
#调用该对象的测试方法,主要接收一个参数:测试数据集
iris_y_predict = knn.predict(iris_x_test)
#调用该对象的打分方法,计算出准确率
score=knn.score(iris_x_test,iris_y_test,sample_weight=None)
#输出测试的结果
print('iris_y_predict = ')  
print(iris_y_predict)  
#输出原始测试数据集的正确标签,以方便对比
print('iris_y_test = ')
print(iris_y_test)
#输出准确率计算结果
print('Accuracy:',score) 

上述代码运行结果如下:
SK_KNN运行效果图

3.2 python代码实现

备注:数据集使用sklearn中的鸢尾花数据集

# -*-coding:utf8 -*-
'''
author:RongGong
'''
from sklearn import datasets
import numpy as np
import operator
#设置随机种子,不设置的话默认是按系统时间作为参数,
#因此每次调用随机模块时产生的随机数都不一样设置后每次产生的一样
np.random.seed(0)

#1.导入鸢尾花的数据集
iris = datasets.load_iris()
#样本数据150*4二维数据,代表150个样本,
#每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
#长150的一维数组,样本数据的标签
iris_y = iris.target
#permutation接收一个数作为参数(150),产生一个0-149一维数组,
#只不过是随机打乱的,
#当然也可以接收一个一维数组作为参数,结果是直接对这个数组打乱
indices = np.random.permutation(len(iris_x))

#选取140个数据作为训练集
iris_x_train = iris_x[indices[:-10]]
iris_y_train = iris_y[indices[:-10]]

#选择10个数据作为测试集
iris_x_test = iris_x[indices[-10:]]
iris_y_test = iris_y[indices[-10:]]

def classfy0(inX,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]
    diffMat = np.tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()
    classCount={}
    for i in range(k):
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel,0)+1
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

#调用classfy0()进行预测
errorCount = 0
print("预测结果:")
for i in range(10):
    predictRes = classfy0(iris_x_test[i],iris_x_train,iris_y_train,3)
    print(predictRes)
    if (predictRes != iris_y_test[i]): errorCount += 1

print("真实分类结果:")
print(iris_y_test)

print("准确率:")
print(1-errorCount/len(iris_y_test))

Python实现KNN算法

4.工程优化以及改进

1.采用Kd_TRee或者BALL_tree的数据结构来优化算法。在数据之间建立关联关系,然后查询关系,免去一一遍历的问题。
算法时间复杂度从(DN**2)降低到(O(DNlogN))

2、算法策略的改进。
1.紧邻的规则的改进(增加点的权重,某个半径内的点)
2.距离阈值的测量(欧式距离,余弦距离,曼哈顿距离)

5.算法小结及注意

5.1算法步骤小结

1.计算距离
2.递增排序
3.选择K个最近点(K一般选择基数)
4.统计K个最近点中类别数目最多的类

5.2数据预处理(数据归一化)

在实际使用KNN算法的过程中会注意到部分属性的数据值非常大,而部分属性的数据值非常小,有可能造成数据值大的属性起决定性作用,从而造成算法失效。因此需要对数据进行归一化的处理。数据归一化处理通常可以使用以下简单公式进行:
x ′ = x − m i n A m a x A − m i n A x^{'} = \frac{x-minA}{maxA-minA} x=maxAminAxminA
用python代码实现为:

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals,(m,1))
    normDataSet = normDataSet/np.tile(ranges,(m,1))
    return normDataSet,ranges,minVals

5.3 KNN距离计算

1.欧式距离
2.曼哈顿距离
3.闵可夫斯基距离

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值