机器学习——k- 近邻算法(kNN)

k- 近邻算法

 

  • 需要用到的模块:numpy,operator

 

1、定义函数

  • 函数1:从文件中提取数据,形成numpy数组
  • 函数2:归一化数据
  • 函数3:分类器
  • 函数4:检验分类器错误率

 

2、分类器步骤

  • 定义距离(一般采用欧式距离)
  • 按照距离排序
  • 选取距离要分类的数据最近的k个点(距离最小)
  • 确定这k个点类别频率
  • 返回频率最高的类别作为预测分类
     

3、代码

from numpy import *
import operator

##从文本中提取信息
def filemat(filename):
    file = open(filename)
    lines = file.readlines()
    lines_number = len(lines)
    
    #创建一个与文本相同行,相同列的零矩阵
    #列需要事前确定
    zeromat = zeros((lines_number,3))
    
    #空字典作为类别
    class_label = []
    index = 0
    
    #提取文件数据
    for line in lines:
        line = line.strip()
        line_list = line
        list1 = line.split('\t')
        #用文件中的数据替换零矩阵和空类别
        zeromat[index,:] = list1[0:3]
        class_label.append(list1[-1])
        index+=1
    return zeromat,class_label
 
## 归一化方法:(x-min)/range       
def  auto_norm(dataset):
    # 选取每一列的最大最小值
    min_value = dataset.min(0)
    max_value = dataset.max(0)
    ranges = max_value - min_value
    # 形成一个与数据集相同的零矩阵
    norm_dataset = zeros(shape(dataset))
    shape0 = dataset.shape[0]
    # 得到当前值与最小值的差值矩阵
    norm_dataset = dataset - tile(min_value,(shape0,1))
    norm_dataset = norm_dataset/tile(ranges,(shape0,1))
    return norm_dataset,ranges,min_value

## 欧氏距离分类(注意需不需要事先将X归一化)
def classify(X,dataset,labels,k):
    # shape函数的功能是读取矩阵的维度
    # shape[0]代表一维中的元素数,二维中的行数
    datasetsize = dataset.shape[0]
    
    # 创建X与所有点的距离数组
    diffMat = tile(X,(datasetsize,1))-dataset
    sqdiffMat = diffMat**2
    sqDistances = sqdiffMat.sum(axis=1)
    distances = sqDistances **0.5
    
    #从小到大排列所有点与X的距离
    sortDisindex = distances.argsort()#列表
    classCount={}
    
    #选择前k个距离最近的点并统计这k个点的类别次数
    for i in range(k):
        klabel = labels[sortDisindex[i]]
        classCount[klabel] = classCount.get(klabel,0)+1
    
    #将k个点的类别出现次数进行排序,取最高出现次数的类别
    sortclasscount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    # 返回分类结果
    return sortclasscount[0][0]
    

## 检测分类器错误率(自分类为测试集和训练集)    
def classify_test(data_mat,data_labels,ratio=0.1):
    line_num = data_mat.shape[0]
    test_num = int(ratio*line_num)
    error_count = 0.0
    for i in range(test_num):
        classify_result = classify(data_mat[i,:],data_mat[test_num:line_num,:],\
                                   data_labels[test_num:line_num],k=3)
        if (classify_result != data_labels[i]) : error_count+=1
    error_rate = float(error_count)/(float(test_num)) 
    return error_rate

 

4、example

from os import listdir
import numpy as np
import operator
import kNN
## 读取文件
def imagex(filename):
    f = open(filename)
    # 形成一个1024维的行向量
    return_vector = zeros((1,1024))
    for i in range(32):
        line_str = f.readline()
        for j in range(32):
            return_vector[0,32*i+j] = int(line_str[j])
    return return_vector

def handwritingtest():
    hwlabels=[]
    # 将文件夹下所有文件名提出,需要与代码在同一文件夹
    training_list = listdir('trainingDigits')
    test_list = listdir('testDigits')
    train_num = len(training_list)
    test_num = len(test_list)
    train_mat = zeros((train_num,1024))
    # 训练集—将所有文件中的数据放入一个numpy数组
    for i in range(train_num):
        filename = training_list[i]
        file = filename.split('.')[0]
        class_number = int(file.split('_')[0])
        hwlabels.append(class_number)
        train_mat[i,:] = imagex('trainingDigits/%s'%filename)
    error_count0 =0.0
     # 测试集进行测试
    for i in range(test_num):
        filename = test_list[i]
        file = filename.split('.')[0]
        class_number = int(file.split('_')[0])
        test_vector = imagex('testDigits/%s'%filename)
        class_result = classify(test_vector,train_mat,hwlabels,k=3)
        if (class_result != class_number):error_count0+=1
    error_rate = float(error_count0)/(float(test_num)) 
    return error_rate

if __name__=="__main__":
    rate = handwritingtest()
    print(rate)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值