参考链接: K means聚类Python–简介
分类算法 – KNN算法
KNN(K-Nearest Neighbor)是一个分类算法,属于有监督学习。 KNN思想的核心在于:近朱者赤,近墨者黑,根据新样本的k个最近邻居来判定其类别。
1. 理论说明
1.1 算法概论
假设我们已知n个样本的特征和标签(即所属分类),并以此作为样本集A。
当输入一个没有标签的样本b时,我们可以通过比较新样本b与样本集A中的数据对应的特征,然后提取出最为相似的k个数据。
最后我们选取k个最相似的数据中出现次数最多的分类,作为新数据的分类。
1.2 算法步骤
Step 1:计算已知类别的样本集A中的所有样本与新样本b之间的距离 Step 2:按照距离的递增次序,对样本集A中的样本进行排序 Step 3:选取与当前样本b距离最近的k个样本 Step 4:确定这k个样本所在类别的出现频率 Step 5:返回这k个样本中出现频率最高的类别作为当前样本b的预测分类
1.3 算法优劣
优势:精度高、对异常值不敏感、算法思想简单、比较适合多分类问题 劣势:计算成本高,中间步骤的储存成本高,对大规模数据不是很友好
1.4 详细问题
①k的选择
和聚类分析中的K-means算法相同,k的选择也是KNN方法的难点所在。
若k很小,结果容易受到噪声和极端值的影响;若k很大,则在选取的近邻中又包含很多无关的点,增加计算量的同时也影响计算结果。 根据经验,我们一般会让k小于样本集A中样本数量的平方根
②距离的度量
在算法中,我们明确说明了要计算已知类别的样本集A中的所有样本与新样本b之间的距离。那我们需要选择哪种距离呢?
当样本特征的单位相同、方差差距不大时,此时选择欧式距离是合理的; 当样本特征的单位不同,并且方差差距较大时,选择欧式距离会更加关注方差大的特征而忽视方差较小的特征,所以此时选取马氏距离效果较好。
2.python实现
2.1 KNN函数(不调包)
此处,python实现KNN算法,不使用python包sklearn 使用的是欧式距离,并且各个样本权重均相同
import pandas as pd
import numpy as np
from collections import Counter
#导入数据
data = pd.read_excel('........xlsx')
train_X = data[['','',''...]] #按列选择自变量
train_Y = data[['..']] #按列选择因变量
test_X = [] #设置待分类样本
#定义KNN函数,直接返回分类
def KNN(train_X,train_Y,test_X,k):
'''需要输入的数据包括训练集的自变量、训练集的因变量、待测试的数据、k'''
'''首先计算欧式距离,并对其排序'''
dist = (np.tile(test_X,(train_X.shape[0],1)) - train_X)**2
distances = (dist.sum(axis=1))**0.5 #计算欧式距离,并且使各个观测的权重相同
sorteddist = distances.argsort() #将数据从小到大排序,返回的是编号
'''选出距离前k小的数据的类别,存放在count中'''
count = []
for i in range(k):
count.append(train_Y[sorteddist[i]])
'''返回出现次数最多的类别'''
return Counter(count).most_common(1)[0][0]
2.2 python实例
此处,我们将使用sklearn包
2.2.1 数据简介
本案例使用的是sklearn包中的鸢尾花数据集 数据包含三种鸢尾花的四个特征:花萼长度(cm)、花萼宽度(cm)、花瓣长度(cm)、花瓣宽度(cm)。 数据共有150个观测,我们将其以8:2分成训练集和测试集
2.2.2 实现环境
python 3.7 & sklearn
2.2.3 实现代码
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
#导入数据
iris = datasets.load_iris()
iris_X = iris.data
iris_Y = iris.target
#将数据分成训练集和测试集,比例为:80%和20%
iris_train_X , iris_test_X, iris_train_Y ,iris_test_Y = train_test_split(
iris_X, iris_Y, test_size=0.2,random_state=0)
#设置KNN算法的参数
KNN =KNeighborsClassifier(algorithm='auto', #在KNN中使用的算法,其他选项还有ball_tree,kd_tree,和brute
leaf_size=30, #当使用和树有关的算法时的叶子数量
metric='minkowski',p=2, #使用的是明可夫斯基距离中的欧式距离
metric_params=None,
n_jobs=1, #并行计算的线程数量
n_neighbors=3, #分成5类(默认)
weights='distance' #距离计算中使用的权重,distance表示按照距离的倒数加权,uniform表示各样本权重相同
)
#将KNN算法应用在训练集上
KNN.fit(iris_train_X, iris_train_Y)
#将结果应用于测试集中
predict = KNN.predict(iris_test_X)
print(predict)
#计算模型的正确率
print(KNN.score(iris_test_X, iris_test_Y))
#正确率为100%
KNN算法的参数选择
2.2.4 本例总结
本例中最重要的就是KNN中参数的选择: algorithm=auto;weights=uniform时,正确率为0.9666 algorithm=auto;weights=distance时,正确率为1.0000
本数据集的问题在于样本量太小