KNN 概述

k-近邻(kNN, k-NearestNeighbor)算法是一种基本分类与回归方法,我们这里只讨论分类问题中的 k-近邻算法。

k 近邻算法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。 k值的选择、距离度量以及分类决策规则是k近邻算法的三个基本要素。

KNN 场景

电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢?

  1. 动作片:打斗次数更多
  2. 爱情片:亲吻次数更多

基于电影中的亲吻、打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型。

KNN自己封装库函数

现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影。
假定 k=3,则三个最靠近的电影依次是, He's Not Really into Dudes 、 Beautiful Woman 和 California Man。
knn 算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。

KNN 原理

KNN 工作原理

  1. 假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系。
  2. 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较。
    1. 计算新数据与样本数据集中每条数据的距离。
    2. 对求得的所有距离进行排序(从小到大,越小表示越相似)。
    3. 取前 k (k 一般小于等于 20 )个样本数据对应的分类标签。
  3. 求 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]

 

 

 

 

 

 

 

相关文章: