knn是一种分类算法。使用knn需要一堆有标签的数据集,数据集记录了每个样本的每个特征,特征的值和它的标签。举个例子:
电影名称 | 打斗镜头 | 接吻镜头 | 电影类型 |
---|---|---|---|
California Man | 3 | 104 | 爱情片 |
He's Not Really into Dudes | 2 | 100 | 爱情片 |
Beautiful Woman | 1 | 81 | 爱情片 |
Kevin Longbade | 101 | 10 | 动作片 |
Robo Slayer 3000 | 99 | 5 | 动作片 |
Amped II | 98 | 2 | 动作片 |
这里特征就是打斗镜头,接吻镜头,下面记录了这些特征的数值。标签就是指的电影类型。
于是我们就可以把这些数据向量化成[[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]]的形式。
这时候对于一个新的数据[?, ?],我们要对其进行类别的判定:
- 首先计算这个新数据同数据集中每个样本的向量之间的距离,一般采用欧式距离:。
- 然后将这个距离从小到大排序
- 接着截取前k个距离近的,统计这k个样本属于哪个标签。根据统计结果,我们给出大概的判断
一个简单的代码
from numpy import *
def createDataSet():
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
labels = ['A', 'A', 'B', "B"]
return group, labels
def classify(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0] # 数据集大小
# tile: 将输入向量的第一维复制dataSetSize次,第二维不变
diffMat = tile(inX, (dataSetSize, 1)) - dataSet # [dataSetSize, 2]
# 欧式距离 [dataSetSize]
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1) # 对第一个维度求和
distances = sqDistances**0.5
print(distances) # [0.82462113 0.72801099 0.85440037 0.82462113]
sortedDistIndicies = distances.argsort() # 升序排序后的索引
print(sortedDistIndicies) # [1 0 3 2]
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=lambda x: x[1], reverse=True)
print(sortedClassCount) # [('A', 2), ('B', 1)]
return sortedClassCount[0][0]
dataSet, labels = createDataSet()
classify([0.8, 0.3], dataSet, labels, 3)
python3.6环境下
归一化
有时候某个特征的值太大,会掩盖其他特征对结果的影响,对于这些特征的值,我们进行一个处理,使它处于0-1之间: