文章目录

  • 概述
  • 一、关于几种距离
  • 1.欧拉距离
  • 2.曼哈顿距离
  • 3.明可夫斯基距离
  • 二、手动实现KNN
  • 1.建立数据集
  • 2.计算离预测点前K近的点
  • 3.根据占比预测
  • 总结一下KNN的优缺点:
  • 三、sklearn中的KNN
  • 1.参数介绍:
  • 2.预测鸢尾花数据集
  • 3.预测手写数字集



概述

回头来整理一下KNN算法的内容,简单来讲KNN算法是一种与距离有关的算法,是机器学习中的一种基于监督学习的一种方法。接下来我们先介绍几种距离的相关概念,然后手动用代码实现KNN,最后介绍sklearn中的KNN,并附上两个案例


一、关于几种距离

1.欧拉距离

其实就是我们高中所学的2点之间的距离,当维数增多时公式如下。

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_git

2.曼哈顿距离

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_数据集_02




我们直接看一眼三维的曼哈顿距离,多维的以此类推:

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_数据集_03

3.明可夫斯基距离

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_git_04


当p=1时,也就是曼哈顿距离,p=2时,是欧氏距离

当p趋近于无穷,是切比雪夫距离

二、手动实现KNN

1.建立数据集

先在x轴,y轴上建立一些点,并打上标签,画出图像,绿色代表0,红色代表1.

import numpy as np
import matplotlib.pyplot as plt

X = [[3.393533211, 2.331273381],
     [3.110073483, 1.781539638],
     [1.343808831, 3.368360954],
     [3.582294042, 4.679179110],
     [2.280362439, 2.866990263],
     [7.423436942, 4.696522875],
     [5.745051997, 3.533989803],
     [9.172168622, 2.511101045],
     [7.792783481, 3.424088941],
     [7.939820817, 0.791637231]
    ]
y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]

X_train = np.array(X)
y_train = np.array(y)

plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1], color='g') #前5个
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1], color='r')  #后5个
plt.show()

结果如下:

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_机器学习_05


很明显可以看出2堆数据的分布

我们再添加一个要预测的点,如下图蓝色的点,我们的目的是判断它属于哪一堆

x = np.array([8.093607318, 3.365731514])

plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1], color='g')
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1], color='r')
plt.scatter(x[0], x[1], color='b')
plt.show()

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_机器学习_06

2.计算离预测点前K近的点

计算一下预测点到所有点的距离

from math import sqrt
distances = []
for x_train in X_train:
    d = sqrt(np.sum((x_train - x)**2))
    distances.append(d)
distances

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_权重_07

用numpy.argsort函数,生成距离的从小到大的下标
我们统计前6个离蓝色点最近的6个点,查看他们的标签,可以看出在前6个点当中有5个是1,也就是红色点,一个是蓝色点

nearest = np.argsort(distances)
k = 6
topK_y = [y_train[neighbor] for neighbor in nearest[:k]]
topK_y

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_git_08

3.根据占比预测

最后查看最频繁的值,我们的结果类别是1,属于红色的点

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_机器学习_09


上面就是一个简单KNN算法的所有步骤了。

总结一下KNN的优缺点:

优点:
1.思想简单
2.能解决多分类问题
缺点:
1.效率低下
如果训练集有m个样本,n个特征,则预测
每⼀个新的数据,需要O(m*n)
2.⾼度数据相关
3.预测结果不具有可解释性
4.维数灾难



三、sklearn中的KNN

sklearn的 KNN官方链接

1.参数介绍:

def KNeighborsClassifier(n_neighbors = 5,
 weights=‘uniform’,
 algorithm = ‘’,
 leaf_size = ‘30’,
 p = 2,
 metric = ‘minkowski’,
 metric_params = None,
 n_jobs = None
 )
  • n_neighbors:这个值就是指 KNN 中的 “K”了。前面说到过,通过调整 K 值,算法会有不同的效果。
  • weights(权重):最普遍的 KNN 算法无论距离如何,权重都一样,但有时候我们想搞点特殊化,比如距离更近的点让它更加重要。这时候就需要 weight 这个参数了,这个参数有三个可选参数的值,决定了如何分配权重。参数选项如下:
    • ‘uniform’:不管远近权重都一样,就是最普通的 KNN 算法的形式。
    • ‘distance’:权重和距离成反比,距离预测目标越近具有越高的权重。
    • 自定义函数:自定义一个函数,根据输入的坐标值返回对应的权重,达到自定义权重的目的。
  • algorithm:在 sklearn 中,要构建 KNN 模型有三种构建方式,1. 暴力法,就是直接计算距离存储比较的那种放松。2. 使用 kd 树构建 KNN 模型 3. 使用球树构建。 其中暴力法适合数据较小的方式,否则效率会比较低。如果数据量比较大一般会选择用 KD 树构建 KNN 模型,而当 KD 树也比较慢的时候,则可以试试球树来构建 KNN。参数选项如下:
    • ‘brute’ :蛮力实现
    • ‘kd_tree’:KD 树实现 KNN
    • ‘ball_tree’:球树实现 KNN
    • ‘auto’: 默认参数,自动选择合适的方法构建模型
    不过当数据较小或比较稀疏时,无论选择哪个最后都会使用 ‘brute’
  • leaf_size:如果是选择蛮力实现,那么这个值是可以忽略的,当使用KD树或球树,它就是是停止建子树的叶子节点数量的阈值。默认30,但如果数据量增多这个参数需要增大,否则速度过慢不说,还容易过拟合。
  • p:和metric结合使用的,当metric参数是"minkowski"的时候,p=1为曼哈顿距离, p=2为欧式距离。默认为p=2。
  • metric:指定距离度量方法,一般都是使用欧式距离。
    • ‘euclidean’ :欧式距离
    • ‘manhattan’:曼哈顿距离
    • ‘chebyshev’:切比雪夫距离
    • ‘minkowski’: 闵可夫斯基距离,默认参数
  • n_jobs:指定多少个CPU进行运算,默认是-1,也就是全部都算。

2.预测鸢尾花数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

iris = datasets.load_iris()
X = iris.data #特征矩阵
y = iris.target #结果标签

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=666) #分割数据集

knn_clf = KNeighborsClassifier(n_neighbors=3)
knn_clf.fit(X_train, y_train) #训练
y_predict = knn_clf.predict(X_test)  #预测

print(y_predict)
print(knn_clf.score(X_test,y_test))  #评估分数
sum(y_predict == y_test) / len(y_test)

运行结果:

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_机器学习_10


可以看到用KNN预测鸢尾花效果还是比较好的

3.预测手写数字集

数据集:这个数字集不是mnist,要区分

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

digits = datasets.load_digits() #下载数据集 

X = digits.data 
y = digits.target

some_digit = X[666]

some_digit_image = some_digit.reshape(8, 8) #这里要改变一下形状,否则显示不了

import matplotlib
import matplotlib.pyplot as plt
plt.imshow(some_digit_image, cmap = matplotlib.cm.binary)
plt.show() #看一下图像

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_机器学习_11

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=666) #分割数据集

from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier(n_neighbors=4)
knn_clf.fit(X_train, y_train)
y_predict = knn_clf.predict(X_test)

knn_clf.score(X_test, y_test)

运行结果:

罗曼诺夫斯基准则 java 罗曼诺夫斯基准则代码_罗曼诺夫斯基准则 java_12