KNN 概述
k-近邻(kNN, k-NearestNeighbor)算法是一种基本分类与回归方法,我们这里只讨论分类问题中的 k-近邻算法。
k 近邻算法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。 k值的选择、距离度量以及分类决策规则是k近邻算法的三个基本要素。
KNN 场景
电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢?
- 动作片:打斗次数更多
- 爱情片:亲吻次数更多
基于电影中的亲吻、打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型。
现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影。
假定 k=3,则三个最靠近的电影依次是, He's Not Really into Dudes 、 Beautiful Woman 和 California Man。
knn 算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。
KNN 原理
KNN 工作原理
- 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系。
- 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较。
- 计算新数据与样本数据集中每条数据的距离。
- 对求得的所有距离进行排序(从小到大,越小表示越相似)。
- 取前 k (k 一般小于等于 20 )个样本数据对应的分类标签。
- 求 k 个数据中出现次数最多的分类标签作为新数据的分类。
KNN 通俗理解
给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的 k 个实例,这 k 个实例的多数属于某个类,就把该输入实例分为这个类。
KNN 开发流程
收集数据:任何方法
准备数据:距离计算所需要的数值,最好是结构化的数据格式
分析数据:任何方法
训练算法:此步骤不适用于 k-近邻算法
测试算法:计算错误率
使用算法:输入样本数据和结构化的输出结果,然后运行 k-近邻算法判断输入数据分类属于哪个分类,最后对计算出的分类执行后续处理
KNN 算法特点
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
将文本记录转换为 NumPy 的解析程序
from numpy import *
def file2matrix(filename):
"""
Desc:
导入训练数据
parameters:
filename: 数据文件路径
return:
数据矩阵 returnMat 和对应的类别 classLabelVector
"""
fr = open("datingTestSet2.txt")
arraylines = fr.readlines()
numberofLines = len(arraylines)
returnMat =zeros((numberofLines, 3))
index = 0
label = []
for line in arraylines:
print(line)
# line=line.strip()
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0:3]
label.append(int(listFromLine[-1].strip('\n')))
index = index + 1
return returnMat,array([label])
if __name__ == '__main__':
datingDataMat,datingLabels=file2matrix("datingTestSet2.txt")
自己封装的KNNimport numpy as np from math import sqrt from collections import Counter from metrics import accuracy_score ######测试Counter 的用法 y=[0,0,0,1,1,1,3,3,3] print(np.array(y).shape[0])==print(len(y)) print(Counter(y)) #Counter({0: 3, 1: 3, 3: 3}) print(Counter(y).most_common(2)) #[(0, 3), (1, 3)] print(np.argsort([2,5,7,3,1])) #[4 0 3 1 2] class KNNClassifier: def __init__(self, k): assert k >= 1, "k must be valid" self.k = k self._X_train = None self._Y_train = None def fit(self, X_train, Y_train): assert X_train.shape[0] == Y_train.shape[0], \ "The size of X_train must be equals to the size of Y-Train" assert self.k <= X_train.shape[0], \ "the feature number of x must be equal to X_train" self._X_train = X_train self._Y_train = Y_train return self def predict(self, x_predict): return np.array([self._predict(x) for x in x_predict]) def _predict(self, x): distances = [sqrt(np.sum((x_train - x) ** 2)) for x_train in self._X_train] nearest = np.argsort(distances) votes = [i for i in self._Y_train[nearest[:self.k]]] return Counter(votes).most_common(1)[0][0] def score(self,X_test,y_test): y_predict=self.predict(X_test) return accuracy_score(y_test,y_predict) def __repr__(self): return "knn(k=%d)" % self.k在求距离时也可用向量法
def classify(inx,dataSet,labels,k = 3): m = dataSet.shape[0] diffMat = tile(inx,(m,1)) - dataSet squareMat = diffMat ** 2 squareDistance = squareMat.sum(axis = 1) distances = squareDistance ** 0.5 nearest = distances.argsort() votes = [i for i in labels[nearest[:k]]] return Counter(votes).most_common(1)[0][0]