首页 > 编程语言 >Chapter2 K-近邻算法案例

Chapter2 K-近邻算法案例

时间:2023-04-08 09:02:38浏览次数:40  
标签:kNN datingLabels 数据 近邻 Chapter2 算法 归一化 real datingDataMat

案例1:使用K-近邻算法分类爱情片和动作片


1. 案例要求

    创建一个应用,应用K-近邻算法,将样本分到以下三种类别。
        1. 不喜欢的人
        2. 魅力一般的人
        3. 极具魅力的人

2. 案例的执行流程

    示例:在约会网站上使用k-近邻算法
        (1)收集数据:提供文本文件。
        (2)准备数据:使用Python解析文本文件。这一步的作用:必须将待处理数据的格式改变为分类器可以接受的格式。(使数据的格式符合要求)
        (3)分析数据:使用Matplotlib画二维扩散图。
        (4)训练算法:此步骤不适用于k-近邻算法。
        (5)测试算法:使用海伦提供的部分数据作为测试样本。测试样本和非测试样本的区别在于:测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。
        (6)使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。

3. 准备数据:从文本文件中解析数据

    准备工作:数据存放在datingTestSet2.txt中,每个样本数据占据一行,共1000行。每个样本都有三个特征。
        1. 每年获得的飞行常客里程数
        2. 玩视频游戏所耗时间百分比
        3. 每周消费的冰淇淋公升数
# 该代码的作用是将文本文件中的数据格式改变为分类器可以接受的格式
# 该代码位于kNN.py中

def file2matrix(filename):
    love_dictionary = {'largeDoses':3, 'smallDoses':2, 'didntLike':1}       # 将三种类别与数字对应起来
    fr = open(filename)                         # 打开文件
    arrayOLines = fr.readlines()                # 读取文件的每一行并以列表的形式返回
    numberOfLines = len(arrayOLines)            # 读取该列表长度,即为行数
    returnMat = np.zeros((numberOfLines, 3))    # 数据(训练)集矩阵 numpy.zero代表生成指定格式的数组,元素用0填充
    classLabelVector = []                       # 标签向量
    index = 0                                   # index是代表行的游标
    for line in arrayOLines:                    # 取出文件的每一行
        line = line.strip()                     # strip()代表去除首尾空格或回车
        listFromLine = line.split('\t')         # 将每一行元素分隔开,以\t为标志,返回的是一个列表
        returnMat[index, :] = listFromLine[0:3] # 填充数据集
        # 该if...else语句的作用是填充标签向量
        if(listFromLine[-1].isdigit()):         # isdigit()检测字符串是否只包含数字,是为True,否为False。listFromLine[-1]为标签(字符串形式)
            classLabelVector.append(int(listFromLine[-1]))
        else:
            classLabelVector.append(love_dictionary.get(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector
# 该代码的作用用于测试
# 该代码位于personalTest.py中

print(kNN.file2matrix('datingTestSet.txt'))
'''
array([[4.0920000e+04, 8.3269760e+00, 9.5395200e-01],
       [1.4488000e+04, 7.1534690e+00, 1.6739040e+00],
       [2.6052000e+04, 1.4418710e+00, 8.0512400e-01],
       ...,
       [2.6575000e+04, 1.0650102e+01, 8.6662700e-01],
       [4.8111000e+04, 9.1345280e+00, 7.2804500e-01],
       [4.3757000e+04, 7.8826010e+00, 1.3324460e+00]])
'''
'''
[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2, 1, 3,...]
'''

4. 分析数据:使用Matplotlib创建散点图

# 该代码用于绘制散点图
# 该代码位于personalTest.py文件中

from numpy import *
import matplotlib
import matplotlib.pyplot as plt

from Ch02 import kNN

fig = plt.figure()           # 创建一个figure
ax = fig.add_subplot(111)    # 在figure的基础上添加子图。参数为行列第几个图 111 代表1行1列第一个子图(共有一个子图)
                             # 224 代表2行2列第4个子图。(共有四个子图)
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet.txt') # 提取数据矩阵和标签向量
# ax.scatter(datingDataMat[:,1], datingDataMat[:,2])  # scatter代表绘制散点图,其中第一个和第二个参数代表长度相同的数组序列。(分别代表x和y)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*array(datingLabels), array(datingLabels))
# 上述函数的第三个参数代表点的大小,根据不同的类别,大小也不同
# 上述函数的第四个参数代表点的颜色,根据不同的类别,颜色也不同
ax.axis([-2,25,-0.2,2.0])                                     # 配置坐标轴,其中参数分别为xmin xmax ymin ymax
plt.xlabel('Percentage of Time Spent Playing Video Games')    # 设置在x轴上的标签
plt.ylabel('Liters of Ice Cream Consumed Per Week')           # 设置在y轴上的标签
plt.show()                                                    # 显示figure

img

5. 准备数据:归一化数值

img
img

    为什么要归一化数值?
        根据上表,如果我们想要计算样本3和样本4之间的欧氏距离,可以使用上面的公式。
        我们很容易发现:上面公式的大小很大程度上取决于数值差值最大的属性(特征)。也就是说,每年获取的飞行常客里程数对于计算结果的影响将远远大于其他两个特征的影响。而产生这种现象的原因仅仅是因为每年获取的飞行常客里程数远大于其他特征值。但是这三种特征应该是同样重要的。(权重是相等的),飞行常客里程数不应该大程度地决定整个距离的大小。所以我们要归一化数值,使这三种特征的取值范围同步,这样的话每个特征的数值差值就同步了。
        因此,在处理这种不同取值范围的特征值时,我们通常采用的方法就是数值归一化,把取值范围限制在0到1或-1到1之间。这里我们将取值范围限制在0到1之间,采用下面的公式。

img

    其中min和max分别为:每个特征的最小特征值和最大特征值。
# 此函数的功能是要把每一个特征都要归一化,使其范围在0-1之间
# 该函数位于kNN.py文件中

def autoNorm(dataSet):
    minVals = dataSet.min(0)                            # min方法,如果无参,代表这个array数组中所有元素的最小值。如果参数为0,则代表返回array数组中每一列(每一个特征)的最小值,如果参数为1,就是行
    maxVals = dataSet.max(0)                            # max方法同上,只是最大值
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))           # 归一化之后的数据集,元素初始化为0
    m = dataSet.shape[0]                                # 取行数
    normDataSet = dataSet - np.tile(minVals, (m, 1))    # 相减,对应公式中的oldValue-min
    normDataSet = normDataSet/np.tile(ranges, (m, 1))   # 相除(这里不是矩阵除法,只是将矩阵对应元素之间进行相除),对应公式中的oldValue-min/max-min
    return normDataSet, ranges, minVals                 # 返回归一化之后的数据集,每个特征的最大值和最小值之间的距离,每个特征的最小值
# 本代码的功能是用于测试
# 代码位于personalTest.py文件中

datingDataMat,datingLabels = kNN.file2matrix('datingTestSet.txt') # 提取数据矩阵和标签向量

print(kNN.autoNorm(datingDataMat))

'''
array([[0.44832535, 0.39805139, 0.56233353],
       [0.15873259, 0.34195467, 0.98724416],
       [0.28542943, 0.06892523, 0.47449629],
       ...,
       [0.29115949, 0.50910294, 0.51079493],
       [0.52711097, 0.43665451, 0.4290048 ],
       [0.47940793, 0.3768091 , 0.78571804]])
'''
'''
array([9.1273000e+04, 2.0919349e+01, 1.6943610e+00])
'''
'''
array([0.      , 0.      , 0.001156])
'''

6. 测试分类器

# 此函数的作用就是用于测试分类器的错误率
# 该函数位于kNN.py文件中

def datingClassTest():
    hoRatio = 0.10      # 代表控制测试数据的比率,测试数据应该为整体数据的10%,剩余的90%应为训练数据。
    datingDataMat, datingLabels = file2matrix('datingTestSet.txt')       # 从文件中加载数据集
    normMat, ranges, minVals = autoNorm(datingDataMat)                    # 归一化数据集
    m = normMat.shape[0]                                                  # 行数
    numTestVecs = int(m*hoRatio)                                          # 测试数据的数量,由比率控制
    errorCount = 0.0                                                      # 每当测试器错误分类数据,则数量+1
    for i in range(numTestVecs):
        #numpy中的冒号有两层意思:默认全部选择、指定范围(左闭右开)
        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          # 如果分类器预测的类别和真实的类别有误,则计数器+1
    print("the total error rate is: %f" % (errorCount / float(numTestVecs))) # 错误率
    print(errorCount)                                                        # 输出错误数量
# 此代码的作用是运行上述的测试程序
# 该代码在哪里都能执行,只要导入了kNN.py文件就行

kNN.datingClassTest()
'''
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
...
the total error rate is: 0.050000 
5.0
'''
# 错误率在5%,还是可以的。

7. 构建完整可用系统

# 本代码实现一个小程序,用于对输入的样本进行分类
# 该代码位于kNN.py文件中

def classifyPerson():
    resultList = ['not at all', 'in small doses', 'in large doses']                  # 用于记录结果的列表
    percentTats = float(input(\
                                  "percentage of time spent playing video games?"))
    ffMiles = float(input("frequent flier miles earned per year?"))
    iceCream = float(input("liters of ice cream consumed per year?"))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles, percentTats, iceCream, ])
    classifierResult = classify0((inArr - \
                                  minVals)/ranges, normMat, datingLabels, 3)        # 训练集和测试集需要归一化,预测样本也需要归一化。
    print("You will probably like this person: %s" % resultList[classifierResult - 1]) # 输出结果
# 本代码用于测试该程序
# 该代码可以随时运行,只要导入kNN.py文件

kNN.classifyPerson()
'''
percentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice cream consumed per year?0.5
2
You will probably like this person: in small doses
'''

标签:kNN,datingLabels,数据,近邻,Chapter2,算法,归一化,real,datingDataMat
From: https://www.cnblogs.com/gao79135/p/17297883.html

相关文章

  • 页面置换算法
    页面置换算法1、最佳置换算法(OPT)2、先进先出置换算法(FIFO)3、最近最久未使用置换算法(LRU)4、时钟置换算法(CLOCK)5、改进的时钟置换算法知识回顾......
  • 基于Python的机器学习算法——sklearn模块
    基于Python的机器学习算法安装包:pipinstallnumpy#安装numpy包pipinstallsklearn#安装sklearn包importnumpyasnp#加载包numpy,并将包记为np(别名)importsklearn#加载sklearn包python中的基础包:numpy:科学计算的基础库,包括多维数组处理、线性代数等pandas:主......
  • 根据数据量来判断算法的复杂度
    根据数据量来判断算法的复杂度通过运行时间判断数据量1000ms即1s,大概可以运行10的7次方数量级的运算左边的复杂度在1s内能处理的数据量大小......
  • LNN工具链详解:在CSK6上运行你自己的AI算法
    工具链简介LNN(ListenAINeuralNetwork)是聆思科技专为聆思AIOT芯片(目前支持CSK6系芯片)定制开发的AI生态工具链,它包含linger和thinker两个部分,其中linger是量化训练组件,thinker是轻量级推理引擎组件,两个套件相互配合实现了训练推理一体化。LNN工具链已支撑聆思芯片在计算机......
  • opencv-python 4.15. 基于分水岭算法的图像分割
    理论任何灰度图像都可以看作是地形表面,其中高强度表示峰和丘陵,而低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水的上升,取决于附近的峰值(梯度),来自不同山谷的水,明显具有不同的颜色将开始融合。为避免这种情况,你需要在水合并的位置建立障碍。你继续......
  • J7、对于ResNeXt-50算法的思考
    这周的内容是一个问题:当conv_shortcut=True时,残差单元会使用一个卷积层对输入进行降维,然后在BN层对该卷积层的输出进行归一化,最后再进行快捷连接。这样可以使得输入与快捷连接的输出的形状相同,从而便于直接相加。当conv_shortcut=False时,快捷连接直接连接输入和输出,而不......
  • 基于DNN深度学习网络的OFDM信号检测算法的仿真,对比LS和MMSE
    1.算法描述        随着无线通信的快速发展,5G正逐渐成长为支撑全社会各行业运作的大型基础性互联网络,其服务范围的大幅扩展对底层技术提出了诸多挑战,尤其是作为物理层关键技术之一的正交频分复用(OrthogonalFrequencyDivisionMultiplexing,OFDM)。近来,深度学习因......
  • 基于DNN深度学习网络的OFDM信号检测算法的仿真,对比LS和MMSE
    1.算法描述随着无线通信的快速发展,5G正逐渐成长为支撑全社会各行业运作的大型基础性互联网络,其服务范围的大幅扩展对底层技术提出了诸多挑战,尤其是作为物理层关键技术之一的正交频分复用(OrthogonalFrequencyDivisionMultiplexing,OFDM)。近来,深度学习因其在计算机视觉以及......
  • m基于flocking算法的无人机群空间避障飞行matlab仿真,对比二维场景和三维场景
    1.算法描述        近年来,随着通信网络、人工智能、自主系统、大数据的前沿技术的发展,无人机蜂群作战也正在由概念变成现实,从理论走向实践。航迹规划,多机协作,集群控制等问题成为当下研究热点。在军事作战中派遣多无人机协同作战相比于单无人机能够在穿透敌方防御系统,......
  • BF算法的实现:病毒感染检测
    一、问题引入BF(Brute-Force)算法介绍了BF算法的具体实现,但并未结合具体案例。本随笔就是结合案例(病毒感染检测)对BF算法进行结合分析。案例4.1:病毒感染检测医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知它们的DNA序列都是环状的。现在研究者巳收集了大量的病毒......