KNN(K近邻算法)的简单实现

目录

介绍:

原理:

步骤

结果:

总结


  • 介绍:

        K近邻(KNN)算法是一种常用的分类和回归算法,它基于样本之间的距离来进行预测。KNN算法的基本思想是:如果一个样本在特征空间中的K个最相似(即距离最近)的样本中的大多数属于某个类别,则该样本也属于这个类别。KNN算法在许多领域中都得到了广泛应用,特别是在模式识别、图像处理、自然语言处理和推荐系统等任务中。它简单直观,并且可以适应多种问题和数据类型。

  • 原理:

        K近邻算法顾名思义就是先求出距离待分类的样本点最近的K个已知类别的样本点,然后根据这K个“邻居”样本点中占比最多的样本点的类别来给待分类的样本的分类。

        如下图,给定K=5,离待分类样本点最近的五个“邻居”样本点中,有四个是红色样本点,只有一个是蓝色样本点。因此,红色的“邻居”样本点占比最多,所以该待分类样本点也会被划分为红色样本点。

  • 步骤:

  • 首先,需要确定想要训练的内容,准备好对应的数据集。我们以判断一部游戏是否受欢迎为例,从IGN媒体评分、玩家论坛评分、游戏销量、人均游玩时长来决定,罗列出训练用的数据集,打包为test.txt。(展示20个,实际有100个数据,数量越多最后预测结果会越准确)

  • 从test.txt中解析数据,需要将数据前4列提取出来存入NumPy矩阵中,将游戏的受欢迎程度按数字进行分类,如1为口碑极差、4为一般、7为很受欢迎
# 从test.txt中解析数据
def file2matrix(filename):
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)
    returnMat = np.zeros((numberOfLines,4))
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:4]
        if listFromLine[-1] == '口碑极差':
            classLabelVector.append(1)
        elif listFromLine[-1] == '口碑不佳':
            classLabelVector.append(2)
        elif listFromLine[-1] == '不受欢迎':
            classLabelVector.append(3)
        elif listFromLine[-1] == '一般':
            classLabelVector.append(4)
        elif listFromLine[-1] == '较受欢迎':
            classLabelVector.append(5)
        elif listFromLine[-1] == '受欢迎':
            classLabelVector.append(6)
        elif listFromLine[-1] == '很受欢迎':
            classLabelVector.append(7)
        index += 1
    return returnMat, classLabelVector
  • 将数据归一化处理,归一化处理有
  1. 最小-最大归一化(Min-Max normalization):找到特征数据中的最小值和最大值对每个特征值进行线性变换,将其映射到0到1的范围内;
  2. Z-score归一化(Standardization):计算特征数据的均值和标准差,对每个特征值进行线性变换,使其服从标准正态分布。

        我们使用最小-最大归一化来进行实验:

# 数据归一化处理
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

  • 计算样本点间的距离进行数据分类,样本点的距离有欧氏距离和曼哈顿距离等多种距离公式,本次实验采用简单的欧氏距离来实现:
# 样本点分类
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
    sortedDistIndices = distances.argsort()
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndices[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]
  • 最后编写输入输出与主函数即可进行训练了:
# 输入输出
def classifyPerson():
    resultList = ['口碑极差','口碑不佳','不受欢迎','一般','受欢迎','较受欢迎','很受欢迎']
    ign = float(input("IGN评分:"))
    player = float(input("玩家评分:"))
    sell = float(input("销量:"))
    hour = float(input("时长:"))
    filename = "test.txt"
    datingDataMat, datingLabels = file2matrix(filename)
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ign, player, sell, hour])
    norminArr = (inArr - minVals) / ranges
    classifierResult = classify0(norminArr, normMat, datingLabels, 3)
    print("该游戏%s" % (resultList[classifierResult-1]))

def main():
    filename = 'C:/Users/86188/Desktop/test.txt'

if __name__ == '__main__':
    classifyPerson()
  • 结果:

  • 总结:

        KNN算法是一种简单的实现样本点数据分类的非参数的监督学习算法,可用于回归和分类问题。其简单易懂,实现过程相对比较简单,容易理解和实现;其无需训练,是一种非参数算法,不用要事先对数据进行训练,因此可以直接应用于新数据集;其适用性广泛,具有很好的通用性,可用于分类和回归等多种任务。

        可同时,KNN算法计算复杂度高,当训练集较大时,KNN算法的计算复杂度会随之增加,特别是在高维空间中会出现“维度灾难”,导致算法性能下降;其对异常值也很敏感,只考虑了距离而没有考虑样本的相关性,容易受到噪声等干扰影响。其数据不平衡,当不同类别的样本数量差别较大时,容易出现偏差,因为距离较远的少数类别点被更多的多数类点包围,导致分类结果不准确。

       

        至于为什么选游戏口碑为实验数据,这就不得不提一款被寄予厚望但是口碑扑街的太空题材开放世界游戏了()。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值