目录
一、KNN算法
1.KNN算法概述
K-近邻(K-NearestNeighbor)算法属于监督学习方法。该算法采用测量不同特征值之间的距离进行分类。其基本法则是:未被标记的样本的类别标签由与其相近的k个样本决定。也就是说,该样本在特征空间中与其最相邻的k个样本中的大多数属于同一个类别。
2.距离度量
- 欧氏距离:在n维空间中两个点之间的距离
- 曼哈顿距离:二维直角坐标系上两点所形成的线段对轴产生的投影的距离总和。
二、KNN算法实例
现需统计班上同学喜欢的音乐风格(假设仅设置Classical music / Pop music两个选项),可根据每月同学们对不同类型音乐的听歌次数判断该同学喜欢的音乐风格 。
部分训练集如下:
Classical music次数 | Pop music次数 | 喜爱风格 |
250 | 10 | Classical music |
270 | 121 | Classical music |
16 | 236 | Pop music |
130 | 269 | Pop music |
200 | 80 | Classical music |
68 | 190 | Pop music |
180 | 150 | Pop music |
155 | 190 | Pop music |
230 | 180 | Classical music |
160 | 186 | Classical music |
8 | 268 | Pop music |
54 | 150 | Pop music |
120 | 259 | Pop music |
204 | 146 | Classical music |
该训练样本的特征值有两个:1.每月听Classical music次数,2. 每月听Pop music次数。
标签为该同学喜爱的风格。
1. 导入数据(训练集dataSet)
import numpy as np
import operator
def createDataSet():
features=np.array([[250,10],[270,121],[16,236],[130,269],[200,80],[68,190],[180,150],[155,190],[230,180],[160,186],[8,268],[54,150],[120,259],[204,146]])
labels=["Classical music","Classical music","Pop music","Pop music","Classical music","Pop music","Pop music","Pop music","Classical music","Classical music","Pop music","Pop music","Pop music","Classical music"]
return features,labels
features,labels = createDataSet()
print(features,'\n',labels)
运行结果:
['Classical music', 'Classical music', 'Pop music', 'Pop music', 'Classical music', 'Pop music', 'Pop music', 'Pop music', 'Classical music', 'Classical music', 'Pop music', 'Pop music', 'Pop music', 'Classical music']
将特征值和标签转为训练集。
2. 通过分类器实现KNN算法
def classify0(inX, dataSet, labels, k):
#返回dataSet的行数,即已知数据集中的所有点的数量
num = len(dataSet)
#行向量方向上将inX复制num次,然后和dataSet矩阵做相减运算
ans = np.tile(inX, (num, 1)) - dataSet
#减完后,对每个数做平方
ans = ans**2
#平方后按行求和,axis=0表示列相加,axis-1表示行相加
dis = ans.sum(axis=1)
#开方计算出欧式距离
ans = dis**0.5
#对距离从小到大排序
y = np.argsort(ans)
#用于类别/次数的字典,key为类别, value为次数
y=list(y[0])
#取出第近的元素对应的类别
dic = dict.fromkeys(list(set(labels)), 0)
#对类别次数进行累加
for i in range(k):
dic[labels[y[i]]]+=1
#根据字典的值从大到小排序
dic = sorted(dic.items(),key =lambda item:item[1],reverse=True)
#返回次数最多的类别,即所要分类的类别
return dic[0][0]
np.tile(inX, (dataSetSize, 1)) 表示把输入向量inX复制(dataSet行,1列)次
np.tile(A, reps)函数中的参数reps代表扩展后的维度
1. 只有一个参数,只向一个维度复制(横向),在行方向上复制
2. 有两个参数,向两个维度复制,同时向行方向和列方向复制
3. 测试实例
#测试集
inX=[180,165]
#真实类别标签
test_label = 'Classicalmusic'
#k从1到9循环输出预测结果
for k in range(1,10):
test_class = classify0(inX,features,labels,k)
print("预测类别:",test_class,"真实类别:",test_label,"k值:",k)
运行结果:
三、总结
1. KNN算法流程
2. k的设定问题
k值选择过小,用较小的领域中的训练样本进行预测,得到的邻近的数量过少,模型拟合的能力较强,但是当训练集中含有噪声样本时,噪声数据对测试数据的干扰会增大,容易过拟合,泛化能力较弱。k值选择过大, 模型拟合能力较弱,训练误差会增大,容易欠拟合。
3. 数据归一化
在计算距离度量时,当某一特征值对计算结果的影响较大,或在计算中起主导地位时,需进行数据的归一化处理。归一化:将所有数据映射到同一尺度。
计算公式:
例如:在Helen的例子中,在计算距离时,”每年获取的飞行常客里程数“对于计算结果的影响远大于其他两特征的影响,经过归一化处理,将所有特征值转化到0-1区间,使计算结果更加准确。
4. KNN算法优缺点分析
knn算法在使用时需要有接近实际数据的训练样本数据。当训练集有大量数据时,需要较大的存储空间;在对数据集中的每个数据计算距离值时,会产生巨大的计算代价。即使knn算法较为简单,但计算复杂度高,空间复杂度高,对系统的开销不容忽略。