关于KNN

K-近邻算法,简称KNN(k-Nearest Neighbor),是一个相当简单的分类/预测算法。其主要思想就是,选取与待分类/预测数据的最相似的K个训练数据,通过对这K个数据的结果或者分类标号取平均、取众数等方法得到待分类/预测数据的结果或者分类标号。

关于KNN,笔者在 浅入浅出:K近邻算法 有较为详细的介绍。

数据集介绍

数据集是有8个分类的文本数据集,使用了结巴分词对每个文本分词,每个单词当作特征,再利用二元词串构造更多特征,然后去掉停用词,去掉出现次数太多和太少的特征,得到了19630个特征。取1998个样本用于训练,509个用于测试。基于词袋模型的思路将每个文本转换为向量,训练集和测试集分别转换为矩阵,并用python numpy模块将其保存为npy格式。

https://github.com/someus/dataset 下载text-classification.7z,解压后导入数据:

test_data.npy test_labels.npy training_data.npy training_labels.npy $ ipython >> > import numpy as np >> > training_data = np.load( "training_data.npy" ) >> > training_data.shape ( 1998 , 19630 ) >> > training_labels = np.load( "training_labels.npy" ) >> > training_labels array([ 6 , 6 , 6 , ..., 2 , 2 , 2 ]) >> > training_labels.shape ( 1998 ,) >> > test_data = np.load( "test_data.npy" ) >> > test_data.shape ( 509 , 19630 ) >> > test_labels = np.load( "test_labels.npy" ) >> > test_labels.shape ( 509 ,)

如何找一样本的最近k个邻居

>>> from sklearn.neighbors import NearestNeighbors
>>> nbrs = NearestNeighbors(n_neighbors=6, algorithm='ball_tree')
>>> nbrs.fit(training_data)  # 构造BallTree,可以快速找出6个最近邻居,原理待学习
NearestNeighbors(algorithm='ball_tree', leaf_size=30, metric='minkowski',
         metric_params=None, n_neighbors=6, p=2, radius=1.0)
>>> distances, indices = nbrs.kneighbors(test_data[0])  # 找training_data中离样本test_data[0]的最近的6个样本
>>> indices  # 6个最近样本,每个值是指在training_data中的第几个样本
array([[500, 294,  62, 802, 732, 703]])
>>> distances  # 对应的距离
array([[ 13.37908816,  13.60147051,  13.60147051




    
,  13.60147051,
         13.60147051,  13.6381817 ]])

也可以依次找出多个测试样本的最近的6个训练样本:

>>> distances, indices = nbrs.kneighbors(test_data[0:2])
>>> indices
array([[ 500,  294,   62,  802,  732,  703],
       [  62,  294,  636, 1945,  802, 1091]])
>>> distances
array([[ 13.37908816,  13.60147051,  13.60147051,  13.60147051,
         13.60147051,  13.6381817 ],
       [  7.93725393,   7.93725393,   8.1240384 ,   8.36660027,
          8.54400375,   8.54400375]])
>>> from sklearn.neighbors import BallTree
>>> bt = BallTree(training_data, metric='euclidean')
>>> distances, indices = bt.query(test_data[0], k=6)                  
>>> indices
array([[500,  62, 802, 294, 732, 703]])
>>> distances
array([[ 13.37908816,  13.60147051,  13.60147051,  13.60147051,
         13.60147051,  13.6381817 ]])

基于KNN的文本分类

令k=6:

>>> from sklearn.neighbors import KNeighborsClassifier
>>> knn = KNeighborsClassifier(n_neighbors=6, metric='euclidean')
>>> knn.fit(training_data, training_labels) # 训练
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='euclidean',
           metric_params=None, n_neighbors=6, p=2, weights='uniform')
>>> predict_labels = knn.predict(test_data) # 预测
>>




    
> sum(predict_labels == test_labels)
>>> 230./509  # 正确率
0.4518664047151277

令k=20:

>>> from sklearn.neighbors import KNeighborsClassifier
>>> knn = KNeighborsClassifier(n_neighbors=20, metric='euclidean')
>>> knn.fit(training_data, training_labels) # 训练
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='euclidean',
           metric_params=None, n_neighbors=20, p=2, weights='uniform')
>>> predict_labels = knn.predict(test_data) # 预测
>>> sum(predict_labels == test_labels)
276  # 效果比k=6时提升了一些
>>> 276./509   # 正确率
0.5422396856581533

这个正确率并不高。在基于贝叶斯的文本分类实战中笔者使用了多项式贝叶斯对同样的数据集进行分类,正确率达到近90%。

我们将每个样本归一化,看看效果。

先写一个归一化工具(mytools.py):

# !/usr/bin/env python
# -*- encoding:utf-8 -*-
import numpy as np
def uniformization(X):
    if X.ndim != 2:
        return None
    X2 = X.copy()
    X2 = X2.astype(float)
    rows = X2.shape[0]
    for i in xrange(0, rows):
        sum_of_squares = sum(X2[i, :]**2)
        if sum_of_squares == 0: continue
        sqrt_sum_of_squares = sum_of_squares**0.5
        X2[i, :] = X2[i, :] / sqrt_sum_of_squares
    return X2 
if __name__ == '__main__':
    arr = np.array([[1,2,3],[4,5,6],[0,0,0]])
    print uniformization(arr)

运行结果如下:

[[ 0.26726124  0.53452248  0.80178373]
 [ 0.45584231  0.56980288  0.68376346]
 [ 0.          0.          0.

处理原始数据集,生成新的数据:

>>> from mytools import uniformization
>>> new_training_data = uniformization(training_data)
>>> new_test_data = uniformization(test_data)

令k=6:

>>> knn = KNeighborsClassifier(n_neighbors=6, metric='euclidean')
>>> knn.fit(new_training_data, training_labels) # 使用新数据训练
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='euclidean',
           metric_params=None, n_neighbors=6, p=2, weights='uniform')
>>> predict_labels = knn.predict(new_test_data) # 预测
>>> sum(predict_labels == test_labels)
294  # 由230提升到294
>>> 294./509  # 正确率有提升
0.5776031434184676

令k=20:

>>> from sklearn.neighbors import KNeighborsClassifier
>>> knn = KNeighborsClassifier(n_neighbors=20, metric='euclidean')
>>> knn.fit(new_training_data, training_labels)  # 使用新数据训练
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='euclidean',
           metric_params=None, n_neighbors=20, p=2, weights='uniform')
>>> predict_labels = knn.predict(new_test_data)  # 预测
>>> sum(predict_labels == test_labels)
314  # 由276提升到314
>>> 314./509  # 正确率有提升
0.6168958742632613

可以看到,归一化后,预测分类的正确率提升很多。

1.6. Nearest Neighbors
sklearn.neighbors.KNeighborsClassifier

上一篇文章已经描述了朴素贝叶斯算法newgroup的分类实现,这篇文章采用KNN算法实现newgroup的分类。 文中代码参考:http://blog.csdn.net/yangliuy/article/details/7401142 1、KNN算法描述 对于KNN算法,前面有一篇文章介绍其思想,但是按个事例采用的模拟的数值数据。本文将采用KNN进行文本分类。算法步骤如下: (1)文本预处 numSamples = dataSet.shape[0] # shape[0]表示行数## step 1: 计算距离# tile(A, reps): 构造一个矩阵,通过A重复reps次得到diff = tile(newInput, (numSamples, 1)) - dataSet # 按元素求差值squaredDiff = diff ** 2 #将差值平方squaredDist = sum(squaredDiff, axis = 1) # 按行累加。   文本分类——常见分类模型   kNN分类模型的主要思想:通过给定一个未标注文档d,分类系统在训练中查找与它距离最接近的k篇相邻(相似或相同)标注文档,然后根据这k篇邻近文档的分类标注来确定文档d的类别。 普通kNN实现   一般常规的kNN计算新输入文档与训练中样本之间的距离,都是新输入文档与每一训练样本计算相似度。数据结构... 相似的对象在特征空间中距离相近。具体来说,对于待分类的样本,KNN算法首先计算它与训练中每个样本之间的距离。然后,算法选取距离最小的K个样本,这些样本被称为“邻居”。最后,根据这些邻居的类别标签,通过投票或加权平均等方式,确定待分类样本的类别。KNN算法的核心在于距离度量,它决定了样本之间的相似度。通过选择合适的距离度量方法,KNN算法能够准确地找出与待分类样本最相似的邻居,从而进行准确的分类。为了演示KNN算法文本分类中的应用,我们选择了一个公开的文本分类数据,如20 Newsgroups数据KNN算法原理 k最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法。它采用测量不同特征值之间的距离方法进行分类。它的思想很简单:如果一个样本在特征空间中的k个最近邻(最相似)的样本中的大多数都属于某一个类别,则该样本也属于这个类别。第一个字母k可以小写,表示外部定义的近邻数量。这句话不难理解,但有点拗口,下面通过一个实例来讲解一下。 首先我们准备一个数据,这个数据很简... 在词袋模型的基础上,引入TF-IDF(Term Frequency-Inverse Document Frequency)权重,以突出那些在特定文档中频繁出现但在整体文档合中不常见的词语,从而增强特征表示的区分度。在学术和工业界,针对KNN算法的优化和扩展一直是研究热点,不断涌现新的研究成果和技术解决方案,以适应大数据时代对算法性能的更高要求。:如科技新闻、体育新闻、财经新闻等多类别分类,KNN同样可以应用于此,通过计算文本向量间的距离,将新闻文章分配给最接近的类别。 1、KNN算法的简介 kNN算法就是找到k个最相似的样本,这些样本所在的类,就是当前文档的所属的类。如下图:绿色圆圈表示你想分类的文本,其他是已知类别的样本。图中其他形状和绿色圆圈的距离代表了相似度。如果k = 3,就是取3个最相似的文本,那么1个蓝色框,2红色三角被选中,因为红色三角多,则绿色圆圈所属的类就是红色三角所在的类。如果k = 5,3个蓝色框和2个红色三角选中,那么就属于蓝色框所 简介:文本分类作为自然语言处理的核心任务,KNN算法因其在分类问题上的性能而受到青睐。本项目聚焦于如何利用C++语言实现KNN算法来对文本数据进行分类,涵盖从数据预处理到最终分类决策的完整流程。我们将探讨如何将文本转化为数值向量表示,计算向量间的距离,确定合适的K值,以及如何通过投票机制为未知类别文本做出分类预测。同时,我们也会考虑到C++... 文本分类是信息检索和数据挖掘中的一个基本任务,它涉及到将自然语言文本按照内容分配到一个或多个预定义的类别中。这一任务广泛应用于垃圾邮件检测、情感分析、话题追踪以及个性化推荐系统等领域。随着机器学习技术的发展,文本分类的自动化和智能化水平不断提高。在深入研究文本分类的算法之前,我们需要了解文本分类的流程,包括文本预处理、特征提取、模型训练、分类预测以及模型评估等关键步骤。每一个步骤都是文本分类性能优化的关键,而本章将对这些基本概念和术语进行介绍,为后续章节中算法的详细介绍和应用打下坚实的基础。