KNN-k近邻回归,K-NearestNeighbour:k个最近的邻居。每个样本都可以用它的最接近的K个邻近值来代表。

首先引入问题?面对如下数据,我们该如何将电影分类呢?

 通过对比打斗镜头和接吻镜头,一方大于另一方,也就是说,这个电影与某一特征非常接近,并且有大量的出现次数,就可判断。

当我们在数据集中判断数据特征属于哪一类别,就需要以上方式,Knn算法。

算法说明:

  1. 输入没有标签的新数据,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。

  2. 一般来说,只选择样本数据集中k个最相似的数据。k一般不大于20,最后选择k个数据中出现次数最多的分类,作为新数据的分类。

 

 主要看K的最适合的选择

那么如何选择K呢?

  1. 计算已知类别数据集众多点与当前点之间的距离:计算两点距离

  2. 按照距离递增次序排序

  3. 选取与当前点距离最小的k个点:选择距离最小的点

  4. 确定前k个点所在类别的出现频率

  5. 返回前k个点出现频率最高的类别作为当前点的预测分类

两个距离度量

1.欧式距离:简单来说,就是点的距离

  • 二维空间里的欧氏距离公式:

  •  三维空间里的欧氏距离公式:

  • n 维空间里的欧氏距离公式:

    2.曼哈顿距离

标明两个点在标准坐标系上的绝对轴距总和。

在平面上,坐标(x1,y1)的i点与坐标(x2,y2)的j点的曼哈顿距离为:d(i,j)=|X1-X2|+|Y1-Y2|。

绿色为欧氏距离,其余为曼哈顿距离。

典型的项目:鸢尾花

对花瓣,花萼的宽度和长度进行回归分析预测 

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset  导入数据
dataset = pd.read_csv('E:\LianXi\机器学习\Iris-data.csv')
dataset.head()

#drop Id column  删除第Id列
dataset = dataset.drop('Id',axis=1)
dataset.head()

# shape
# print(dataset.shape)

# # more info on the data 有关数据的更多信息
# print(dataset.info())
#
# # descriptions
# print(dataset.describe())
#
# # class distribution  阶级分布
# print(dataset.groupby('Species').size())



# 未分组:变量之间的散点矩阵图
from pandas.plotting import scatter_matrix
# scatter plot matrix
scatter_matrix(dataset,figsize=(10,10))
plt.show()

#分组后:散点矩阵图,diag_kind=“kde”:kde密度曲线,如果不加则下图对角线处默认为柱状图。
# updating the diagonal elements in a pairplot to show a kde
sns.pairplot(dataset, hue="Species",diag_kind="kde",markers='+')

#
# Importing metrics for evaluation  应用不同的分类
from sklearn.metrics import confusion_matrix     #计算混淆矩阵以评估分类的准确性
from sklearn.metrics import classification_report   #显示主要的分类指标,返回每个类标签的精确、召回率


# X = dataset.iloc[:, :-1].values  #前四列
# y = dataset.iloc[:, -1].values   #最后一列
X=dataset[['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']]
y =dataset['Species']

# Splitting the dataset into the Training set and Test set   将数据集拆分为训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 1)


# K-Nearest Neighbours
from sklearn.neighbors import KNeighborsClassifier

classifier = KNeighborsClassifier(n_neighbors=8)
classifier.fit(X_train, y_train)

y_pred = classifier.predict(X_test)

# Summary of the predictions made by the classifier    #预测摘要
print(classification_report(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
# Accuracy score
from sklearn.metrics import accuracy_score
print('accuracy is',accuracy_score(y_pred,y_test))



# experimenting with different n values   用不同k值实验
k_range = list(range(1, 20))
scores = []
for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X, y)
    y_pred = knn.predict(X)
    scores.append(accuracy_score(y, y_pred))

plt.plot(k_range, scores)
plt.xlabel('Value of k for KNN')
plt.ylabel('Accuracy Score')
plt.title('Accuracy Scores for Values of k of k-Nearest-Neighbors')
plt.show()

数据集:链接:https://pan.baidu.com/s/1apV6wx9plvv9Yir0l8ExAQ?pwd=373z 
               提取码:373z

我们得到这张图时,发现有几个点的准确率都很高,甚至k=1,达到1的准确率,但如何选择呢?

k=1,数据集太小了,容易造成过拟合,很多细节都收入,例如噪声等。k=15,达到0.98,但是数据太多了,分析不到位,达到欠拟合,我们可以把其他点代入进去,发现只有k=8,准确率完全等于一,此时k=8就是我们要的最合适的值。

总结:knn算法用于预测某些特征是否满足,最终来预测,k的值如何选取是个重要问题,如果太小,细节处理太多,会造成过拟合,k太大,会造成欠拟合。

knn也有缺点:

1.计算量大,尤其是特征数非常多的时候

2.样本不平衡的时候,对稀有类别的预测准确率低

3.慵懒散学习方法,基本上不学习,导致预测时速度比起逻辑回归之类的算法慢

如果学习了其他算法,knn就劣势很多了。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐