突发!员工跳楼!只拿低保工资!央企设计院集体罢工!

突发!北京某院集体罢工!

淄博向东,惠泊向西:在人民与人民币之间,惠泊停车选择了人民币

【少儿禁】马建《亮出你的舌苔或空空荡荡》

10部适合女性看的唯美情色电影

生成图片,分享到微信朋友圈

自由微信安卓APP发布,立即下载! | 提交文章网址
查看原文

Python数据分析之k-近邻算法(kNN)

胡萝卜酱 DataGo数据狗 2022-07-01

本文参考于《机器学习实战》

k-近邻算法(k-nearest neighbor,KNN)是一种基本的分类与回归算法。它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。本文将基于《机器学习实战》上的约会数据集展开。

 分类步骤 


 准备数据 


约会对象分为三类:1.不喜欢的人 2. 魅力一般的人 3. 极具魅力的人 。测试集datingTestSet.txt,每行一个样本,每个样本3个特征和一个类别,数据集维数1000x3 ,三个特征如下: 

  • 每年获得的飞行常客里程数 

  • 玩视频游戏所消耗时间百分比 

  • 每周消费的冰淇淋公升数 

将得到的txt文本文件转换成训练样本矩阵和标签向量,代码如下:

import numpy as np
import operator
def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)       #得到文件行数
    returnMat = np.zeros((numberOfLines,3))  
    classLabelVector = []                     
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        if listFromLine[-1] == 'largeDoses':  #极具魅力的人记为1
            classLabelVector.append(1)
        if listFromLine[-1] == 'smallDoses'#魅力一般的人记为2
            classLabelVector.append(2)
        if listFromLine[-1] == 'didntLike'#不喜欢的人记为3
            classLabelVector.append(3)
        index += 1
    return returnMat,classLabelVector
datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
print('datingDataMat:\n',datingDataMat)
print('datingLabels\n',datingLabels)

 分析数据 


通过数据可视化直观了解特征对分类的影响。代码如下:

import matplotlib
import matplotlib.pyplot as plt
def datavisualization(datingDataMat,datingLabels):
    zhfont = matplotlib.font_manager.FontProperties(fname=r'c:\windows\fonts\simsun.ttc')#设置中文字体路径
    fig = plt.figure(figsize=(8,13))
    ax1 = fig.add_subplot(311)#画布切分成3x1,第一个位置添加子图
    ax1.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*np.array(datingLabels), 15.0*np.array(datingLabels))
    ax1.axis([-2,25,-0.2,2.0]) 
    #利用datingLabel变量,绘制色彩不等,尺寸不同的点;指定坐标轴范围
    plt.xlabel('玩视频游戏所消耗时间占百分比',fontproperties=zhfont)#横轴标签
    plt.ylabel('每周消费的冰激凌公升数',fontproperties=zhfont) #纵轴标签
    ax2 = fig.add_subplot(312)#在画布上添加第二个子图  
    ax2.scatter(datingDataMat[:,0], datingDataMat[:,1], 15.0*np.array(datingLabels), 15.0*np.array(datingLabels))
    ax2.axis([-5000,100000,-2,23])
    plt.xlabel('每年获得的飞行常客里程数',fontproperties=zhfont)#横轴标签
    plt.ylabel('玩视频游戏所消耗时间占百分比',fontproperties=zhfont)#纵轴标签
    ax3 = fig.add_subplot(313)#在画布上添加第三个子图
    ax3.scatter(datingDataMat[:,0], datingDataMat[:,2], 15.0*np.array(datingLabels), 15.0*np.array(datingLabels))
    ax3.axis([-5000,100000,-0.2,2.0])
    plt.xlabel('每年获得的飞行常客里程数',fontproperties=zhfont)#横轴标签
    plt.ylabel('每周消费的冰激凌公升数',fontproperties=zhfont)#纵轴标签
    plt.show()
datavisualization(datingDataMat,datingLabels)

图形如下:

 测试数据 


首先是数据特征归一化。定义函数如下:

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m,1))
    normDataSet = normDataSet/np.tile(ranges, (m,1))   
    return normDataSet, ranges, minVals

我们将已有数据的90%作为训练集,剩下的10%作为测试集。

#kNN算法
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
def datingClassTest():
    hoRatio = 0.10      #hold out 10%
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        print ("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
        if (classifierResult != datingLabels[i]): errorCount += 1.0
    print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
    print (errorCount)
datingClassTest()    

分类结果如下,错误率为5%,通过调整hoRatio和变量k的值,错误率会相应变化。

 使用算法 


通过输入三个特征的值,输出是否喜欢该约会对象。

def classifyPerson():
    resultList = ['不喜欢','有点喜欢','很喜欢']
    #三维特征用户输入
    precentTats = float(input("玩视频游戏所耗时间百分比:"))
    ffMiles = float(input("每年获得的飞行常客里程数:"))
    iceCream = float(input("每周消费的冰激淋公升数:"))
    filename = "datingTestSet.txt"
    datingDataMat, datingLabels = file2matrix(filename)
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([precentTats, ffMiles, iceCream])
    norminArr = (inArr - minVals) / ranges
    classifierResult = classify0(norminArr, normMat, datingLabels, 3)
    print("你可能%s这个人" % (resultList[classifierResult-1]))
classifyPerson()     

输入特征值,输出判断结果。

 结语 


kNN是非常常用的分类算法,除了通过上述方式定义函数外,你也可以直接通过下述语句直接调用。

from sklearn.neighbors import KNeighborsClassifier




文章有问题?点此查看未经处理的缓存