机器学习实战第2章-knn

本文的代码基于机器学习实战,然后修改了一些部分,以适应3.x的Python

首先是用到的库

import pandas as pd
import numpy as np
import heapq
from collections import  Counter
import os

读数据

def file2matrix(filename):
    df = pd.read_csv(filename,sep="\t",header=None)
    matrix = df.to_numpy()
    x = matrix[...,0:-1]
    label = matrix[...,-1]
    return x , label

这里以及后续更新的,读取数据方面都是使用pandas库,操作简单,且转化成numpy后容易切片操作

分类

def classify0(inX, dataSet, labels, k):
    distance = np.sum((dataSet - inX)**2,axis=1)**0.5
    k_largest_ind = heapq.nsmallest(k,range(len(distance)),distance.take)
    k_label = labels[k_largest_ind]
    cnt_dict = Counter(k_label)
    return heapq.nlargest(1,cnt_dict.items(),key = lambda x:x[1])[0][0]

注意这里,dataset的维度是nm,n是数据集个数,m是样本的特征维度,labels的维度是n1,然后inx是要被预测的样本,维度是1m
这里的dataSet-inX,numpy进行了广播操作,把inx扩展成了n
m,然后再相减,得到的是一个n*m的数组,而每一行的平方和再开方就是样本和每个数据的欧氏距离了,所以这里sum时指定axis为1,
第二行就能利用堆得到前k个最小距离的数据下标,
第3行就能利用下标得到k个邻居的标签了,然后使用Python自带的Counter得到计数字典并返回最大的那个

标准化

这个不用说,对knn来说几乎是必须的一步,无量纲化能去掉某些指标太大而带来的负面影响

def autoNorm(dataSet):
    minval = np.min(dataSet,axis=0)
    rangeval = np.max(dataSet,axis=0)-np.min(dataSet,axis=0)
    return (dataSet - minval ) / ( rangeval ),minval,rangeval

这个还要返回最小值和最大值因为后面在预测时也需要用他们来标准化数据

在dating数据集上的表现

def dating_dataset_test():
    hold_out = 0.7
    dataset, labels= file2matrix("datingTestSet2.txt")
    normdata,minval,rangeval = autoNorm(dataset)
    n = normdata.shape[0]
    test_data = normdata[:int(0.3*n)]
    train_data = normdata[int(0.3*n):]
    test_label = labels[:int(0.3*n)]
    train_label = labels[int(0.3*n):]
    error = 0
    for (x,y) in zip(test_data,test_label):
        if classify0(x,train_data,train_label,3)!=y:
            error += 1
    print("the error is {}".format(error/(n*0.3)))

这里采用了留出法的验证方法,所以实际上里面的test_data应该是valid_data,懒得改了233
把数据集化为7:3的训练集和验证集,而knn是不需要训练的,所以这里就直接验证了
zip函数是Python自带的,挺好用的一个函数,

读取手写数字的数据集

def img2vector(filename):
    data = pd.read_csv(filename,header=None).to_numpy()
    vector = np.zeros((1,1024))

    for i in range(32):
        for j in range(32):
            vector[0][32*i+j]=data[i][0][j]
    return vector

这里的数据集并不是mnist那个,只不过是为了方便操作,作者自己编了一些数据集罢了

构造数据集

def read_data_in_file(filedir):
    filelist = os.listdir("trainingDigits")
    n = len(filelist)
    training_x = np.zeros((n, 1024))
    training_y = np.zeros((n,))
    for i in range(n):
        filename = "/".join(("trainingDigits", filelist[i]))
        training_x[i] = img2vector(filename)
        training_y[i] = int(filelist[i][0])
    return training_x,training_y

使用os库,再配合上join函数,我们能容易得到所需的文件名,然后遍历下去就能得到数据集啦

手写数字的训练表现

def head_written_dataset_test():
    training_x, training_y = read_data_in_file("trainingDigit")
    test_x, test_y = read_data_in_file("testDigit")
    error = 0
    for (x,y) in zip(test_x,test_y):
        if classify0(x,training_x,training_y,4) !=y:
            error += 1
    print("the error rate is {}".format(error/len(test_y)))

这儿没啥好说的啦

总的原书的代码就是这些内容,当然还有很多我们可以自己拓展实现的,比如说对k的选取可以编个函数去看看效果,比如说选取的距离度量方式可以编写成其他方式,而这2个也是knn的效果的比较重要的影响因素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值