KNN算法(10折交叉验证)

一、问题描述

在UC Irvine Machine Learning数据集上选择三个数据,编写KNN算法预测结果,并使用十次-十折交叉验证

二、数据集选用

1.Wine.data
2.Iris.data
3.O-ring-erosion-only.data
实验平台:Python3.7
数据集下载
提取码:7060

三、 KNN分类器

kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。
原理:
1.存在一个训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。
2.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。在这里距离一般用欧式距离或曼哈顿距离。
在这里插入图片描述

3.一般的,我们只选择样本数据集中前k个最相似的数据,通常k是不大于20的整数,最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

四、 十折交叉验证

十折交叉验证是将训练集分割成10个子样本,一个单独的子样本被保留作为验证模型的数据,其他9个样本用来训练。交叉验证重复10次,每个子样本验证一次,平均10次的结果或者使用其它结合方式,最终得到一个单一估测。这个方法的优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,10次交叉验证是最常用的。

五、源码

'''
    1、计算已知类别数据集中的点与当前点之间的距离
    2、按照距离递增次序排序
    3、选取与当前点距离最小的k个点
    4、确定前k个点所在类别的出现概率
    5、返回前k个点出现频率最高的类别作为当前点的预测分类
'''
import numpy as np
import operator

#处理文本
def fileToMatrix(iris):
    fr = open(iris)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)
    returnMat = np.zeros((numberOfLines, 5))
    classLabelVector = []
    index = 0
    for line in arrayOLines:
        line = line.strip()
        listFromLine = line.split(',')
        returnMat[index,:] = listFromLine[0:5]
        classLabelVector.append(listFromLine[-1])
        index += 1
    return returnMat, classLabelVector

#功能:归一化数据,避免某些数据的特征值过大
#def autoNorm(dataSet):
def autoNorm(dataSet):
    minVals = dataSet.min(0)#取列值的最小值
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m,1))
    normDataSet = normDataSet/np.tile(ranges, (m, 1))#特征值相除
    return normDataSet, ranges, minVals

#功能:kNN核心算法
#intX - 输入向量,dataSet - 输入训练样本集,labels - 标签向量,k表示用于选择最近邻居的数目
#def classify(inX, dataSet, labels, k):
def classify(inX, dataSet, labels,k):
    #欧式距离的计算
    dataSize = dataSet.shape[0]#数据的行数
    diffMat = np.tile(inX, (dataSize,1)) - dataSet#将输入向量inX纵向重复dataSet的行数次
    sqDiffMat = diffMat ** 2 #距离度量,度量公示为欧氏距离
    sqDistances = sqDiffMat.sum(axis = 1)# 每行数据相加
    distances = sqDistances ** 0.5#得到训练样本集每一点与当前点的距离
    sortedDistIndicies = distances.argsort() #对欧式距离进行排序
    #选择距离最小的k个点
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]#最近K个的距离对应的类别
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#类别分别出现的概率
    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)#选择发生频率最高的元素标签进行排序
    return sortedClassCount[0][0]

#功能:#功能:十折交叉验证
#思路:将数据集分成十份,轮流将其中9份做训练1份做测试,10次结果的均值作为对算法精度的估计
#一般还要进行多次10倍交叉验证

#def dataClassTest(iris, k):
if __name__=='__main__':
    file_data = 'iris.data'
    k=5
    testRate = 0.1
    datingDataMat, datingLabels = fileToMatrix(file_data)
    datingDataMat = datingDataMat[:,:k-1]
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m * testRate)
    all = 0
    for k in range(1,11):
        t = normMat[0:numTestVecs]
        p = datingLabels[0:numTestVecs]
        for i in range(numTestVecs):
            errorCount = 0
            classifierResult = classify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
            if(classifierResult != datingLabels[i]):    errorCount += 1.0
        #----------将第几折的数据拿出来,放回到normMat的前面
        b = normMat[numTestVecs*(k-1):numTestVecs*k]
        normMat[0:numTestVecs] = b
        normMat[numTestVecs*(k-1):numTestVecs*k] = t
        errorRate = errorCount/float(numTestVecs)
        #----------将第几折类别拿出来,放回到datingLabels的前面
        c = datingLabels[numTestVecs*(k-1):numTestVecs*k]
        datingLabels[0:numTestVecs] = c
        datingLabels[numTestVecs*(k-1):numTestVecs*k] = p
        errorRate = errorCount/float(numTestVecs)
        all = all + errorRate
        #------------------------------------------------------------------
        print("第%d折分类的错误率为%f" % (k,(errorCount/float(numTestVecs))))
    #获得平均错误率
    print("平均正确率为%f" % (1-(all/10)))

六、实验结果

6.1 wine.data
在这里插入图片描述
6.2 iris.data
在这里插入图片描述
6.3 o-ring-erosion-only.data
在这里插入图片描述

七、 实验结果分析总结:

   通过对比三个数据集,数据类型相似或相近,在酒和鸢尾花上交叉验证的准确率分别高达94%和99%,在O形圈上的准确率是50%,这是与数据中的数据特征相关,数据本身数值影响了分类准确率。KNN算法优点是精度较高、无数据输入假定;缺点是空间复杂度高。验证法与2折、3折相比,10折同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,能得到更精确的分类器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值