KNN算法

一 KNN算法介绍

K-近邻算法(K Nearest Neighbor,简称KNN).比如根据你的“邻居”来推断出你的类别.

KNN算法思想:如果一个样本在特征空间中的 k 个最相似的样本中的大多数属于某一个类别,则该样本也属于这个类别 .

KNN算法的应用方式:

  • 分类问题处理:

    1.计算未知样本到每一个训练样本的距离

    2.将训练样本根据距离大小升序排列

    3.取出距离最近的 K 个训练样本

    4.进行多数表决,统计 K 个样本中哪个类别的样本个数最多

    5.将未知的样本归属到出现次数最多的类别

  • 回归问题处理:

    1.计算未知样本到每一个训练样本的距离

    2.将训练样本根据距离大小升序排列

    3.取出距离最近的 K 个训练样本

    4.把这个 K 个样本的目标值计算其平均值

    5.平均值作为未知的样本预测值

二 KNN算法API

# 导包 
from sklearn.neighbors import KNeighborsClassifier,KNeighborsRegressor # 分类算法,回归算法

2.1 KNeighborsClassifier 分类算法

英文翻译:
    KNeighborsClassifier # 分类算法  
    estimator # 估量值 估计器

例句:

estimator = KNeighborsClassifier(n_neighbors=3)  

API解释:
    KNeighborsClassifier() # 创建分类算法对象
    n_neighbors=n          # 参数 k 的值 即几个样本(邻居)

应用场景:标签不连续通过分类思想解决.

2.2 KNeighborsRegressor 回归算法

英文翻译:
    KNeighborsRegressor # 回归算法  
    estimator # 估量值 估计器

例句:

estimator = KNeighborsRegressor(n_neighbors=4)

API解释:
    KNeighborsRegressor()  # 创建回归算法对象
    n_neighbors=n          # 参数 k 的值 即几个样本(邻居)

应用场景:标签连续通过回归思想解决.

三 两个经典案例

3.1 鸢尾花案例

本案例通过提取鸢尾花的特征,通过数据集训练模型使其可以分辨不同种类的鸢尾花.在Anaconda2024版本中已经集成了鸢尾花的数据集.方便大家直接使用.

1

2

# 0. 导包
from sklearn.datasets import load_iris  # 加载鸢尾花数据集
import seaborn as sns                   # Seaborn绘图
import matplotlib.pyplot as plt         # matplotlib
import pandas as pd                     # pandas
from sklearn.model_selection import train_test_split  # 切割训练集和测试集
from sklearn.preprocessing import StandardScaler      # 数据标准化处理
from sklearn.neighbors import KNeighborsClassifier    # KNN算法 分类对象
from sklearn.metrics import accuracy_score            # 模型评估

# 1.定义函数 用于加载鸢尾花数据集 并简单查看数据集各部分
def dm01_load_iris():
    # 1.1加载数据集
    iris_data = load_iris()
    # 1.2 打印数据集
    # print(iris_data)
    # 1.3 #打印所有的键 即属性名
    # dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
    # print(iris_data.keys())
    # 1.4 查看数据集字段特征
    print(iris_data.data[:5])
    # 1.5 查看数据集的标签字段
    print(iris_data.target[:5])
    # 1.6 查看数据集的标签名
    # ['setosa' 'versicolor' 'virginica']
    print(iris_data.target_names)
    # 1.7 查看数据集的特征名
    # ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
    print(iris_data.feature_names)
    # 1.8 查看数据集描述信息
    # print(iris_data.DESCR)
    # 1.9 查看数据集文件名
    # print(iris_data.filename)
    # 1.10 查看数据集 数据模型
    # print(iris_data.data_module)

# 2.定义函数 用于通过 Seaborn散点图的方式 对鸢尾花数据集进行可视化
def dm02_show_iris():
    # 1.加载鸢尾花数据集
    iris_data = load_iris()
    # 2.封装成DF 对象 作为可视化展示的数据源
    iris_df = pd.DataFrame(iris_data.data,columns=iris_data.feature_names)
    # 3.给DF 对象新增1列 表示:标签
    iris_df['label'] = iris_data.target
    print(iris_df)
    # 4.可视化 散点图
    # x: x轴值, 这里是: 花瓣的长度,  y: y轴值, 这里是: 花瓣的宽度,  hue: 颜色(根据鸢尾花的标签来分组, 不同分组颜色不同), fit_reg=False, 不绘制拟合回归线.
    sns.lmplot(data=iris_df,x='petal length (cm)',y='petal width (cm)',hue='label',fit_reg=False)
    # 设置标题
    plt.title('iris data')
    # 绘图
    plt.show()
    
if __name__ == '__main__':
    # dm01_load_iris()
    dm02_show_iris()

3

# 3.定义函数实现划分训练集和测试集
def dm03_train_test_split():
    # 1.加载数据集
    iris_data = load_iris()
    # 2. 划分训练集和测试集
    # iris_data.data => 特征, 一共150条
    # iris_target => 标签, 一共150条
    # test_size => 测试集占比, 0.2 => 训练集 : 测试集 => 8 : 2
    # random_state => 随机种子, 如果种子一样, 则每次划分的数据集都是一样的.
    # 细节: 返回值的时候, 注意下四个参数的顺序, 即: 训练集特征, 测试集特征, 训练集标签, 测试集标签.
    x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.2,random_state=66)
    # 3.打印划分后的结果
    print(f'训练集,x-特征:{len(x_train)}')
    print(f'测试集,x-特征:{len(x_test)}')
    print(f'训练集,y-标签:{len(y_train)}')
    print(f'测试集,y-标签:{len(y_test)}')

# 4.定义函数 实现模型预测和评估
def dm04_predict():
    # 1.加载数据
    iris_data = load_iris()
    # 2.数据预处理 因数据量小且Anaconda2024提前处理过 这里只划分训练集与测试即可
    x_train, x_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size=0.2,random_state=66)
    # 3.特征工程
    # 3.1 特征提取:查看训练集的 特征, 因为特征是已经提取好的, 所以无需我们手动提取了, 即, 特征为: 花萼的长度, 花萼的宽度, 花瓣长度, 花瓣的宽度.
    # print(x_train)
    # 3.2 特征预处理
    # 创建标准化对象
    transfer = StandardScaler()
    # 标准化训练集的特征
    x_train = transfer.fit_transform(x_train)
    # 查看结果
    # print(x_train)
    # 标准化测试集的特征
    x_test = transfer.transform(x_test)

    # 4.模型训练(机器学习)
    # 4.1 创建估计器对象
    estimator = KNeighborsClassifier(n_neighbors=5)
    # 4.2 模型训练
    estimator.fit(x_train,y_train)  # 传入 训练集的特征和标签

    # 5.模型预测
    # 场景1
    # 对测试集预测 得到预测后的测试集标签
    y_predict = estimator.predict(x_test)
    print(f'测试集预测结果为{y_predict}') # [1 0 0 0 1 1 0 2 0 0 1 1 2 2 0 2 1 1 0 2 2 1 2 1 0 1 0 0 1 2]
    # 场景2 对新数据集做预测
    # step1:定义新的数据集
    my_data = [[2.1, 3.5, 5.6, 3.2]]
    # step2:对新数据集标准化处理
    my_data = transfer.transform(my_data)
    # step3:对新数据集做结果分类预测,打印预测结果
    my_predict = estimator.predict(my_data)
    print(f'新数据集预测结果为{my_predict}')  # 新数据集预测结果为[1]
    # step4:对新数据集做概率预测,看看在各个标签中的概率
    my_predict_proba = estimator.predict_proba(my_data)
    print(f'新数据集在各标签概率预测为{my_predict_proba}') # [[0.  0.6 0.4]] 即 占 0 1 2的概率

    # 6. 模型评估 KNN(K近邻算法), 评估指标主要是: 预测的准确率.
    # 方式1 直接评估 获取准确率
    print(f'直接评估准确率为{estimator.score(x_test,y_test)}')  # 传入测试集特征和标签 # 0.9

    # 方式2 用真实值和预测值评估得到准确率
    print(f'真实值和预测值对比评估结果为{accuracy_score(y_test,y_predict)}')  # 传入测试集标签和预测值标签 # 0.9



if __name__ == '__main__':
    # dm03_train_test_split()
    dm04_predict()

3.2 手写数字识别案例

MNIST_data

# 背景相关
MNIST手写数字识别 
1999年发布,成为分类算法基准测试的基础
MNIST仍然是研究人员和学习者的可靠资源

# 需求
从数万个手写图像的数据集中正确识别数字.
(超级经典的案例,数据集网络资源丰富,本文只手撕代码.)
# 导包
import matplotlib.pyplot as plt                         # matplotlib绘图
import pandas as pd                                     # pandas
from sklearn.model_selection import train_test_split    # 分割训练集和测试集
from sklearn.neighbors import KNeighborsClassifier      # KNN 分类算法
import joblib                                           # 加载或保存模型
from collections import Counter                         # 分组计数

# 1. 定义函数用于查看数字图片
def show_digit(idx):
    """
    定义函数用于查看数字图片
    :param idx: 行索引
    :return: 无
    """
    # 1.读取数据 获取df对象
    data = pd.read_csv('data/手写数字识别.csv')
    # 细节: 非法值校验
    if idx < 0 or idx > len(data)-1:
        return
    # 2. 获取数据: 特征+标签
    x = data.iloc[:,1:]  # 所有行,第二列到最后
    y = data.iloc[:,0]   # 所有行,第一列
    # 3. 查看数据集
    print(f'x的维度{x.shape}')         # (42000, 784)
    print(f'y的各分类数量{Counter(y)}') #Counter({1: 4684, 7: 4401, 3: 4351, 9: 4188, 2: 4177, 6: 4137, 0: 4132, 4: 4072, 8: 4063, 5: 3795})
    # 4.获取具体的某张图片 某一行数据等于一条样本数据
    # step1 把一条样本数据转成(28,28)的二维数组 即模拟28*28像素的图片
    digit = x.iloc[idx].values.reshape(28,28)
    # step2 显示图片
    plt.imshow(digit,cmap='gray')  # cmap='gray'  灰色显示 即 灰度图
    # step3 取消坐标显示
    plt.axis('off')
    # step4 绘图
    plt.show()  # 8
    
# 在main函数中测试
if __name__ == '__main__':
    # 显示数字图片
    show_digit(10)

8

# 2.训练模型
def train_model():
    # 1.读取数据 获取df对象
    data = pd.read_csv('data/手写数字识别.csv')
    # 2.获取数据 特征+标签
    x = data.iloc[:,1:]
    y = data.iloc[:,0]
    # 3.特征预处理
    # step1 X轴(像素点)的归一化处理
    x = x / 255
    # step2 划分训练集和测试集
    # stratify=y 按照y的类别比例进行分割
    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,stratify=y,random_state=66)
    # 4.训练模型
    estimator = KNeighborsClassifier(n_neighbors=3)
    estimator.fit(x_train,y_train)
    # 5.模型评估 评测正确率
    my_score = estimator.score(x_test,y_test)
    print(f'模型评估的正确率为{my_score}')   # 0.9657142857142857
    # 6.保存模型
    joblib.dump(estimator,'model/knn.pth')

# 3. 测试模型
def use_model():
    # 1.加载图片
    img = plt.imread('data/demo.png')  # 28 * 28像素
    plt.imshow(img,cmap='gray') # 灰度图
    plt.show() # 2

shuzi_2

	# 2.加载模型
    estimator = joblib.load('model/knn.pth')

    # 3.预测图片
    img = img.reshape(1,-1)  # 1行 所有列 等同于 (1, 784)
    y_test = estimator.predict(img)
    print(f'预测的数字是{y_test}')  # [2]

# 在main函数中测试
if __name__ == '__main__':
    # 训练模型
    # train_model()  # 0.9657142857142857
    # 测试模型
    use_model()

以上就是要和大分享的KNN算法相关内容,机器学习算法还有很多,后面我还会持续分享其他训练模型的算法.我们下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值