2018-09-12 15:05:08 Amo_te_ama_me 阅读数 70

一 概述

最近在看《机器学习实战》这本书,书中的代码都是对某种算法在对应应用场景的实现,感觉比大学时代的数据结构或者算法题还要晦涩难懂,只能慢慢学习了,算法这种东西类似做数学题,要多做多练。

K-近邻算法一个典型的应用场景就是在区别电影类别中,比如说根据在电影片段中出现亲吻,打
斗场景来判断电影是否是爱情片或是动作片。

简单来说,K-紧邻算法采用测量不同特征值之间的距离方法进行分类。

二 工作原理

存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

算法步骤为:

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

三 代码实例

首先我们先准备一个简单的数据集:

from numpy import *
import operator


def createDataSet():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])  # 训练样本
    labels = ['A', 'A', 'B', 'B']  # 标签向量
    return group, labels
if __name__ == '__main__':
    #创建测试数据集
    group, labels = createDataSet()
    #打印测试数据集
    print(group)
    print(labels)

然后是k-近邻算法:

"""
函数说明:kNN算法,分类器

Parameters:
    inX - 用于分类的数据(测试集)
    dataSet - 用于训练的数据(训练集)
    labes - 分类标签
    k - kNN算法参数,选择距离最小的k个点
Returns:
    sortedClassCount[0][0] - 分类结果
"""
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]  # 第二维的长度 https://blog.csdn.net/u010758410/article/details/71554224
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet  # https://blog.csdn.net/ksearch/article/details/21388985
    sqDiffMat = diffMat ** 2  # 幂 - 返回x的y次幂
    sqDistances = sqDiffMat.sum(axis=1)  # 将一个矩阵的每一行向量相加
    distances = sqDistances ** 0.5  # 求根
    sortedDistIndicies = distances.argsort()  # 元素从小到大排列,提取其对应的index(索引),然后输出
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # python3中用items()替换python2中的iteritems()
    # key=operator.itemgetter(1)根据字典的值进行排序
    # key=operator.itemgetter(0)根据字典的键进行排序
    # reverse降序排序字典
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

代码主要含义就是根据两点距离公式:
这里写图片描述
计算距离,选择距离最小的前k个点,并返回分类结果。

测试代码:

if __name__ == '__main__':
    # 创建数据集
    group, labels = kNN.createDataSet()
    # kNN分类
    print(kNN.classify0([0, 0], group, labels, 3))

打印出‘B’,证明运行正确。

以上代码其实就是为了实现上面的数学公式,第一次接触用python写科学计算代码的同学可能感觉到很吃力,不要着急,慢慢练习就熟练了。

2015-11-07 17:27:58 niuwei22007 阅读数 12812
k近邻算法(kNN)

        本博客来源于CSDN:http://blog.csdn.net/niuwei22007/article/details/49703719

              本博客源代码下载地址:CSDN免费下载GitHub下载地址 均带有详细注释和测试数据

        今天学习了《机器学习实战》这本书介绍的第一个机器学习算法—k近邻算法。书中介绍它对于分类非常有效,比如书中的例子是对电影的题材进行分类。

一、算法原理

        算法原理是什么?允许我不严谨的说一下:首先有一堆有标签的样本,比如有一堆各种各样的鸟(样本集),我知道各种鸟的不同外貌(特征),比如羽毛颜色有无脚蹼身体重量身体长度以及最重要的它属于哪一种鸟类别/标签);然后给我一只不是这堆鸟中的一只鸟(测试样本),让我观察了它的羽毛颜色等后,让我说出它属于哪一种鸟?我的做法是:遍历之前的一堆鸟,分别比较每一只鸟的羽毛颜色、身体重量等特征与给定鸟的相应特征,并给出这两只鸟的相似度。最终,从那一堆鸟中找出相似度最大的前k,然后统计这k只鸟的分类,最后把分类数量最多的那只鸟的类别作为给定的类别。虽然结果不一定准确,但是是有理论支持的,那就是概率论,哈哈。

        下面来看一下书上对这个算法的原理介绍:存在一个训练样本集,并且每个样本都存在标签(有监督学习)。输入没有标签的新样本数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出与样本集中特征最相似的数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,而且k通常不大于20。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

二、如何解决问题

        没接触过的同学应该能懂了吧。书中的举例是对电影的题材进行分类:爱情片or动作片。依据电影中打斗镜头和接吻镜头的数量。下面来看一下如何用kNN来解决这个问题。

        

        要解给定一部电影,判断其属于哪一种电影这个问题,就需要知道这个未知电影存在多少个打斗镜头和接吻镜头,上图所示,问号位置所代表的两种镜头次数分别是多少?

        下面我们来看一下图中电影的特征值,如下表:


        相信看过数据以后,即使不知道未知电影(?)属于哪一种类型,但是可以通过某个计算方法计算出来。

  • 第一步:首先计算未知电影与已知电影的相似度(抽象距离--相似度越小,距离越远)。具体如何计算暂且不考虑。下面看一下相似度列表:

  • 第二步:再将相似度列表排序,选出前k个最相似的样本。此处我们假设k=3,将上表中的相似度进行排序后前3分别是:He’s Not Really into DudesBeautiful WomanCalifornia Man
  • 第三步:统计最相似样本的分类。此处很容易知道这3个样本均为爱情片。
  • 第四步:将分类最多的类别作为未知电影的分类。那么我们就得出结论,未知电影属于爱情片。

        下面贴一下书上总结的k近邻算法的一般流程:


三、用python实现kNN算法之简单分类

#coding=UTF8
from numpy import *
import operator

def createDataSet():
    """
    函数作用:构建一组训练数据(训练样本),共4个样本
    同时给出了这4个样本的标签,及labels
    """
    group = array([
        [1.0, 1.1],
        [1.0, 1.0],
        [0. , 0. ],
        [0. , 0.1]
    ])
    labels = ['A', 'A', 'B', 'B']
    return group, labels

def classify0(inX, dataset, labels, k):
    """
    inX 是输入的测试样本,是一个[x, y]样式的
    dataset 是训练样本集
    labels 是训练样本标签
    k 是top k最相近的
    """
    # shape返回矩阵的[行数,列数],
    # 那么shape[0]获取数据集的行数,
    # 行数就是样本的数量
    dataSetSize = dataset.shape[0] 
    
    """
    下面的求距离过程就是按照欧氏距离的公式计算的。
    即 根号(x^2+y^2)
    """
    # tile属于numpy模块下边的函数
    # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A
    # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2]
    # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2],
    #                  [0, 1, 2, 0, 1, 2]]
    # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]],
    #                    [[0, 1, 2, 0, 1, 2]]] 
    # 上边那个结果的分开理解就是:
    # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的
    # 然后C包含1个元素,即C=[E],同理D=[E]
    # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的
    # F就是A了,基础元素
    # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]]
    # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。
    # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离
    # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较;
    # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。
    # 比如inX = [0,1],dataset就用函数返回的结果,那么
    # tile(inX, (4,1))= [[ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0]]
    # 作差之后
    # diffMat = [[-1.0,-0.1],
    #            [-1.0, 0.0],
    #            [ 0.0, 1.0],
    #            [ 0.0, 0.9]]
    diffMat = tile(inX, (dataSetSize, 1)) - dataset
    
    # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。
    # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。
    # sqDiffMat = [[1.0, 0.01],
    #              [1.0, 0.0 ],
    #              [0.0, 1.0 ],
    #              [0.0, 0.81]]
    sqDiffMat = diffMat ** 2
    
    # axis=1表示按照横轴,sum表示累加,即按照行进行累加。
    # sqDistance = [[1.01],
    #               [1.0 ],
    #               [1.0 ],
    #               [0.81]]
    sqDistance = sqDiffMat.sum(axis=1)
    
    # 对平方和进行开根号
    distance = sqDistance ** 0.5
    
    # 按照升序进行快速排序,返回的是原数组的下标。
    # 比如,x = [30, 10, 20, 40]
    # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3]
    # 那么,numpy.argsort(x) = [1, 2, 0, 3]
    sortedDistIndicies = distance.argsort()
    
    # 存放最终的分类结果及相应的结果投票数
    classCount = {}
    
    # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数
    for i in range(k):
        # index = sortedDistIndicies[i]是第i个最相近的样本下标
        # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B')
        voteIlabel = labels[sortedDistIndicies[i]]
        # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0
        # 然后将票数增1
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    
    # 把分类结果进行排序,然后返回得票数最多的分类结果
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

if __name__== "__main__":
    # 导入数据
    dataset, labels = createDataSet()
    inX = [0.1, 0.1]
    # 简单分类
    className = classify0(inX, dataset, labels, 3)
    print 'the class of test sample is %s' %className

四、用python实现kNN算法之改进分类


#coding=UTF8
from numpy import *
import operator
from os import listdir

def classify0(inX, dataset, labels, k):
    """
    inX 是输入的测试样本,是一个[x, y]样式的
    dataset 是训练样本集
    labels 是训练样本标签
    k 是top k最相近的
    """
    # shape返回矩阵的[行数,列数],
    # 那么shape[0]获取数据集的行数,
    # 行数就是样本的数量
    dataSetSize = dataset.shape[0] 
    
    """
    下面的求距离过程就是按照欧氏距离的公式计算的。
    即 根号(x^2+y^2)
    """
    # tile属于numpy模块下边的函数
    # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A
    # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2]
    # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2],
    #                  [0, 1, 2, 0, 1, 2]]
    # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]],
    #                    [[0, 1, 2, 0, 1, 2]]] 
    # 上边那个结果的分开理解就是:
    # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的
    # 然后C包含1个元素,即C=[E],同理D=[E]
    # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的
    # F就是A了,基础元素
    # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]]
    # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。
    # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离
    # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较;
    # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。
    # 比如inX = [0,1],dataset就用函数返回的结果,那么
    # tile(inX, (4,1))= [[ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0]]
    # 作差之后
    # diffMat = [[-1.0,-0.1],
    #            [-1.0, 0.0],
    #            [ 0.0, 1.0],
    #            [ 0.0, 0.9]]
    diffMat = tile(inX, (dataSetSize, 1)) - dataset
    
    # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。
    # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。
    # sqDiffMat = [[1.0, 0.01],
    #              [1.0, 0.0 ],
    #              [0.0, 1.0 ],
    #              [0.0, 0.81]]
    sqDiffMat = diffMat ** 2
    
    # axis=1表示按照横轴,sum表示累加,即按照行进行累加。
    # sqDistance = [[1.01],
    #               [1.0 ],
    #               [1.0 ],
    #               [0.81]]
    sqDistance = sqDiffMat.sum(axis=1)
    
    # 对平方和进行开根号
    distance = sqDistance ** 0.5
    
    # 按照升序进行快速排序,返回的是原数组的下标。
    # 比如,x = [30, 10, 20, 40]
    # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3]
    # 那么,numpy.argsort(x) = [1, 2, 0, 3]
    sortedDistIndicies = distance.argsort()
    
    # 存放最终的分类结果及相应的结果投票数
    classCount = {}
    
    # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数
    for i in range(k):
        # index = sortedDistIndicies[i]是第i个最相近的样本下标
        # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B')
        voteIlabel = labels[sortedDistIndicies[i]]
        # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0
        # 然后将票数增1
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    
    # 把分类结果进行排序,然后返回得票数最多的分类结果
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
    
def file2matrix(filename):
    """
    从文件中读入训练数据,并存储为矩阵
    """
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #获取 n=样本的行数
    returnMat = zeros((numberOfLines,3))        #创建一个2维矩阵用于存放训练样本数据,一共有n行,每一行存放3个数据
    classLabelVector = []                       #创建一个1维数组用于存放训练样本标签。  
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        # 把回车符号给去掉
        line = line.strip()    
        # 把每一行数据用\t分割
        listFromLine = line.split('\t')
        # 把分割好的数据放至数据集,其中index是该样本数据的下标,就是放到第几行
        returnMat[index,:] = listFromLine[0:3]
        # 把该样本对应的标签放至标签集,顺序与样本集对应。
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector
    
def autoNorm(dataSet):
    """
    训练数据归一化
    """
    # 获取数据集中每一列的最小数值
    # 以createDataSet()中的数据为例,group.min(0)=[0,0]
    minVals = dataSet.min(0) 
    # 获取数据集中每一列的最大数值
    # group.max(0)=[1, 1.1]
    maxVals = dataSet.max(0) 
    # 最大值与最小的差值
    ranges = maxVals - minVals
    # 创建一个与dataSet同shape的全0矩阵,用于存放归一化后的数据
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    # 把最小值扩充为与dataSet同shape,然后作差,具体tile请翻看 第三节 代码中的tile
    normDataSet = dataSet - tile(minVals, (m,1))
    # 把最大最小差值扩充为dataSet同shape,然后作商,是指对应元素进行除法运算,而不是矩阵除法。
    # 矩阵除法在numpy中要用linalg.solve(A,B)
    normDataSet = normDataSet/tile(ranges, (m,1))
    return normDataSet, ranges, minVals
   
def datingClassTest():
    # 将数据集中10%的数据留作测试用,其余的90%用于训练
    hoRatio = 0.10
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        print "the classifier came back with: %d, the real answer is: %d, result is :%s" % (classifierResult, datingLabels[i],classifierResult==datingLabels[i])
        if (classifierResult != datingLabels[i]): errorCount += 1.0
    print "the total error rate is: %f" % (errorCount/float(numTestVecs))
    print errorCount

if __name__=="__main__"
    datingClassTest()

        改进一:数值归一化

        第三节就是按照第二节中描述实现的算法。但是这只是最简单的分类,当遇到特征值相差很大的时候,分类效果就不好了。比如,原来的dataSet中有一个这样的样本:[1, 10000]。同时输入样本仍然为第三节中测试的[0.1, 0.1]。所以很明显,当求这两个样本之间的距离的时候就出问题,由于那个10000太大,对最终的结果影响最大,其他的0.1和1可以忽略不计了。因此就用到了数值归一化。如果还有不太清楚地,百度一下。详细实现看代码,有详细注释。

        改进二:从文件中读入数据

        要做一个稍微复杂一点的测试,就需要多准备点样本数据,而在第三节中,训练样本只有4个,而且是固定生成的。在新的算法里边加入了可以从文件中读取训练数据。代码有详细注释。

五、用python实现kNN算法之手写数字识别

        识别手写数字,需要先把手写数字图片转换为相应的01矩阵格式,这里提供已经经过转换的数据文件。trainingDigits是2000个训练样本,testDigits是900个测试样本。

#coding=UTF8
from numpy import *
import operator
from os import listdir

def classify0(inX, dataset, labels, k):
    """
    inX 是输入的测试样本,是一个[x, y]样式的
    dataset 是训练样本集
    labels 是训练样本标签
    k 是top k最相近的
    """
    # shape返回矩阵的[行数,列数],
    # 那么shape[0]获取数据集的行数,
    # 行数就是样本的数量
    dataSetSize = dataset.shape[0] 
    
    # tile属于numpy模块下边的函数
    # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A
    # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2]
    # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2],
    #                  [0, 1, 2, 0, 1, 2]]
    # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]],
    #                    [[0, 1, 2, 0, 1, 2]]] 
    # 上边那个结果的分开理解就是:
    # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的
    # 然后C包含1个元素,即C=[E],同理D=[E]
    # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的
    # F就是A了,基础元素
    # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]]
    # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。
    # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离
    # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较;
    # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。
    # 比如inX = [0,1],dataset就用函数返回的结果,那么
    # tile(inX, (4,1))= [[ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0],
    #                    [ 0.0, 1.0]]
    # 作差之后
    # diffMat = [[-1.0,-0.1],
    #            [-1.0, 0.0],
    #            [ 0.0, 1.0],
    #            [ 0.0, 0.9]]
    diffMat = tile(inX, (dataSetSize, 1)) - dataset
    
    # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。
    # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。
    # sqDiffMat = [[1.0, 0.01],
    #              [1.0, 0.0 ],
    #              [0.0, 1.0 ],
    #              [0.0, 0.81]]
    sqDiffMat = diffMat ** 2
    
    # axis=1表示按照横轴,sum表示累加,即按照行进行累加。
    # sqDistance = [[1.01],
    #               [1.0 ],
    #               [1.0 ],
    #               [0.81]]
    sqDistance = sqDiffMat.sum(axis=1)
    
    # 对平方和进行开根号
    distance = sqDistance ** 0.5
    
    # 按照升序进行快速排序,返回的是原数组的下标。
    # 比如,x = [30, 10, 20, 40]
    # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3]
    # 那么,numpy.argsort(x) = [1, 2, 0, 3]
    sortedDistIndicies = distance.argsort()
    
    # 存放最终的分类结果及相应的结果投票数
    classCount = {}
    
    # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数
    for i in range(k):
        # index = sortedDistIndicies[i]是第i个最相近的样本下标
        # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B')
        voteIlabel = labels[sortedDistIndicies[i]]
        # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0
        # 然后将票数增1
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    
    # 把分类结果进行排序,然后返回得票数最多的分类结果
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
    
def file2matrix(filename):
    """
    从文件中读入训练数据,并存储为矩阵
    """
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #获取 n=样本的行数
    returnMat = zeros((numberOfLines,3))        #创建一个2维矩阵用于存放训练样本数据,一共有n行,每一行存放3个数据
    classLabelVector = []                       #创建一个1维数组用于存放训练样本标签。  
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        # 把回车符号给去掉
        line = line.strip()    
        # 把每一行数据用\t分割
        listFromLine = line.split('\t')
        # 把分割好的数据放至数据集,其中index是该样本数据的下标,就是放到第几行
        returnMat[index,:] = listFromLine[0:3]
        # 把该样本对应的标签放至标签集,顺序与样本集对应。
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector
    
def autoNorm(dataSet):
    """
    训练数据归一化
    """
    # 获取数据集中每一列的最小数值
    # 以createDataSet()中的数据为例,group.min(0)=[0,0]
    minVals = dataSet.min(0) 
    # 获取数据集中每一列的最大数值
    # group.max(0)=[1, 1.1]
    maxVals = dataSet.max(0) 
    # 最大值与最小的差值
    ranges = maxVals - minVals
    # 创建一个与dataSet同shape的全0矩阵,用于存放归一化后的数据
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    # 把最小值扩充为与dataSet同shape,然后作差,具体tile请翻看 第三节 代码中的tile
    normDataSet = dataSet - tile(minVals, (m,1))
    # 把最大最小差值扩充为dataSet同shape,然后作商,是指对应元素进行除法运算,而不是矩阵除法。
    # 矩阵除法在numpy中要用linalg.solve(A,B)
    normDataSet = normDataSet/tile(ranges, (m,1))
    return normDataSet, ranges, minVals
   
def img2vector(filename):
    """
    将图片数据转换为01矩阵。
    每张图片是32*32像素,也就是一共1024个字节。
    因此转换的时候,每行表示一个样本,每个样本含1024个字节。
    """
    # 每个样本数据是1024=32*32个字节
    returnVect = zeros((1,1024))
    fr = open(filename)
    # 循环读取32行,32列。
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])
    return returnVect

def handwritingClassTest():
    hwLabels = []
    # 加载训练数据
    trainingFileList = listdir('trainingDigits')           
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        # 从文件名中解析出当前图像的标签,也就是数字是几
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]     #take off .txt
        classNumStr = int(fileStr.split('_')[0])
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
    # 加载测试数据
    testFileList = listdir('testDigits')        #iterate through the test set
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]     #take off .txt
        classNumStr = int(fileStr.split('_')[0])
        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
        print "the classifier came back with: %d, the real answer is: %d, The predict result is: %s" % (classifierResult, classNumStr, classifierResult==classNumStr)
        if (classifierResult != classNumStr): errorCount += 1.0
    print "\nthe total number of errors is: %d / %d" %(errorCount, mTest)
    print "\nthe total error rate is: %f" % (errorCount/float(mTest))

if __name__== "__main__":
    handwritingClassTest()    

六、小结

        引用原话:k近邻算法是分类数据最简单最有效的算法。k紧邻算法必须保存全部数据集,如果训练数据集很大,必须使用大量的存储空间。此外,由于必须对数据集中的每个数据计算距离值,实际使用时可能非常耗时。(这些是很容易理解的)

        k近邻算法的另外一个缺陷是它无法给出任何数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。(就是说k近邻算法只能是单纯的比较样本特征值之间的大小关系,给出样本之间的欧氏距离,并不能给出这些特征数据的内在含义。还是比较抽象!用一句不太恰当的描述是:k近邻算法只是知道两个样本之间的有区别,长得像不像,机械的区分样本之间的差别,没有类似于人的理解能力。)

2017-06-23 09:08:52 xundh 阅读数 3250

本文内容来自《机器学习实战》中国工信出版集团 人民邮电出版社

一、简介

简单地说,k-近邻算法采用测量不同特征值之间的距离方法进来分类
特点:

  • 优点:精度高、对异常值不敏感、无数据输入假定
  • 缺点:计算复杂度高、空间复杂度高
  • 适用数据范围:数值型和标称型

k-近邻算法称为kNN,它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前κ个最相似的数据,这就是k-近邻算法中κ的出处。通常κ是不大于20的整数。最后,选择κ个最相似数据出现次数最多的分类,作为新数据的分类。

二、示例

电影分类。
样本数据:

电影名称 打斗镜头 接吻镜头 电影类型
California Man 3 104 爱情片
He’s Not Really into Dudes 2 100 爱情片
Beautiful woman 1 81 爱情片
Kevin Longblade 101 10 动作片
Robo Slayer 3000 99 5 动作片
Amped II 98 22 动作片
? 18 90 未知

如果我们计算出已知电影与未知电影的距离:

电影名称 与未知电影的距离
California Man 20.5
He’s Not Really into Dudes 18.7
Beautiful woman 19.2
Kevin Longblade 115.3
Robo Slayer 3000 117.4
Amped II 118.9

按照距离递增排序,可以找到k个距离最近的电影。假定k=3,则三个最靠近的电影依次是:

  1. He’s Not Really into Dudes
  2. Beautiful woman
  3. California Man

kNN按照距离最近的三部电影的类型,决定未知电影的类型——爱情片。

三、Python操作

1. 使用Python导入数据

from numpy import *
import operator

def createDataSet():
#用来创建数据集和标签
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group , labels

这里有4组数据,每组数据有两个我们已知的属性或者特征值。向量labels包含了每个数据点的标签信息,labels包含的元素个数等于group矩阵行数。这里将数据点(1,1.1)定义为类A,数据点(0,0.1)定义为类B。为了说明方便,例子中的数值是任意选择的,并没有给出轴标签。
这里写图片描述
kNN,带有4个数据点的简单例子。

2. 实施kNN分类算法

代码流程为:
计算已知类别数据集中的每个点依次执行以下操作

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

classify0函数:

def classify0(inX,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX,(dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

参数说明:

  • inX:用于分类的输入向量
  • dataSet:输入的训练样本集
  • labels:标签向量
  • k:用于选择最近邻居的数目

其中标签向量的元素数目和矩阵dataSet的行数相同。程序使用的是欧氏距离公式,计算向量xA与xB之间的距离:

d=(xA0xB0)2+(xA1xB1)2

计算完距离后,对数据按照从小到大排序,确认前k个距离最小元素民在的主要分类。输入k总是正整数;最后,将classCount字典分解为元组列表,然后使用程序第二行导入运算符模块的itemgetter方法,按照第二个元素的次序对元组进行排序,最后返回发生频率最高的元素标签。
运行测试:

group , labels = createDataSet()
print(classify0([0,0],group,labels,3))

这里写图片描述

3. 如何测试分类器

错误率是评估常用方法,完美的错误率为0,最差错误率是1.0。

四、示例:使用kNN改进约会网站的配对效果

1.使用Matplotlib创建散点图

准备一份样本数据。

每年获得的飞行常客里程数 玩视频游戏所耗时间百分比 每周消费的冰淇淋公升数
40920   8.326976    0.953952    3
14488   7.153469    1.673904    2
26052   1.441871    0.805124    1
75136   13.147394   0.428964    1
38344   1.669788    0.134296    1
...

代码:

from numpy import *
import operator

def classify0(inX,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX,(dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

def file2matrix(filename):
    fr = open(filename)
    arrayOfLines = fr.readlines()
    numberOfLines = len(arrayOfLines)
    returnMat = zeros((numberOfLines,3))
    classLabelVector = []
    index = 0
    for line in arrayOfLines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1

datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')

import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
plt.show()

获得的散点图示例:
这里写图片描述

样本数据可以在网上通过搜索”datingTestSet2.txt”获得。这里散点图使用datingDataMat矩阵的第二、第三列数据,分别表示特征值“玩视频游戏所耗时间百分比”和“每周所消费的冰淇淋公升数”。

由于没有使用样本分类的特征值,在图上很难看出任何有用的数据模式信息。一般来说,可以采用色彩或其他的记号来标记不同样本分类,以便更好地理解数据信息。进行这样的修改:

ax.scatter(datingDataMat[:,1],datingDataMat[:,2] ,15.0*array(datingLabels),15.0*array(datingLabels))

这里写图片描述

利用变量datingLabels存储的类标签属性,在散点图上绘制了色彩不等、尺寸不同的点。

2.准备数据:归一化数值

归一化数值将不同取值范围的特征值进行数值归一化,如将取值范围处理为0到1或者-1到1之间。通过下面公式可以将取值范围特征值转化为0到1区间内的值:

newValue=(oldValuemin)/(maxmin)

其中min和max分别是数据集中的最小特征值和最大特征值。虽然改变数值取值范围增加了分类器的复杂度,但为了得到准确结果,我们必须这样做。下面autoNorm()函数实现归一化:

def autoNorm(dataSet):
      minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals -minVals
    nromDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals,(m,1))
    normDataSet = normDataSet/tile(ranges,(m,1))
    return normDataSet , ranges , minVals

normMat , ranges , minVals = autoNorm(datingDataMat)

3.测试算法

通常我们使用已有数据的90%作为训练样本来训练分类器,而使用10%的数据去测试分类器,检测分类器的正确率。创建一个测试函数:

def datingClassTest():
    hoRatio = 0.10
    datingDataMat , datingLabels = file2matrix('datingTestSet.txt')
    normMat,ranges,minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],\
                                    datingLabels[numTestVecs:m],3)
        print ("the classifier came back with : %d,the real answer is :%d"\
              %(classifierResult,datingLabels[i]))
        if(classifierResult != datingLabels[i]):errorCount += 1.0
    print ("the total error rate is :%f" % (errorCount / float(numTestVecs)))

使用

normMat , ranges , minVals = autoNorm(datingDataMat)
datingClassTest()

4.补全程序,实现完整功能

def classifyPerson():
    resultList = ['not at all','in small doses','in large doses']
    percentTats = float(input("percetage of time spent playing video games?"))
    ffMiles = float(input("frequent flier miles earned per year?"))
    iceCream = float(input("listers of ice cream consumed per year?"))
    datinDataMat,datingLabels = file2matrix('datingTestSet2.txt')
    normMat,ranges ,minVals=autoNorm(datingDataMat)
    inArr = array([ffMiles,percentTats,iceCream])
    classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print ("You will probably like this person:",resultList[classifierResult - 1])

classifyPerson()

运行结果示例:
这里写图片描述

2018-03-13 16:37:41 cd_home 阅读数 459

# 环境 win10 + py3

一 . k-紧邻算法概述

分类:KNN算法属于监督学习的一种

算法:k-近邻算法采用测量不同特征值之间的距离进行分类

优点:精度高,对异常值不敏感,无数据输入假定

缺点:计算的时间和空间复杂度较高

适用数据范围:数值型和标称型

二.k-近邻算法的一般流程

①收集数据

②准备数据:距离计算所需要的数值,最好是格式化数据

③分析数据

④测试算法:计算错误率

⑤使用算法

三.使用k-近邻算法原理和python代码实现

原理:对未知分类的数据中的每个点依次执行下面的操作

①计算已知类别的数据集中的每个点和当前点之间的距离

②按距离递增排序

③选取于当前点距离最小的K个点

④确定k个点所在类别出现的概率

⑤返回前k个点出现频率最高的分类,作为预测分类

使用python实现代码如下:

from numpy import *

import operator

def classify0(inX, dataSet, labels, k):
    '''k-近邻算法'''
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]

这个函数传入的参数分别是:inX(用于分类的输入向量)

                                            dataSet(输入的训练样本集)

                                            labels(标签向量)

                                            k(最后选择的近邻数目)


核心公式:计算两点之间xA和xB的距离。使用欧氏距离公式

 


四.实例:使用k-近邻改进约会网站的配对效果

约会网站统计出三条特征值,分别是:

                                                   ①每周飞行里数

                                                   ②玩游戏视频消耗时间的百分比

                                                   ③每周消耗冰淇凌的公升数

                                                目标值:

                                                     1.不喜欢

                                                     2.魅力一般

                                                     3.极具魅力   

过程:

①收集数据:本次使用已经存在的数据集,点击下载只做学习参考,请勿用于商业用途

②准备数据:使用Python解析文本文件

③分析数据:使用Matplotlib画二维扩散图

④测试算法:

⑤使用算法:

代码如下:

一.首先将文本解析

form numpy import *
def file2matrix(filename):
'''将文本记录转换到NumPy的解析程序'''
fr = open(filename) # 打开文本
numberOfLines = len(fr.readlines()) # 获得文本行数
returnMat = zeros((numberOfLines,3)) # 设置另一维度为3(可以根据需要调整)
classLabelVector = []
fr = open(filename)
index = 0
for line in fr.readlines(): # 循环处理每行数据("40920   8.326976    0.953952    3")
line = line.strip() # 截掉所有的回车字符('40920\t8.326976\t0.953952\t3')
listFromLine = line.split('\t') # 使用制表符,将整行数据分割成一个元素列表(['40920', '8.326976', '0.953952', '3'])
returnMat[index,:] = listFromLine[0:3] # 获取前三个元素将他们存储到特征矩阵中
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
datingDataMat,datingLabels = file2matrix("datingTestSet2.txt")
print(file2matrix("datingTestSet2.txt"))

输出结果如下


二.为了更加直观的了解数据的含义使用Matplotlib使数据可视化

import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1], datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels ))
plt.show()

输出效果如下:

横坐标:玩视频游戏的百分比

纵坐标:每周消费的冰激凌公升数


更改字段:

ax.scatter(datingDataMat[:,1], datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels ))

输出效果如下:

横坐标:每年飞行的里程

纵坐标:玩视频游戏所占的百分比


三:归一化数据

根据上面的图片可以看出。如果想计算某两个样本之间的距离,使用欧姓距离公式,因为飞行里程数和其他数据相比十分巨大,会对结果造成关键的影响,但是实际上飞行里程数对分类结果造成的影响应该没有这么巨大。

所以在处理不同取值范围的特征值时,通常采用的方法是将数据归一化。将取值范围处理到0到1,或者-1到1之间。

归一化公式:

newValue = (oldValue-min)/(max-min)

min, max 分别为特征的最小,最大值

### (有点类似于按比例缩小)

归一化python代码实现:

def autoNorm(dataSet):
    '''数据归一化'''
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges, (m,1)) #element wise divide
return normDataSet, ranges, minVals
normMat,ranges,minVals = autoNorm(datingDataMat)
normMat,ranges,minVals

运行结果》》》


四.测试算法

一般情况下使用10%-20%左右的数据作为测试集数据。要求测试数据是在整个样本数据中随机产生的。

代码如下

import operator
def datingClassTest():
hoRatio = 0.10 #选出10%
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #加载数据
normMat, ranges, minVals = autoNorm(datingDataMat) # 归一化数据
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) #数据传入分类器
print ("分类器的计算结果是: %d, 实际的值是: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print("分类器的错误率是: %f" % (errorCount/float(numTestVecs)))
print('总共错判:',errorCount)

结果如下:


正确率95%,应该还可以.

## k-近邻算法,k的取值会对正确率产生很大影响,如何确认k的选值十分重要。

五.使用分类器

def classMan():
iflist = ['不喜欢','有些魅力','魅力十足']
ftime = float(input('每周的飞行时间是:'))
gtime = float(input('玩游戏所占的时间比是:'))
ice = float(input('每周消耗的冰激凌公升数:'))
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #加载数据
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ftime,gtime,ice])
classifierResult = classify0((inArr -minVals)/ranges,normMat,datingLabels,3)
print('猜你对这个人的感觉是:',iflist[classifierResult-1])
classMan()

结果如下:


下面是完整代码:

from numpy import *
import operator

def file2matrix(filename):
'''将文本记录转换到NumPy的解析程序'''
fr = open(filename) # 打开文本
numberOfLines = len(fr.readlines()) # 获得文本行数
returnMat = zeros((numberOfLines,3)) # 设置另一维度为3(可以根据需要调整)
classLabelVector = []
fr = open(filename)
index = 0
for line in fr.readlines(): # 循环处理每行数据("40920   8.326976    0.953952    3")
line = line.strip() # 截掉所有的回车字符('40920\t8.326976\t0.953952\t3')
listFromLine = line.split('\t') # 使用制表符,将整行数据分割成一个元素列表(['40920', '8.326976', '0.953952', '3'])
returnMat[index,:] = listFromLine[0:3] # 获取前三个元素将他们存储到特征矩阵中
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
# datingDataMat,datingLabels = file2matrix("datingTestSet2.txt")

def autoNorm(dataSet):
'''归一化'''
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges, (m,1))
return normDataSet, ranges, minVals


def classify0(inX, dataSet, labels, k):
'''k-近邻'''
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]

def datingClassTest():
'''测试类器正确率'''
hoRatio = 0.10 #选出10%
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #加载数据
normMat, ranges, minVals = autoNorm(datingDataMat) # 归一化数据
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) #数据传入分类器
print("分类器的计算结果是: %d,实际的值是: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print( "分类器的错误率是: %f" % (errorCount/float(numTestVecs)))
print('总共错判',errorCount)
def classMan():
iflist = ['不喜欢','有些魅力','魅力十足']
ftime = float(input('每周的飞行时间是:'))
gtime = float(input('玩游戏所占的时间比是:'))
ice = float(input('每周消耗的冰激凌公升数:'))
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #加载数据
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ftime,gtime,ice])
classifierResult = classify0((inArr -minVals)/ranges,normMat,datingLabels,3)
print('猜你对这个人的感觉是:',iflist[classifierResult-1])
classMan()


总结:主要流程就是数据集的解析,归一化,测试,使用。k-近邻算法对k的选值不好把握。对结果影响也比较大


主要参考:机器学习实战 原书链接 

原文使用py2 ,本文使用py3,代码略有不同







2019-12-21 11:29:42 haohaixingyun 阅读数 6

 

 

  sklearn 机器学习
  决策树 k-紧邻算法
  随机森林 决策树
  数据处理和特征工程 朴素贝叶斯
  主成分分析pca与奇异值分解svd Logistic 回归
  逻辑回归 支持向量机
  聚类算法和k-means Adaboost
  svm 线性回归
  线性回归,岭回归,Lasso 树回归
  朴素贝叶斯 k-均值聚类算法
  XGBoost Apriori 算法
  神经网络 Fp-growth 算法
    奇异值分解svd

 

没有更多推荐了,返回首页