K近邻算法

今天天有点热啊,刚好又停电了,闲来无事就实现了下K近邻算法。K近邻算法的思想是将欲分类新数据的特征与所有样本的特征一一做比较,找出K个最相似数据(距离最短)的标签,然后找出K个标签里出现最多的标签,即为所分类的新数据的标签。具体见K近邻算法

用Python实现了下,代码如下所示:

# -*- coding: utf-8 -*-
"""
Created on Sun Jul 07 15:40:25 2013

@author: lming_08
"""

import numpy as np

train_set_count = 16000
    
def create_dataset(file_name):
    fd = open(file_name)
    lines = fd.readlines()
    #inst_count = len(lines)    #实例数
    #vec_dimension = len(lines[0])    #向量维数

    class_label = []    #类别标签
    feature_vec_set = np.zeros((train_set_count, 16), dtype = np.int)    #特征向量集
    
    index = 0
    for line in lines:
        if index >= train_set_count:
            break
        line = line.strip()
        data = line.split(",")        
        
        class_label.append(data[0])
        feature_vec_set[index, :] = [np.int(data[i]) for i in range(1, len(data))]
        index += 1
   
    #feature_vec_set is ndarray, and class_label is list     
    return feature_vec_set, class_label
    
def KNN(inX, feature_vec_set, class_label, k):
    train_set_count = len(class_label)

    dist_array = np.zeros((train_set_count, 1), dtype = np.int)
    inX_repeat = np.tile(inX, (train_set_count, 1))

    diff_array = inX_repeat - feature_vec_set
    
    sqdiff_array = diff_array ** 2    
    dist_array = sqdiff_array.sum(axis = 1)    #每一行求和
    sorted_index = dist_array.argsort()
    
    votelabel = [0] * 26    #26个字母分别对应0...25
    for i in range(k):
        ch = class_label[sorted_index[i]]    #对应的标签        
        votelabel[ord(ch) - 65] = votelabel[ord(ch) - 65] + 1
        
    votelabel_min_index = votelabel.index(max(votelabel))
    
    return chr(votelabel_min_index + 65)
    
if __name__ == "__main__":
    feature_vec_set, class_label = create_dataset("./letter_recognition/letter_recognition.txt")
    
    fd = open("./letter_recognition/remain_4000rows.txt")
    fd_result = open("./letter_recognition/test_result.txt", "a")
    lines = fd.readlines()
    
    test_count = 0
    error_count = 0
    for line in lines:
        test_count += 1
        line = line.strip()
        data = line.split(",")
        inX = np.array([np.int(data[i]) for i in range(1, len(data))])
        ch = KNN(inX, feature_vec_set, class_label, 20)
        
        if line[0] != ch:
            #print(u"分类的标签是%c,其实际标签是%c" % (line[0], ch))
            fd_result.write("分类的标签是%c,其实际标签是%c\n" % (line[0], ch))
            error_count += 1
    
    print(u"测试样本数为%d, 错误率为%f" % (test_count, error_count / float(test_count)))
    fd.close()
    fd_result.close()
    
代码中用到的训练样本集是来自于美国加州大学欧文分校的机器学习数据资源,用来对字母进行识别的数据集,具体见http://archive.ics.uci.edu/ml/datasets/Letter+Recognition

训练样本集是采用letter_recognition.txt中头16000行数据,而后4000行数据用于测试

运行代码如下所示:

F:\python_workspace>python KNN.py
测试样本数为4000, 错误率为0.073750


可以看出错误率为7.375%,再查看下误分类的情况,可以查看下test_result.txt文件,部分如下所示:

分类的标签是G,其实际标签是C
分类的标签是A,其实际标签是Y
分类的标签是K,其实际标签是L
分类的标签是P,其实际标签是H
分类的标签是H,其实际标签是B
分类的标签是K,其实际标签是G
分类的标签是G,其实际标签是R
分类的标签是X,其实际标签是E
分类的标签是H,其实际标签是D
分类的标签是J,其实际标签是I
分类的标签是E,其实际标签是G
分类的标签是H,其实际标签是Y
分类的标签是D,其实际标签是B
分类的标签是N,其实际标签是D
分类的标签是H,其实际标签是Q
分类的标签是G,其实际标签是X
分类的标签是H,其实际标签是K
分类的标签是Q,其实际标签是O

...


实际运行过程中速度很慢,这是因为每一个测试向量都要与每一个训练样本向量比较距离,算法复杂度较高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值