KNN算法

来源:互联网 发布:南京听说科技软件下载 编辑:程序博客网 时间:2024/06/01 21:28

1、介绍

KNN算法又称为k近邻分类(k-nearest neighbor classification)算法。KNN是一种监督类型的分类算法,通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离最近的邻居进行分类判断(投票法)或者回归。

KNN算法的过程为:

  1. 算距离:选择一种距离计算方式, 通过数据所有的特征计算新数据与已知类别数据集中的数据点的距离
  2. 找邻居:按照距离递增次序进行排序,选取与当前距离最小的k个点
  3. 做分类或回归:对于离散分类,返回k个点出现频率最多的类别作预测分类;对于回归则返回k个点的加权值作为预测值

2、重点

1)数据的所有特征都要做可比较的量化。

若是数据特征中存在非数值的类型,必须采取手段将其量化为数值。举个例子,若样本特征中包含颜色(红黑蓝)一项,颜色之间是没有距离可言的,可通过将颜色转换为灰度值来实现距离计算。另外,样本有多个参数,每一个参数都有自己的定义域和取值范围,他们对distance计算的影响也就不一样,如取值较大的影响力会盖过取值较小的参数。为了公平,样本参数必须做归一化。

2)选择适合的计算距离函数

距离的定义有很多,如欧氏距离、余弦距离、汉明距离、曼哈顿距离等等。一般情况下,选欧氏距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量情况下,汉明距离可以用来作为度量。通常情况下,如果运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。

3)确定K的值

K是一个自定义的常数,K的值也直接影响最后的估计,一种选择K值得方法是使用 cross-validate(交叉验证)误差统计选择法。交叉验证的概念之前提过,就是数据样本的一部分作为训练样本,一部分作为测试样本,比如选择95%作为训练样本,剩下的用作测试样本。通过训练数据训练一个机器学习模型,然后利用测试数据测试其误差率。 cross-validate(交叉验证)误差统计选择法就是比较不同K值时的交叉验证平均误差率,选择误差率最小的那个K值。例如选择K=1,2,3,… , 对每个K=i做100次交叉验证,计算出平均误差,然后比较、选出最小的那个。

3、补充

1)加权KNN

以上是KNN的基本算法,有一个问题就是该算法给所有的近邻分配相等的权重,这个还可以这样改进,就是给更近的邻居分配更大的权重(你离我更近,那我就认为你跟我更相似,就给你分配更大的权重),而较远的邻居的权重相应地减少,取其加权平均。需要一个能把距离转换为权重的函数,gaussian函数是一个比较普遍的选择。

def gaussian(dist,sigma=10.0):    """Input a distance and return it's weight"""    weight = np.exp(-dist**2/(2*sigma**2))    return weight

2)交叉验证

Holdout Method(保留)

方法:将原始数据随机分为两组,一组做为训练集,一组做为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率为此Hold-OutMethod下分类器的性能指标.。Holdout Method相对于K-fold Cross Validation 又称Double cross-validation ,或相对K-CV称 2-fold cross-validation(2-CV)
优点:好处的处理简单,只需随机把原始数据分为两组即可
缺点:严格意义来说Holdout Method并不能算是CV,因为这种方法没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,所以这种方法得到的结果其实并不具有说服性.(主要原因是 训练集样本数太少,通常不足以代表母体样本的分布,导致 test 阶段辨识率容易出现明显落差。此外,2-CV 中一分为二的分子集方法的变异度大,往往无法达到「实验过程必须可以被复制」的要求。)

K-fold Cross Validation(k折叠)

方法:作为Holdout Methon的演进,将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标.K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2. 而K-CV 的实验共需要建立 k 个models,并计算 k 次 test sets 的平均辨识率。在实作上,k 要够大才能使各回合中的 训练样本数够多,一般而言 k=10 (作为一个经验参数)算是相当足够了。
优点:K-CV可以有效的避免过学习以及欠学习状态的发生,最后得到的结果也比较具有说服性.
缺点:K值选取上

Leave-One-Out Cross Validation(留一)

方法:如果设原始数据有N个样本,那么留一就是N-CV,即每个样本单独作为验证集,其余的N-1个样本作为训练集,所以留一会得到N个模型,用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标.
优点:相比于前面的K-CV,留一有两个明显的优点:
a.每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。
b. 实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的.
缺点:计算成本高,因为需要建立的模型数量与原始数据样本数量相同,当原始数据样本数量相当多时,LOO-CV在实作上便有困难几乎就是不显示,除非每次训练分类器得到模型的速度很快,或是可以用并行化计算减少计算所需的时间。

Holdout method方法的想法很简单,给一个train_size,然后算法就会在指定的比例(train_size)处把数据分为两部分,然后返回。

def my_train_test_split(X,y,train_size=0.95,shuffle=True):    """    Input X,y, split them and out put X_train, X_test; y_train, y_test.    Example:    ------    X = np.array([[0, 1],[2, 3],[4, 5],[6, 7],[8, 9]])    y = np.array([0, 1, 2, 3, 4])    Then    X_train = np.array([[4, 5],[0, 1],[6, 7]])    X_test = np.array([[2, 3],[8, 9]])    y_train = np.array([2, 0, 3])    y_test = np.array([1, 4])    """    order = np.arange(len(y))    if shuffle:        order = np.random.permutation(order)    border = int(train_size*len(y))    X_train, X_test = X[:border], X[border:]    y_train, y_test = y[:border], y[border:]    return X_train, X_test, y_train, y_test

K folds算法是把数据分成k份,进行k此循环,每次不同的份分别来充当测试组数据。但是注意,该算法不直接操作数据,而是产生一个迭代器,返回训练和测试数据的索引。看docstring里的例子应该很清楚。

  """    K-Folds cross validation iterator.    Provides train/test indices to split data in train test sets. Split dataset     into k consecutive folds (without shuffling by default).    Each fold is then used a validation set once while the k - 1 remaining fold form the training set.    Example:    ------    X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])    y = np.array([1, 2, 3, 4])    kf = KFold(4, n_folds=2,false)    for train_index, test_index in kf:        X_train, X_test = X[train_index], X[test_index]        y_train, y_test = y[train_index], y[test_index]        print("TRAIN:", train_index, "TEST:", test_index)    TRAIN: [2 3] TEST: [0 1]    TRAIN: [0 1] TEST: [2 3]    """def KFold(n,n_folds=5,shuffe=False):    idx = np.arange(n)    if shuffe:        idx = np.random.permutation(idx)    fold_sizes = (n // n_folds) * np.ones(n_folds, dtype=np.int) # folds have size n // n_folds    fold_sizes[:n % n_folds] += 1 # The first n % n_folds folds have size n // n_folds + 1    current = 0    for fold_size in fold_sizes:        start, stop = current, current + fold_size        train_index = list(np.concatenate((idx[:start], idx[stop:])))        test_index = list(idx[start:stop])        yield train_index, test_index        current = stop # move one step forward

评价算法
首先我们用一个函数评价算法,给定训练数据与测试数据,计算平均的计算误差,这是评价算法好坏的重要指标。

def test_algo(alg,X_train,X_test,y_train,y_test,kn=3):    error = 0.0    for i in range(len(y_test)):        guess = alg(X_train,y_train,X_test[i],kn=kn)        error += (y_test[i] - guess)**2    return error/len(y_test)

参考博客:
http://www.jianshu.com/p/48d391dab189
http://www.th7.cn/Program/Python/201412/332782.shtml

0 0
原创粉丝点击