KNN算法(K近邻算法)

算法简介

KNN算法中文名称叫做K近邻算法,是众多机器学习算法里面最基础入门的算法。它是一个有监督的机器学习算法,既可以用来做分类任务也可以用来做回归任务。KNN算法的核心思想是未标记的样本的类别,由距离他最近的K个邻居投票来决定

在这里插入图片描述

算法三要素

  • (1).k值的选取
    在这里插入图片描述

在这里插入图片描述

  • 对于k值的选择,没有一个固定的经验,一般根据样本的分布,选择一个较小的值,可以通过交叉验证选择一个合适的k值。
  • 选择较小的k值,就相当于用较小的领域中的训练实例进行预测,训练误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是泛化误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
  • 选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少泛化误差,但缺点是训练误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
  • 一个极端是k等于样本数m,则完全没有分类,此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单。

在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法(简单来说,就是一部分样本做训练集,一部分做测试集)来选择最优的K值。

  • (2).距离度量的方式
    在这里插入图片描述
  • (3).分类决策规则

对于分类决策规则,一般都是使用多数表决法。所以我们重点是关注上面说的k值的选择和距离的度量方式。

KNN算法的应用场景

  • 文本分类

  • 用户推荐

  • 回归问题

KNN算法实现

import numpy as np
import matplotlib.pyplot as plt
import operator

# 已知分类的数据
x1 = np.array([3, 2, 1])
y1 = np.array([104, 100, 81])
x2 = np.array([101, 99, 98])
y2 = np.array([10, 5, 2])
# 画散点图
scatter1 = plt.scatter(x1, y1, c='r')
scatter2 = plt.scatter(x2, y2, c='b')
# 未知数据
x = np.array([18])
y = np.array([90])
scatter3 = plt.scatter(x, y, c='k')
# 画图例
plt.legend(handles=[scatter1, scatter2, scatter3], labels=['labelA', 'labelB', 'X'], loc='best')
plt.show()
# 已知分类的数据
x_data = np.array([
    [3, 104],
    [2, 100],
    [1, 81],
    [101, 10],
    [99, 5],
    [98, 2]
])
y_data = np.array(['A', 'A', 'A', 'B', 'B', 'B'])
x_test = np.array([18, 90])
# 计算样本数量
x_data_size = x_data.shape[0]
# 复制x_test
x_test_copy = np.tile(x_test, (x_data_size, 1))
# 计算x_test与每一个样本的差值
diffMat = x_test_copy - x_data
# 计算差值的平方
sqDiffMat = diffMat**2
# 求和(每行相加)
value_sum = sqDiffMat.sum(axis=1)
# 开方
distance = value_sum**0.5
# 从小到大排序(返回下标)
sortedDistance = distance.argsort()

count = {}
# 设置k的值
k = 5
for i in range(k):
    # 获取标签
    vote_label = y_data[sortedDistance[i]]
    # 统计标签数量
    count[vote_label] = count.get(vote_label, 0) + 1


# 因为字典的建存储是随机的,故需要对字典进行排序
# 根据operator.itemgetter(1)---第一个值对count排序,然后再取倒序
sorted_count = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
print("未知数所属的类是{}".format(sorted_count[0][0]))

# 未知数所属的类是A

在这里插入图片描述

KNN实战(iris分类)

import numpy as np
import operator
from sklearn import datasets  # sklearn自带的数据集
from sklearn.model_selection import train_test_split  # 切分数据集
from sklearn.metrics import classification_report, confusion_matrix
import random


def knn(x_test, x_data, y_data, k):
    # 计算样本数量
    x_data_size = x_data.shape[0]
    # 复制x_test
    x_test_copy = np.tile(x_test, (x_data_size, 1))
    # 计算x_test与每一个样本的差值
    diffMat = x_test_copy - x_data
    # 计算差值的平方
    sqDiffMat = diffMat ** 2
    # 求和(每行相加)
    value_sum = sqDiffMat.sum(axis=1)
    # 开方
    distance = value_sum ** 0.5
    # 从小到大排序(argsort函数返回的是数组值从小到大的索引值)
    sortedDistance = distance.argsort()

    count = {}
    for i in range(k):
        # 获取标签
        vote_label = y_data[sortedDistance[i]]
        # 统计标签数量
        count[vote_label] = count.get(vote_label, 0) + 1
    # 因为字典的建存储是随机的,故需要对字典进行排序
    # 根据operator.itemgetter(1)---第一个值对count排序,然后再取倒序
    sorted_count = sorted(count.items(), key=operator.itemgetter(1), reverse=True)
    return sorted_count[0][0]


# 载入数据
iris = datasets.load_iris()
# 切分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2)

'''
# 自己实现一个数据的切分
data_size = iris.data.shape[0]
index = [i for i in range(data_size)]
random.shuffle(index)    # shuffle() 方法将序列的所有元素随机排序
iris.data = iris.data[index]
iris.target = iris.target[index]

test_size = 40
x_train = iris.data[test_size:]
x_test = iris.data[:test_size]
y_train = iris.target[test_size:]
y_test = iris.target[:test_size]
'''

predictions = []
for i in range(x_test.shape[0]):
    predictions.append(knn(x_test[i], x_train, y_train, 5))

# 计算准确率和召回率
print(classification_report(y_test, predictions))
# 计算混淆矩阵
print(confusion_matrix(y_test, predictions))

'''
Backend TkAgg is interactive backend. Turning interactive mode on.
              precision    recall  f1-score   support
           0       1.00      1.00      1.00        11
           1       0.89      1.00      0.94         8
           2       1.00      0.91      0.95        11
    accuracy                           0.97        30
   macro avg       0.96      0.97      0.96        30
weighted avg       0.97      0.97      0.97        30


[[11  0  0]
 [ 0  8  0]
 [ 0  1 10]]

'''

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

!一直往南方开.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值