天天看点

Python实现KNN算法KNN算法导入

KNN算法导入

KNN算法的大致思路如图所示。采用数据集是教材使用的燕尾花数据集。

Python实现KNN算法KNN算法导入

以下是在KNN函数中几个变量的用法

*

  • dist 列表 暂放训练集的点到测试点的距离
  • nearest 数组 对dist列表里的距离从大到小按索引排序返回的
  • valuest 列表 前k个距离最近的训练集的标签值(花的种类)
  • count 字典 统计每个种类出现的频率(种类:次数)*

对距离dist[]的大小进行从大到小排序按索引进行排序,以数组形式返回

nearest = np.argsort(dist)

进而获得前k个距离最近的训练集

利用字典count{}再对标签出现的次数统计 确定前k个点出现的频率。

count ={} #标签:次数
        for i in range(k):
            key = valuest[i]
            if(key in count.keys()):
                count[key]+=1
            else:
                count[key]=1
           

利用lambda再对字典中以值的大小从大到小排序,确定最多的那个类别

countList = sorted(count.items(),key = lambda x:x[1],reverse=True)
        test_result.append(countList[0][0])
           

代码

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn
import math
'''分析步骤:
1.计算测试数据和每个训练数据的距离;
2.对距离的大小进行从小到大排序
3.选取距离最小的k个点
4.确定前k个点类别的出现频率
5.出现频率最高的类别就是预测类别了'''
def loadDataSet(): #加载燕尾花数据
    from sklearn.model_selection import train_test_split
    from sklearn.datasets import load_iris
    iris_dataset = load_iris() #加载了数据集
    return train_test_split(iris_dataset['data'],iris_dataset['target'],random_state=0) #返回的形式是数组
def euclidean_Distance(X1,X2):#计算欧式距离
    distance = 0;
    distance =sum((X1 - X2)**2)
    return np.sqrt(distance)
#train:训练集  value:训练集标签  test测试集 k:指定邻近的个数
def knn(train,value,test,k):
    test_result=[]  #用来存放测试集标签(结果)
    for i in range(len(test)):#迭代每个测试数据
        dist =[] #暂放数据的距离的列表
        #计算每个测试数据和每个训练数据的距离
        for j in range(len(train)):
            dist.append(euclidean_Distance(train[j],test[i]))
        #对距离的大小进行从小到大排序 按索引进行排序
        nearest = np.argsort(dist)
        valuest = [value[m] for m in nearest[:k]] #获取前k个距离最近的训练集的标签值
        #对标签出现的次数统计 确定前k个点出现的频率
        count ={} #标签:次数
        for i in range(k):
            key = valuest[i]
            if(key in count.keys()):
                count[key]+=1
            else:
                count[key]=1
        #通过排序确定最多的那个类别
        countList = sorted(count.items(),key = lambda x:x[1],reverse=True)
        test_result.append(countList[0][0])
    return test_result;             
def main():
    k=3
    #train:训练集   train value:训练集标签   test  测试集数据  test——value:测试集标签
    train,test,train_value,test_value=loadDataSet()
    result=knn(train,train_value,test,k)
    print('数据集提供的测试集标签:',test_value)
    print('knn后测试集标签:',result)
    #计算精度
    m=0
    test_value = test_value.tolist()
    n = len(test_value)
    for i in range(n):
        if test_value[i]==result[i]: 
            m+=1
    accuracy = m/n
    print('knn分类后的精度为:',accuracy)   
main()

           

结果

Python实现KNN算法KNN算法导入

总结

  1. 对标签频率进行统计,参考了网络上的资料,很多都是使用collection中的Counter() 实现统计,而我使用更底层的算法:利用字典进行统计,键是种类,值是出现次数(频率),最后利用lambda表达式排序取最高的那一个;
  2. 在对距离的大小排序后获取训练数据样本对应的标签值上,dist[]列表来保存距离。使用了numpy库中的argsort( )对获取距离从小到大排序所对应dist[]的索引值(即:按索引进行排序),方便后面获取训练集的标签。比我一开始想的训练集多加一列,把距离加到那一列上,再进行排序方便了很多。
  3. 总体设计完后,感觉有些情况下用数组计算,会比其他的序列(列表、字

    典)等的直接计算更为方便。总体上,对Python接触还不够多,看似简单

    的一个作业,其实编码过程中还走了不少弯路。