统计学习方法第三章K近邻算法(KNN)

# -*- coding: utf-8 -*-
# @FileName: 统计学习方法第三章K近邻算法
# @Software: PyCharm
# @Author  : li Xu
# @Time    :2021//03//02

import time

import numpy as np


def loaddata(fileName):
    '''
    加载数据集
    :param fileName: 要加载的数据集路径
    :return:
    '''
    print('start to read file')
    # 存放数据及标记
    dataArr = []
    labelArr = []
    # 读取文件
    fr = open(fileName, 'r')
    # 遍历文件的每一行
    for line in fr.readlines():
        # 获取当前行,并按“,”切割成字段放入列表中
        # strip:去掉每行字符串首尾指定的字符(默认空格或换行符)
        # split:按照指定的字符将字符串切割成每个字段,返回列表形式
        curline = line.strip().split(',')
        # 将每行中除标记外的数据放入数据集中(curLine[0]为标记信息)
        # 在放入的同时将原先字符串形式的数据转换为整型
        dataArr.append([int(num) for num in curline[1:]])
        # 将标记信息放入标记集中
        # 放入的同时将标记转换为整型
        labelArr.append(int(curline[0]))
    # 返回数据集和标记
    return dataArr, labelArr


def calDist(x1, x2):
    '''
    计算两个样本之间得距离(一般情况使用欧氏距离)
    :param x1:向量1
    :param x2:向量2
    :return:两向量之间得距离
    '''
    return np.sqrt(np.sum(np.square(x1 - x2)))  # np.square计算元素的平方


def getClosest(trainDataMat, trainLabelMat, x, topK):
    '''
    预测样本x的标记。
    获取方式通过找到与样本x最近的topK个点,并查看它们的标签。查找里面占某类标签最多的那类标签
    :param trainDataMat:训练集数据集
    :param trainLabelMat:训练集标签集
    :param x:要预测的样本x
    :param topK:选择参考最邻近样本的数目(样本数目的选择关系到正确率,详看3.2.3 K值的选择)
    :return:预测的标记
    '''
    # 建立一个存放向量x与每个训练集中样本距离的列表
    # 列表的长度为训练集的长度,distList[i]表示x与训练集中第i个样本的距离
    distList = [0] * len(trainLabelMat)
    # 遍历训练集中所有的样本点,计算与x的距离
    for i in range(len(trainDataMat)):
        # 获取训练集中当前样本的向量
        x1 = trainDataMat[i]
        # 计算向量x与训练集样本x的距离
        curDist = calDist(x1, x)
        # 将距离放入对应的列表位置中
        distList[i] = curDist
    # 对距离列表进行排序,argsort:函数将数组的值从小到大排序后,并按照其相对应的索引值输出
    topKlist = np.argsort(np.array(distList))[:topK]  # 升序排列
    # 建立一个长度时的列表,用于选择数量最多的标记
    labelList = [0] * 10
    # 对topK个索引进行遍历
    for index in topKlist:
        labelList[int(trainLabelMat[index])] += 1
    return labelList.index(max(labelList))


def model_test(trainDataArr, trainLabelArr, testDataArr, testLabelArr, topK):
    '''
    测试正确率
    :param trainDataArr:训练集数据集
    :param trainLabelArr: 训练集标记
    :param testDataArr: 测试集数据集
    :param testLabelArr: 测试集标记
    :param topK: 选择多少个邻近点参考
    :return: 正确率
    '''
    print('start test')
    # 将所有列表转换为矩阵形式,方便运算
    trainDataMat = np.mat(trainDataArr);
    trainLabelMat = np.mat(trainLabelArr).T
    testDataMat = np.mat(testDataArr);
    testLabelMat = np.mat(testLabelArr).T
    # 错误值计数
    errorCnt = 0
    # 遍历测试集,对每个测试集样本进行测试,由于计算向量与向量之间的时间耗费太大,测试集有6000个样本
    # 所以这里人为改成了测试200个样本点
    for i in range(200):
        print('test %d:%d' % (i, 200))
        # 读取测试集当前测试样本的向量
        x = testDataMat[i]
        # 获取预测的标记
        y = getClosest(trainDataMat, trainLabelMat, x, topK)
        # 如果预测标记与实际标记不符,错误值计数加1
        if y != testLabelMat[i]:
            errorCnt += 1
    # 返回正确率
    return 1 - (errorCnt / 200)


if __name__ == '__main__':
    start = time.time()
    # 获取训练集
    trainDateArr, trainLabelArr = loaddata('Mnist/mnist_train.csv')
    # 获取测试集
    testDataArr, testLabelArr = loaddata('Mnist/mnist_test.csv')
    # 计算测试集正确率
    accuracy = model_test(trainDateArr, trainLabelArr, testDataArr, testLabelArr, 25)
    # 打印正确率
    print('accuracy is:%d' % (accuracy * 100), '%')
    end = time.time()
    # 显示花费时间
    print('time span:', end - start)

accuracy is:97 %
time span: 465.8361213207245
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值