码迷,mamicode.com
首页 > 其他好文 > 详细

机器学习实战——kNN分类器

时间:2014-12-08 17:47:16      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:机器学习   knn   垃圾邮件   

惰性学习法:简单的存储数据,一直等待,直到给定一个测试元组时才进行泛化,根据对存储的元组的相似性进行分类。kNN(k近邻)分类方法于20世纪50年代提出,由于计算密集型算法,因此到60年代之后随着计算能力增强后才逐步应用。

kNN基于类比学习,将给定的测试元组表示为n维空间中的一个点,n代表属性数目。然后使用某种距离度量方式来寻找与给定测试元组最近的k个训练元组,对这个k个训练元组的类别进行统计,返回类别数目多的类别作为未知测试元组的类别。

常用的距离度量就是欧几里得距离,也称为二范数。同时为了减小不同属性值的取值范围对距离计算的影响,一般使用最大-最小规范化将属性值都变换到[0,1]区间。

根据上述特性,可知kNN算法最适合应用在数值型属性上,对于序数型属性可以变换为数值型,标称型属性规范化后也比较好,但是二元属性则可能效果不是太好。主要优缺点:

优点:精度高,对噪声不敏感,无需数据输入假定

缺点:时间和空间复杂度高,需要确定k值(k值的确定可能需要很多经验)

下面是使用《机器学习实战》一书中的kNN算法对一个垃圾邮件的数据进行实际分类的实现。这个数据共有3065个训练样本,1536个测试样本。每个样本使用了57个特征,特征中有数值型数据和二元属性,类别标号为{0,1},0表示不是垃圾邮件,1表示是垃圾邮件。

首先是从文件读取数据:

def loadDataSet(fp):
    if os.path.exists(fp):
        try:
            fh = open(fp, 'r')
            rtnTrainSet = zeros((TRAINSET_NUM, FEATURES_NUM))
            trainLabel = []
            rtnTestSet = zeros((TESTSET_NUM, FEATURES_NUM))
            testLabel = []
            i = 0
            for line in fh:
                line = line.strip()
                terms = line.split(',')
                if i < TRAINSET_NUM:
                    rtnTrainSet[i,:] = terms[0:FEATURES_NUM]
                    trainLabel.append(int(terms[FEATURES_NUM]))
                    i += 1
                else:
                    rtnTestSet[i - TRAINSET_NUM, :] = terms[0:FEATURES_NUM]
                    testLabel.append(int(terms[FEATURES_NUM]))
                    i += 1
        except Exception, msg:
            print 'An unexcepted error occur: ', msg
        finally:
            fh.close()
        return rtnTrainSet,trainLabel,rtnTestSet,testLabel
    else:
        print "The data file does not exists!"
        return None
文件每一行代表一个样本,各特征使用逗号分隔,最后一个字段为类别标号。这里面使用的是Numpy这个第三方库存储数据到矩阵中。

然后是数据的规范化处理,规范化到[0,1]区间。

def normalize(ds):
    minVals = ds.min(0)
    maxVals = ds.max(0)
    ranges = maxVals - minVals
    normDS = zeros(shape(ds))
    n = ds.shape[0]
    normDS = ds - tile(minVals, (n, 1))
    normDS = normDS / tile(ranges, (n, 1))
    return normDS

最后,分类器的实现就是将每个待测试的样本输入,使用训练样本计算最近的k个邻居然后得出最多的类别。

def kNNclassify(ds, labels, k, inputX):
    dsSize = ds.shape[0]
    diff = tile(inputX, (dsSize, 1)) - ds
    sqDiff = diff ** 2
    sqDist = sqDiff.sum(axis = 1)
    dist = sqDist ** 0.5
    sortedDist = dist.argsort()
    classCount = {}
    for i in range(k):
        votedLabel = labels[sortedDist[i]]
        classCount[votedLabel] = classCount.get(votedLabel, 0) + 1
    sortedClassCount = sorted(classCount.iteritems(),
                              key = operator.itemgetter(1),reverse = True)
    return sortedClassCount[0][0]
对1536个测试数据进行分类,同时使用不同的k值,得到不同k值分类的准确率,绘制了如下的图表:

bubuko.com,布布扣

从图中可以看出当k为10的时候精确度为75%为最高,这个结果并不是太好,主要原因是垃圾邮件的57个特征中有部分二元属性,当使用kNN进行分类计算距离时会有较大影响。

最后使用k=10对训练集也进行测试,得到如下结果。

Train Accuracy: 0.9282

bubuko.com,布布扣

机器学习实战——kNN分类器

标签:机器学习   knn   垃圾邮件   

原文地址:http://blog.csdn.net/u010487568/article/details/41804651

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!