zoukankan      html  css  js  c++  java
  • 机器学习-KNN算法

    KNN思想

    • 如果一个样本在特征空间中的k个最相似的样本中的大多数属于某一个级别,则该样本也属于这个级别
    • 少数服从多数的原则

    实现KNN算法方式

    1. 计算要预测的样本与空间中所有样本的距离
    2. 取出与当前样本距离最近的K个样本
    3. 统计这个K个样本中,大部分属于哪一个类别
    4. 大部分属于哪一个类别, 那么这个就可以预测出属于这个类别

    距离测度公式

    • 欧式距离,两点之间的直线距离
    • 平方欧式距离
    • 曼哈顿距离 没有斜路

       绿色和红色距离一样

    • 余弦距离

       伊朗10次和1次的余弦角是0,所以一类

    • 闵可夫斯基距离,对几组距离的定义

     

    代码

    import numpy as np
    import operator
    import matplotlib.pyplot as plt
    from array import array
    from matplotlib.font_manager import FontProperties
    
    
    def file2matrix(filePath):
        fr = open(filePath)
        #     readlines:是一次性将这个文本的内容全部加载到内存中(列表)
        arrayOflines = fr.readlines()
        numOflines = len(arrayOflines)
        returnMat = np.zeros((numOflines, 3))
        classLabelVector = []
        index = 0
        for line in arrayOflines:
            line = line.strip()
            print(line.split('	'))
            listFromline = list(map(float, line.split('	')))
            returnMat[index, :] = listFromline[0:3]
            classLabelVector.append(int(listFromline[-1]))
            index += 1
        return returnMat, classLabelVector
    
    
    '''
        将训练集中的数据进行归一化
        归一化的目的:
            训练集中飞行公里数这一维度中的值是非常大,那么这个纬度值对于最终的计算结果(两点的距离)影响是非常大,
            远远超过其他的两个维度对于最终结果的影响
        实际约会姑娘认为这三个特征是同等重要的
        下面使用最大最小值归一化的方式将训练集中的数据进行归一化
    '''
    def autoNorm(dataSet):
        #     dataSet.min(0)   代表的是统计这个矩阵中每一列的最小值     返回值是一个矩阵1*3矩阵
        minVals = dataSet.min(0)
        maxVals = dataSet.max(0)
        ranges = maxVals - minVals
        m = dataSet.shape[0]
        #     normDataSet存储归一化后的数据
        # normDataSet = np.zeros(np.shape(dataSet))
        # 把最小值minVals复制m份,每份复制一次
        info = np.tile(minVals, (m, 1))
        normDataSet = dataSet - info
        # (每个值 - 最小值)矩阵 / (最大值 - 最小值)矩阵
        normDataSet = normDataSet / np.tile(ranges, (m, 1))
        return normDataSet, ranges, minVals
    
    # normMat第几行 i *3
    # normMat_1000 所有的评级标准
    # datingLables_1000 所有的好感度
    def classify(normMat_i, normMat_1000, datingLables_1000, key):
        dataSetSize = normMat_1000.shape[0]
        # 求两点间的距离
        diffMat = np.tile(normMat_i, (dataSetSize, 1)) - normMat_1000
        sqDiffMat = diffMat ** 2
        # 矩阵横着加
        sqDistances = sqDiffMat.sum(axis=1)
        distance = sqDistances ** 0.5
        sortedDistIndicies = distance.argsort()
        #     classCount保存的K是魅力类型   V:在K个近邻中某一个类型的次数
        classCount = {}
        for i in range(key):
            voteLabel = datingLables_1000[sortedDistIndicies[i]]
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
        return sortedClassCount[0][0]
    
    
    
    def datingClassTest():
        hoRatio = 0.1
        datingDataMat, datingLables = file2matrix('D:/code/python/test2/data/data_datingTestSet2.txt')
        # 归一化, normMat最大值减去最小值概率矩阵1000*3、ranges最大值减去最小值、minVals 最小值
        normMat, ranges, minVals = autoNorm(datingDataMat)
    
        # m = 1000 numTestVecs=100
        m = normMat.shape[0]
        numTestVecs = int(m * hoRatio)
        errorCount = 0.0
        for i in range(numTestVecs):
            #    normMat = 概率 = (每个值 - 最小值)矩阵 / (最大值 - 最小值)矩阵 m行
            classifierResult = classify(normMat[i, :], normMat[numTestVecs:m], datingLables[numTestVecs:m], 4)
            print('模型预测值: %d ,真实值 : %d' 
                  % (classifierResult, datingLables[i]))
            if (classifierResult != datingLables[i]):
                errorCount += 1.0
        errorRate = errorCount / float(numTestVecs)
        print('正确率 : %f' % (1 - errorRate))
        return 1 - errorRate
    
    def classifyperson():
        resultList = ['没感觉', '看起来还行', '极具魅力']
        input_man = [50000, 8, 9.5]
        datingDataMat, datingLabels = file2matrix('D:/code/python/test2/data/data_datingTestSet2.txt')
        normMat, ranges, minVals = autoNorm(datingDataMat)
        result = classify((input_man - minVals) / ranges, normMat, datingLabels, 10)
        print('你即将约会的人是:', resultList[result - 1])
    
    
    if __name__ == '__main__':
        acc = datingClassTest()
        if(acc > 0.9):
            classifyperson()
  • 相关阅读:
    python3-file的修改实现类似shell中sed的功能
    python3-字典的循环
    python3-file文件操作
    python3-字典的增删改查
    python3-字典中存储列表
    python3-字典中的一些常用方法
    python3-字典中包含字典
    报错调试和工具使用
    (三)、Struts第三天
    struts体系结构
  • 原文地址:https://www.cnblogs.com/bigdata-familyMeals/p/14614280.html
Copyright © 2011-2022 走看看