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不难看出,未知电影很可能属于爱情片。下面通过实现K-近邻算法验证一下猜想。
距离的衡量方法(Euclidean Distance)
d(x,y)= ∑ i = 1 n ( x i − y i ) 2 \sqrt[]{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}} ∑i=1n(xi−yi)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]处。