《机器学习实战》学习笔记:K-近邻算法(1)

Python版本:python3.x


K-近邻算法

k-近邻算法简单、直观:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K给实例,这K个实例的多数属于某个类,就把该输入实例分为这个类。
书中电影分类例子:

电影名称 打斗镜头 接吻镜头 电影类型
California Man 3 104 爱情片
He’s Not Really into Dudes 2 100 爱情片
Beautiful Woman 1 81 爱情片
Kevin Longblade 101 10 动作片
Robo Slayer 3000 99 5 动作片
Amped II 98 2 动作片
18 90 未知
表1.1 每部电影的打斗镜头数、接吻镜头数以及电影类型
  • 训练样本集:表1.1前六行
  • 测试样本集:表1.1最后一行
  • 特征:打斗镜头,接吻镜头
  • 分类标签:所知道电影的类型

即使不知道未知电影属于哪种类型,我们也可以通过某种方法计算出来。其实根据表1.1不难看出,未知电影很可能属于爱情片。下面通过实现K-近邻算法验证一下猜想。

距离的衡量方法(Euclidean Distance)

d(x,y)= i = 1 n ( x i y i ) 2 \sqrt[]{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}}

  • k-近邻算法步骤:
    1. 为了判断未知实例的类别,以所有已知类别的实例作为参照
    2. 选择参数K
    3. 计算未知实例与所有已知实例的距离
    4. 选择最近K个已知实例
    5. 让未知实例归类为K个最邻近样本中最多数的类别

Python3 代码实现

import numpy as np
import operator

#创建数据集

def createDataSet():
    # 六组二维特征
    group = np.array([[3,104],[2,100],[1,81],[101,10],[99,5],[98,2]])
    # 六组特征的标签
    labels = ['爱情片','爱情片','爱情片','动作片','动作片','动作片']
    return group, labels

#kNN算法
#inX - 用于分类的数据(测试集)
#dataSet - 用于训练的数据(训练集)
#labes - 分类标签
#k - kNN算法参数,最好选择为奇数

def classfy0(inX, dataSet, labels, k):
    # numpy函数shape[0]返回dataSet的行数
    dataSetSize = dataSet.shape[0]
    # 在列向量方向上重复inX共1次(横向),在行向量方向上重复inX共dataSetSize次(纵向)
    diffMat = np.tile(inX,(dataSetSize,1)) - dataSet
    # 二维特征相减后平方
    sqDiffMat = diffMat**2
    # sum()所有元素相加,sum(0)列相加,sum(1)行相加
    sqDistances = sqDiffMat.sum(axis=1)     # 此处从二维矩阵变为一维数组
    # 开方,计算出距离
    distances = sqDistances**0.5
    # 返回distances中元素从小到大排序后的索引值
    sortedDistIndices = distances.argsort()
    # 定一个记录类别次数的字典
    classCount = {}
    for i in range(k):
        # 取出前k个元素的类别
        voteIlabel = labels[sortedDistIndices[i]]
        # dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
        # 计算类别次数
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
        # python3中用items()替换python2中的iteritems()
        # key=operator.itemgetter(1)根据字典的值进行排序
        # key=operator.itemgetter(0)根据字典的键进行排序
        # reverse降序排序字典
        sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
        # 返回次数最多的类别,即所要分类的类别
        return sortedClassCount[0][0]

if __name__ == '__main__':
    group, labels = createDataSet()
    # 测试集
    test = [18,90]
    #kNN分类
    test_class = classfy0(test,group,labels,3)
    print(test_class)

结果如图所示:
在这里插入图片描述

代码中涉及的函数(方法)详解

numpy函数中的tile函数:它的功能是重复某个数组,比如tile(A,n),功能是将数组A重复n次,构成一个新的数组。比如

import numpy as py
array = np.array[1,2,3]
b = np.tile(array,3)
print(b)

结果为:
在这里插入图片描述
输入一个元组(1,3)是一样的。

b = np.tile(array,(1,3))
print(b)

结果与上图一样为:
在这里插入图片描述
输入一个元组(3,1)变成三行的数组了

b = np.tile(arry,(3,1))
print(b)

结果为:
在这里插入图片描述


numpy函数中的argsort()函数:返回的是数组值从小到大的索引值
比如:

import numpy as np
array1 = np.array([5,3,4])
a = array1.argsort()
print(a)

其结果为:

其中最小值3是在array1[1]处。

猜你喜欢

转载自blog.csdn.net/jlf7026/article/details/83548047