Python——机器学习之近邻算法(KNN)

近邻算法——K-NearestNeighbor

如果一个待分类样本在特征空间中的k个最相似(即特征空间中K近邻)的样本中的大多数属于某一个类别,则该样本也属于这个类别,即近朱者赤,近墨者黑,这是一种监督学习。

在这里插入图片描述
例如:
在黑实线的圆圈内(只选3个邻居),有两个红三角一个蓝方块,那么系统认为?就是红三角
在黑虚线的圆圈内(只选5个邻居),有两个红三角三个蓝方块,那么系统认为?就是蓝方块

  1. 所以定的邻居数(n_neighbors)会影响最终的判断
    注意:n_neighbors过大会使训练模型欠拟合(过于粗糙,不论是当前训练集还是之后测试集表现都不好),过小会使训练模型过拟合(可能在训练集很准确,但是在新的测试集表现很差)

  2. 此外,距离度量的方式也有较大的影响,距离一般使用欧式距离或者曼哈顿距离
    在这里插入图片描述
      可以看出,欧氏距离是闵可夫斯基距离在 p=2时的特例,而曼哈顿距离是 p=1时的特例。

下面举上2个案例

鸢尾花实验

# 近邻算法
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
import matplotlib
import matplotlib.pyplot as plt

if __name__ == '__main__':
	#系统自带有鸢尾花数据
    datas = load_iris()
    #获取训练集(真正要训练的数据)和目标结果集(分类的结果)
    tarin, target = datas.data, datas.target
    # 为了知道n_neighbors取多少合适,我们要在一定范围内取值去测试
    #这里我训练1~33使,训练结果的正确率
    x = np.arange(1, 33)
    y = []
    for num in x:
    	#设置n_neighbors数
        knn = KNeighborsClassifier(n_neighbors=num)
        # 模型评估(交叉验证)
        # cv=10代表9份训练1份测试
        # scoring='accuracy'表示9次训练中每次的准确率
        arrmodel = cross_val_score(knn, tarin, target, cv=10, scoring='accuracy')
        # 9次训练结果准确率的平均值
        avgmodel = arrmodel.mean()
        #1~33次每次都放到y中
        y.append(avgmodel)
    print(y)

    # 设置中文
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    # 设置折线图
    plt.plot(x, y, 'pink')
    #加数字
    for x1, y1 in zip(x, y):
        plt.text(x1, y1, str(x1), ha='center', va='bottom', fontsize=12, rotation=0)
    plt.show()

在这里插入图片描述
x轴就是n_neighbors数,y就是准确率,从图中看到13、18、20正确率比较高,那么下次我们就让n_neighbors等于这些数,然后做后面测试集的预测分类就会比较准确

手写数字识别

在这里插入图片描述
上面是我准备的数据,.前面的数字表示我们的数字(也就是真正的分类结果),后面的表示这个数字有多少个训练数据,一共0~ 9,每个数字3000~4000的量

import matplotlib.pyplot as plt
import cv2
from sklearn.model_selection import cross_val_score
from sklearn.neighbors import KNeighborsClassifier

if __name__ == '__main__':
    # 训练集数组和训练目标数组(分类结果)
    tarin, target = [], []
    #
    new=[]
    # 利用循环读入0-9的每个3000张图片
    #num表示分类结果
    for num in range(10):
    	#flag表示每个分类中取都多少个数据进行训练
        for flag in range(300):
            target.append(num)
            #opencv去读取图片,会变成二维数组
            digit = cv2.imread("C:/Users/wuyanxiang/study/python/chenming/mnist_data/" + str(num) + "." + str(flag) + ".jpg")
            #将数组内RGB只拿第一个R值,否则RGB每个值都要计算,工作量太大
            res = digit[:, : , 0].reshape(784)
            #二值化,避免不同灰度值的影响
            for rn in range(len(res)):
                res[rn]=0 if res[rn]<128 else 255
            #放进训练数组里
            tarin.append(res)
      	#看工作进度
        print("--------"+str(num))
    #==================================
    #训练完后6效果最好
    # x = range(1, 55)
    # y = []
    # for k in x:
    #     knn = KNeighborsClassifier(n_neighbors=k)
    #	  准确率
    #     val = cross_val_score(knn, tarin, target, cv=20, scoring="accuracy").mean()
    #     print("========"+k)
    #     y.append(val)
    # plt.plot(x, y)
    # plt.show()
    # ==================================

	
	#weights='distance' 给每个邻居到点一个权重,距离越近权重越大,这样更合理
	#p=2 使用的是欧氏距离
	#n_jobs=-1 开启全核
    knn = KNeighborsClassifier(n_neighbors=6,weights='distance',p=2,n_jobs=-1)
    #正确率
    res = cross_val_score(knn, tarin, target, cv=20, scoring="accuracy").mean()
    #真正训练模型
    knn.fit(tarin,target)
    #对图片进行识别
    #test测试数据 test_target真正分类结果
    test,test_target=[],[]
    for rn in range(10):
        for co in range(300,310):
            test_target.append(rn)
            digit = cv2.imread("C:/Users/wuyanxiang/study/python/chenming/mnist_data/" + str(rn) + "." + str(co) + ".jpg")
            res = digit[:, :, 0].reshape(784)
            test.append(res)
    #预测结果
    pre=knn.predict(test)
    print("-------预测结果")
    print(pre)
    print("-------真实结果")
    print(test_target)
--------0
--------1
--------2
--------3
--------4
--------5
--------6
--------7
--------8
--------9
-------预测结果
[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3 3 3 5 3
 3 3 3 4 4 1 4 4 4 4 4 9 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7
 1 7 7 7 7 7 8 3 3 6 8 5 8 8 8 8 7 7 9 9 9 9 9 9 9 9]
-------真实结果
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值