• [机器学习]-K近邻-最简单的入门实战例子


    本篇文章分为两个部分,前一部分主要简单介绍K近邻,后一部分是一个例子

    第一部分--K近邻简介

      从字面意思就可以容易看出,所谓的K近邻,就是找到某个样本距离(这里的距离可以是欧式距离,曼哈顿距离,切比雪夫距离等)最近的K个数据,根据最近的K个邻居属于什么分类,来判断这个样本属于什么分类。 

      简单说一下优缺点:

        优点:简单,适合于多分类问题(multi-modal,对象具有多个类别标签), kNN比SVM的表现要好。

        缺点:I:计算量大    II.如果某个分类占绝对优势,分类的效果很差,比如,印度阿三主要是黑人,如果你随便找个人,

           使用K近邻判断这个人是不是黑人,这个人周围可能都是黑人,所以不适合这种类型的数据集。

    第二部分--实战例子

      数据集:iris数据集,这是个什么样的数据集呢?

        通过3种鸢尾属植物的花的四个属性(萼片长度(sepal length)、萼片宽度sepalwidth)、花瓣长度(petal length)和花瓣宽度(petal width)) 来判断属于哪一种鸢尾属植物,这三种鸢尾属植物分别是setosa、versic010r和virginica。

      数据集地址:iris数据集     将数据复制到txt文件中。

      代码:

    import csv
    import random
    import math
    import operator
    
    #装载数据集
    def loadDataset(filename, split, trainingSet = [], testSet = []):
        with open(filename, 'rt') as csvfile:
            lines = csv.reader(csvfile)
            dataset = list(lines)
            for x in range(len(dataset)-1):
                for y in range(4):
                    # print(type(dataset[x][y]))
                    dataset[x][y] = float(dataset[x][y])
                if random.random() < split:
                    trainingSet.append(dataset[x])
                else:
                    testSet.append(dataset[x])
    
    #计算样本之间的欧式距离
    def euclideanDistance(instance1, instance2, length):
        distance = 0
        for x in range(length):
            distance += pow((instance1[x]-instance2[x]), 2)
        return math.sqrt(distance)
    
    #找到相邻的k个样本
    def getNeighbors(trainingSet, testInstance, k):
        distances = []
        length = len(testInstance)-1
        for x in range(len(trainingSet)):
            #testinstance
            dist = euclideanDistance(testInstance, trainingSet[x], length)
            distances.append((trainingSet[x], dist))
        """
            operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号
        """
        #distances是一个list里面放的tuple,tuple第二个元素是距离,这里就是根据距离排序,默认升序
        distances.sort(key=operator.itemgetter(1))
        neighbors = []
        for x in range(k):
            neighbors.append(distances[x][0])
        return neighbors
    
    #找到k个样本中出现最多的分类,并返回
    def getResponse(neighbors):
        classVotes = {}
        for x in range(len(neighbors)):
            response = neighbors[x][-1]
            if response in classVotes:
                classVotes[response] += 1
            else:
                classVotes[response] = 1
        """
            注意,python3中字典的iteritems()方法已经取消,只有item()
        """
        # sortedVotes = sorted(classVotes.iteritems(), key=operator.itemgetter(1), reverse=True)
        """
            sort 与 sorted 区别:
            sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
            list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
            reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)
        """
    
        """
            print(classVotes)
            输出格式为:{'Iris-versicolor': 1, 'Iris-virginica': 2}
        """
    
        """
            print(classVotes.items())
            输出格式为:dict_items([('Iris-versicolor', 1), ('Iris-virginica', 2)])
        """
        sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True)
    
        """
            print(sortedVotes)
            输出格式为:[('Iris-virginica', 3)]
        """
        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)))*100.0
    
    #主函数
    def main():
        #prepare data
        trainingSet = []
        testSet = []
        split = 0.67  #0.67相当于2/3,就是说2/3是训练集,1/3是测试集,整个iris数据集中有150个数据
        loadDataset(r'../data/DTree/irisdata.txt', split, trainingSet, testSet)
        # print(trainingSet)
        print ('训练集样本数: ' + repr(len(trainingSet)))
        print ('测试集样本数: ' + repr(len(testSet)))
        #generate predictions
        predictions = []
        k = 3
        for x in range(len(testSet)):
            # trainingsettrainingSet[x]
            neighbors = getNeighbors(trainingSet, testSet[x], k)
            result = getResponse(neighbors)
            predictions.append(result)
            if result == testSet[x][-1]:
                correct = True
            else:
                correct = False
            print ('预测结果:' + repr(result) + ', 实际值=' + repr(testSet[x][-1]) + ',  是否预测正确=' + repr(correct))
        accuracy = getAccuracy(testSet, predictions)
        #整个测试集预测准确率
        print('准确率: ' + repr(accuracy) + '%')
    
    if __name__ == '__main__':
        main()

    输出结果为:

    训练集样本数: 109
    测试集样本数: 41
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-setosa', 实际值='Iris-setosa',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-versicolor',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-versicolor', 实际值='Iris-virginica',  是否预测正确=False
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    预测结果:'Iris-virginica', 实际值='Iris-virginica',  是否预测正确=True
    准确率: 97.5609756097561%
  • 相关阅读:
    (转)android头像设置:从本地照片库或拍照获取并剪裁
    获取短信验证码之后按钮背景变化并且出现倒计时
    欢迎界面的下方指示位置圆
    android 关于Toast重复显示解决方法
    判断是不是电话号码
    (转)根据ImageView的大小来压缩Bitmap,避免OOM
    (转)android屏幕适配
    GSON解析JSON
    Linux-命令-cut
    Linux-自疑惑
  • 原文地址:https://www.cnblogs.com/gunduzi/p/10623013.html
Copyright © 2020-2023  润新知