《Machine Learning in action》,机器学习实战(笔记)之k-Nearest Neighbors
使用工具
- Python3.8
- pycharm
- anaconda
- jupyter notebook
一、The k_Nearest neighbors classification algorithm
k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法。它的工作原理是:存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类. 举例
电影的分类: 众多周知的,电影可以按照题材分类,然而题材的本身是如何定义的?是由谁来判定某部电影是属于哪个题材的?同一题材的电影是有哪些公共的特征呢?这些都是今天考虑到的问题,这里将用k-邻近算法来构造程序,进行自动划分电影的题材。 可以通过一部电影中的打斗镜头和接吻的镜头次数来判断近似的判断电影的类别。 图1 每部电影的打斗镜头数、接吻镜头数以及电影评估类型 所以当知道电影的某种特征镜头的次数的时候,就可以近似判断其类型。 即使不知道电影属于那种类型,也是可以通过某种方法进行计算的,首先计算未知电影与样本集中电影(就是已知类型的电影集)的距离(先具体某种计算方法) 现在得到了样本集中所有电影与未知电影的距离,按照距离进行递增排序,这样可以找到k个距离最近的电影,如上图所示,假设k=3,那么这三个最近的电影就是He’s Not Really into Dudes,、Beautiful Woman、and California Man. ,k-邻近算法就是按照这种方法更加这三个电影的类型来判断未知电影的类型,而这三部电影都是爱情片,故该电影就是爱情片。
实现k_NN算法(电影的分类)
K-邻近算法的一般步骤:
- 1、收集数据:可以采用任何的方法。
- 2、准备数据:距离计算所需要的数值,最好是结构化的数据格式。
- 3、分析数据:可以使用任何方法。
- 4、训练算法:此步骤不适用与k-邻近算法。
- 5、测试算法:计算错误率。
- 6、使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-邻近算法判定输入数据分别属于哪个分类,
最后应用对计算出的分类执行后续的操作。
1、准备:使用Python导入数据,这里借用numpy进行数据的创建。
- 将上面的电影进行数据化的转变,以数轴的方式进行结构化。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210313103954838.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RwX2RhcmVud3U=,size_16,color_FFFFFF,t_70#pic_center)
- 将上图中的,进行数字化
import numpy as np
'' ''
利用numpy创建有关电影的数据集
这里就是一个简单的实例
group: 数据集
label: 分类的标签(电影的分类名字)
'' '
def CreateDataset ( ) :
# 四组二维的特征
group = np. array ( [ [ 1 , 101 ] , [ 5 , 90 ] , [ 108 , 5 ] , [ 116 , 9 ] ] )
# 设置相应的标签
labels = [ "Romance" , "Romance" , "Action" , "Action" ]
return group, labels
# 观察数据集
if __name__ == '__main__' :
# s实例化数据集
group, labels = CreateDataset ( )
# 打印数据集
print ( group)
print ( labels)
- 运行结果如下图:
2、利用Python构建K_邻近算法
import numpy as np
import operator
'' '
函数说明:
KNN算法,分类器
'' '
'' '
该函数的参数:
inx - 用于分类的输入向量
dataset - 输入的训练样本
labels - 标签向量
k - 表示用来选择的最近邻的数目
'' '
def classify0 ( 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 ]
def CreateDataset ( ) :
# 四组二维的特征
group = np. array ( [ [ 1 , 101 ] , [ 5 , 90 ] , [ 108 , 5 ] , [ 116 , 9 ] ] )
# 设置相应的标签
labels = [ "Romance" , "Romance" , "Action" , "Action" ]
return group, labels
# 观察数据集
if __name__ == '__main__' :
#进行测试
# 实例化,也就是创建数据集
group, labels = CreateDataset ( )
# 建立测试集
test_1 = [ 102 , 19 ]
# 使用分类器
test_class = classify0 ( test_1, group, labels, 3 )
# 打印分类结果
print ( test_class)
其结果如下所示: 这个例子使用的二维的数据,当我们使用多维的数据的时候,也是同样的方式来构建k-NN算法,其欧氏距离的公式都是类似的方式。