机器学习-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()
原文地址:https://www.cnblogs.com/bigdata-familyMeals/p/14614280.html