机器学习 KNN近邻算法

什么是K近邻算法?

K近邻(K-nearst neighbors,KNN),是一种基本的分类与回归方法,简述说明就是给定一些训练数据集,对新的输入实例,在给定的训练数据集中找到与输入实例最相邻近的K个实例,若这K个实例的多数属于某个类,就把该输入实例分类到这个类中。kNN是一种基本的分类算法,在机器学习分类算法中占有相当大的地位,同时也是一种较于简单的数据分类统计技术方法。

算法思想

KNN是通过测量不同特征值之间的距离进行分类。一般先进行对数据的准备,列如收集、清洗和预处理数据。第二步确定用于比较样本之间相似性的度量方法,常见的如欧几里得距离、曼哈顿距离等,然后选择一个K值,找到与之最近样本用来对数据的预测评估以及优化;

欧氏距离(Euclidean Distance):也称欧氏距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。 在二维和三维空间中的欧氏距离就是两点之间的实际距离。

计算公式:

曼哈顿距离(Manhattan Distance):是种使用在几何度量空间的几何学用语,用以标明两个点在标准坐标系上的绝对轴距总和。

例如在平面上,坐标(x1,y1)的i点与坐标(x2,y2)的j点的曼哈顿距离为:

d(i,j)=|X1-X2|+|Y1-Y2|.

KNN中K值大小选择对模型的影响

当k值过小:

容易受到异常点的影响,容易过拟合,模型过于复杂

当k值过大:

受到样本均衡的问题,容易欠拟合,模型过于简单

KNN算法的优缺点

优点:

算法简单,易于实现,因为算法的复杂性并不高

参数量少,训练 KNN 算法时唯一需要的参数是 k 的值和我们想从评估指标中选择的距离度量的选择。
k近邻算法天生就支持多分类,区别与感知机、逻辑回归、SVM。

准确性高,对异常值和噪声有较高的容忍度。

缺点:

K近邻算法容易导致维度灾难,在高维空间中计算距离的时候,就会变得非常远;样本不平衡时,预测偏差比较大。k选值的大小会直接影响模型呈现(使用交叉验证的方法来确定k值的大小);

算法实现

数据准备:根据sklearn中提供的测试数据集来进行训练,这里引入的是鸢尾花卉(Iris)数据集,它是很常用的一个数据集。

代码实现:

#引入sklearn库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
if __name__ == '__main__':
    #获取sklearn库中鸢尾花的数据集
    iris = load_iris()
    data = iris.get("data")
    target = iris.get("target")
    #划分20%的测试集
    x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=0)
    #设置k值为5
    KNN = KNeighborsClassifier(n_neighbors=7)
    KNN.fit(x_train, y_train)
    #评价模型的准确程度
    train_score = KNN.score(x_train, y_train)
    test_score = KNN.score(x_test, y_test)
    print("模型的准确率:", test_score)
    # 输入带预测的数据
    X1 = np.array([[1.5, 3, 5.8, 2.2], [6.2, 2.9, 4.3, 1.3],[2.1,6.6,1.6,6.3]])
    prediction = KNN.predict(X1)
    k = iris.get("target_names")[prediction]
    #返回鸢尾花的类型(山鸢尾为Setosa、变色鸢尾为Versicolor、维吉尼亚鸢尾为Virginica)
    print("第一朵花的种类为:", k[0])
    print("第二朵花的种类为:", k[1])
    print("第二朵花的种类为:", k[2])
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from matplotlib.colors import ListedColormap
#导入iris数据
from sklearn.datasets import load_iris
iris = load_iris()
X=iris.data[:,:2] #只取前两列
y=iris.target
 
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y,random_state=42) #划分数据,random_state固定划分方式
#导入模型
from sklearn.neighbors import KNeighborsClassifier 
#训练模型
n_neighbors = 7
knn = KNeighborsClassifier(n_neighbors=n_neighbors)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
#查看各项得分
print("y_pred",y_pred)
print("y_test",y_test)
print("score on train set", knn.score(X_train, y_train))
print("score on test set", knn.score(X_test, y_test))
print("accuracy score", accuracy_score(y_test, y_pred))
 
# 可视化
 
# 自定义colormap
def colormap():
    return mpl.colors.LinearSegmentedColormap.from_list('cmap', ['#FFC0CB','#00BFFF', '#1E90FF'], 256)
 
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
axes=[x_min, x_max, y_min, y_max]
xp=np.linspace(axes[0], axes[1], 500) #均匀500的横坐标
yp=np.linspace(axes[2], axes[3],500) #均匀500个纵坐标
xx, yy=np.meshgrid(xp, yp) #生成500X500网格点
xy=np.c_[xx.ravel(), yy.ravel()] #按行拼接,规范成坐标点的格式
y_pred = knn.predict(xy).reshape(xx.shape) #训练之后平铺
 
# 可视化方法一
plt.figure(figsize=(15,5),dpi=100)
plt.subplot(1,2,1)
plt.contourf(xx, yy, y_pred, alpha=0.3, cmap=colormap())
#画三种类型的点
p1=plt.scatter(X[y==0,0], X[y==0, 1], color='blue',marker='^')
p2=plt.scatter(X[y==1,0], X[y==1, 1], color='green', marker='o')
p3=plt.scatter(X[y==2,0], X[y==2, 1], color='red',marker='*')
#设置注释
plt.legend([p1, p2, p3], iris['target_names'], loc='upper right',fontsize='large')
#设置标题
plt.title(f"3-Class classification (k = {n_neighbors})", fontdict={'fontsize':15} )
 
# 可视化方法二
plt.subplot(1,2,2)
cmap_light = ListedColormap(['pink', 'cyan', 'cornflowerblue'])
cmap_bold = ListedColormap(['darkorange', 'c', 'darkblue'])
plt.pcolormesh(xx, yy, y_pred, cmap=cmap_light)
 
# Plot also the training points
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold,
                edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title(f"3-Class classification (k = {n_neighbors})" ,fontdict={'fontsize':15})
plt.show()

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值