KNN算法的简单实现

KNN算法
一,问题分析
KNN最邻近分类算法的实现原理:为了判断未知样本的类别,以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与未知样本距离最近的K个已知样本,再以k个样本中占多数的类别作为预测结果。
算法中关键的点是“距离”的计算和占多数类的判断。距离的计算,本次采用欧氏距离,以二维平面为例,这里的“距离”在数学上即为两点的直线距离,公式如下:
在这里插入图片描述
三维或更高维在此基础上扩展即可。如三维即有三个特征的样本,公式变为
在这里插入图片描述
要完成knn算法的实现,参考课本鸢尾花预测模型的实现,主要做以下几个事情:
1,定义鸢尾花数据集my_iris_datasets
2,定义数据集拆分函数my_train_test_split
3, 定义计算欧式距离的函数
4,自己定义一个分类器
4,定义fit函数
5,定义计算精确度的函数score
二,程序设计
1,数据集的定义
加载下载好的iris数据文本文件,将文件内的数据存入列表,存入列表内的元素仍为列表,包含鸢尾花的4个特征和所属种类。加载需用到csv模块
在这里插入图片描述

2,拆分函数
将加载的数据集拆成两部分(训练集合数据集),做法是遍历数据集,利用随机数生成函数生成0到1的小数,判断和给定的某个拆分比例值得大小,小则将样本放在训练集train_set,否则放在测试集test_set,需要导入random模块
在这里插入图片描述
3,欧式距离计算函数
这一部分通过给定两个样本实例,和样本特征个数,循环样本的特征数次,循环体内用公式计算欧式距离即可,最后把每个维度的差的平方和开方返回即可。
在这里插入图片描述
4,KNNclassifier类的定义
参考书本,在构造函数内定义训练集列表train_set和测试集列表test_set,邻近数K,将参数n_neighbors赋值给K,定义fit函数,对于KNN算法,要做的就是将数据集赋给训练集,
定义评估函数score。
在这里插入图片描述
5,模型评估函数
评估模型需要遍历测试集的数据,每一个样本计算和训练集样本的欧氏距离进行计算后,选取最邻近的k个,放入列表中,判断类别最多的作为预测结果,和已知标签比对,最终得到正确率。
在这里插入图片描述
三,代码实现

# import pdb
import math
import csv
import operator
import random
import numpy as np

# pdb.set_trace()
# 加载鸢尾花卉数据集:给定路径,将文件数据存入列表
def loadIrisDataset(filename):
    with open(filename, 'rt') as csvfile:
        lines = csv.reader(csvfile)      
        dataset = list(lines)
        for x in range(len(dataset)):
            for y in range(4):
                dataset[x][y] = float(dataset[x][y])
        return dataset
    
# 拆分数据集,返回训练集和测试集两个列表 :
#dataset(要拆分的数据集) split(训练集所占比例) trainingSet(训练集) testSet(测试集)
def splitDataSet(dataSet, split ):
    trainingSet=[]
    testSet = []
    for x in range(len(dataSet)):
        if random.random() <= split:
            trainingSet.append(dataSet[x])
        else:
            testSet.append(dataSet[x])
    print(len(trainingSet))
    print(len(testSet))
    return trainingSet,testSet
# 计算欧氏距离 dimension:维度,即样本特征数
def euclideanDistance(sample1, sample2, dimension):
    distance = 0
    for x in range(dimension):
        distance += pow((sample1[x] - sample2[x]), 2)
    return math.sqrt(distance)
 
# 选取距离最近的K个实例,以某一个测试集样本为参照,与训练集中每一个样本求欧氏距离
def getNeighbors(trainingSet, testSample, k):
    distances = []
    #求取样本特征数,减1是因为样本最后一个数值为样本标签,即样本所属类别
    demension = len(testSample) - 1
    for x in range(len(trainingSet)):
        dist = euclideanDistance(testSample, trainingSet[x], demension)
        distances.append((trainingSet[x], dist))
    distances.sort(key=operator.itemgetter(1))
    #选取前k个距离
    neighbors = []
    for x in range(k):
        neighbors.append(distances[x][0])
    return neighbors
 
#  获取距离最近的K个实例中占比例较大的分类
def chooseNearest(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True)
    return sortedVotes[0][0]
 
# 计算准确率
def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(testSet))) 
class my_KNNClassifier:
    def __init__(self,n_neighbors):
        self.train_set=[]
        self.test_set=[]
        self.k = n_neighbors
    def fit(self,train_set,test_set):
        self.train_set = train_set
        self.test_set = test_set
    def score(self):
        predictions = []
        for x in range(len(test_set)):
            neighbors = getNeighbors(train_set, test_set[x], self.k)
            result = chooseNearest(neighbors)    
            predictions.append(result)
        accuracy = getAccuracy(test_set, predictions)
        print("Accuracy:{:.2f}".format(accuracy))              
if __name__=='__main__':
    # 使用鸢尾花卉数据集进行分类
    dataSet = loadIrisDataset(r'E:\\Download\\iris_dataset.txt')
    train_set,test_set = splitDataSet(dataSet, 0.75)
    classifier = my_KNNClassifier(n_neighbors=1)
    classifier.fit(train_set,test_set)
    classifier.score()

四,程序调试和运行
此次是在juputer notebook环境下运行,首次运行时,对读取的文件数据处理没有到位,出现下面的错误:
在这里插入图片描述
错误原因是加载得到的数据集里的元素是NoneType类型,还需要把数据部分转化为实数。解决办法是将所有样本的数据部分实数化,如下图:
在这里插入图片描述
其他还出现了拼写等小错误,并未列举,运行结果如下:
在这里插入图片描述
5 .总结
通过本次KNN算法的简单实现,对算法有了更加深刻的认识,KNN的分类过程关键是算待测样本和已有数据之间的一个“距离”,以及挑出最小的几个。本次采用了欧式距离,其他还有什么Mahalanobis距离,Bhattacharyya距离等,算法简单易懂,但这也是算法的缺点,要遍历已有数据样本,得到n个距离,再找最近的k个,还要找最多的标签,最终对样本标签做出预测。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值