《机器学习实战笔记--第一部分 分类算法:KNN算法 1》

    在监督学习中,我们只需要输入给定的样本集,机器就可以推出指定目标变量的可能结果。监督学习一般使用两种类型的目标变量:标称值和数值型。标称值目标变量只在有限目标中取值,数值型目标变量则从无限的数值中取值。

分类算法:第二章:k-近邻算法,使用距离矩阵进行分类;

                第三章:决策树;

                第四章:讨论使用概率论建立分类器;

                第五章:Logistic回归;使用最有参数正确分类原始数据,在搜索最优参数的过程中常用的集中优化算法;

                第六章:支持向量机;

                第七章:元算法:AdaBoost


Numpy函数库的使用基础:

    >>>random.rand(4,4)

    将会构造一个4*4的随机数组    

    Tip: Numpy函数库中会存在两种不同的数据类型(矩阵matrix和数组array),都可以用于处理行列表示的数字元素,虽然看起来很相似,但是在两个数据类型上执行相同的数学运算可能会产生不同的结果。

    使用mat()函数可以将数组转化为矩阵;.I操作符可以实现矩阵求逆


    下面我们将介绍本书的第一个分类算法:k—近邻算法(KNN)

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

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

    确定:计算复杂度高,空间复杂度高; 

    适用于数值型和标称型。

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

    k-近邻算法的一般流程:

(1)收集数据:任意方法收集;

(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式;

(3)分析数据:可以使用任何方法;

(4)训练算法:此步骤不适合k-近邻算法;

(5)测试算法:计算错误率;

(6)使用算法:首先需要驶入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入的数据分别属于哪一类,最后应用对计算出的分类结果执行后续的处理。


1、准备:使用python导入数据

创建KNN.py文件

from numpy import *
import operator
"""
科学计算包和运算符模块
k-近邻算法在执行排序操作是使用这个模块提供的函数
"""
def createDataset():

    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])

//注意array中()内还有[],在存入各个数组

    labels = ['A','A','B','B']

    return group,labels

为了方便,使用createDataset()函数,它用来创建数据集和标签。保存KNN.py文件,在新的模块中导入KNN.py


这里的四组数据,每组数据有两个我们已知的属性或特征值。group矩阵每行包含一个不同的数据,向量labels包含元素的个数等于group的矩阵行数。下图是带有标签的四个数据点。



2、从文本中解析数据

使用程序清单2-1的函数运行KNN算法为每组数据进行分类。该函数的功能是使用KNN算法将每组数据划分到某个类中。

首先给出KNN的算法和伪代码和实际的python代码

对未知的类别属性的数据集中的每个点依次执行一下操作:

(1)计算已知类别数据集中的点与当前点之间的距离;

(2)按照距离递增排序;

(3)选取与当前点距离最小的K个点;

(4)确定前K个点所在类别的出现频率;

(5)返回前K个点出现频率最高的类别作为当前点的预测分类。

函数classify0()如程序清单2-1所示:

import KNN
from numpy import *
import operator
group,labels = KNN.createDataset()

def classify0(inX, dataSet, labels, k):
    """
    用于分类的输入向量:inX
    输入训练集:dataSet
    标签向量:labels
    选择近邻的数目:k
    """
    #标签向量的元素和矩阵dataSet的行数相同,dataSetSize为行数
    dataSetSize = dataSet.shape[0]
    
    #将inX向量按行重复dataSetSize次,列重复一次,变成与dataSet一样的形式,并计算差值diffMat
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    
    #对差值求平方
    sqDiffMat = diffMat**2
    #axis=1 把每一行向量的值加在一起求和
    sqDistances = sqDiffMat.sum(axis=1)
    #开平方
    distances = sqDistances**0.5
    
    #argsort():将x中的元素从小到大排列,提取其对应的index(索引),然后输出索引
    sortedDistIndicies = distances.argsort()
    classCount={}
    for i in range(k):
        #sortedDistIndicies[i]返回的是distances中排在第i个数值的索引
        #labels[i]:即返回的是第i个位置的向量的标签存入voteIlabel
        voteIlabel = labels[sortedDistIndicies[i]]
        #更新字典中对应标签的数值
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    
    """
    sorted(iterable[, cmp[, key[, reverse]]])
    参数解释:


(1)iterable指定要排序的list或者iterable,不用多说;


(2)cmp为函数,指定排序时进行比较的函数,可以指定一个函数或者lambda函数,如:
      students为类对象的list,每个成员有三个域,用sorted进行比较时可以自己定cmp函数,例如这里要通过比较第三个数据成员来排序,代码可以这样写:
      students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
       sorted(students, key=lambda student : student[2])
(3)key为函数,指定取待排序元素的哪一项进行排序,函数用上面的例子来说明,代码如下:
       sorted(students, key=lambda student : student[2]) 
       key指定的lambda函数功能是去元素student的第三个域(即:student[2]),因此sorted排序时,会以students所有元素的第三个域来进行排序。
有了上面的operator.itemgetter函数,也可以用该函数来实现,例如要通过student的第三个域排序,可以这么写:
sorted(students, key=operator.itemgetter(2)) 
sorted函数也可以进行多级排序,例如要根据第二个域和第三个域进行排序,可以这么写:
sorted(students, key=operator.itemgetter(1,2)) 
    
    """

    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)

    #这里python3的写法是classCount.items()与原书不同

    return sortedClassCount[0][0]



以之前创建的训练集,调用分类函数可得到的分类结果如上所示。

程序清单2-1使用欧氏距离公式,计算两个向量点xA,xB之间的距离



计算完所有的距离后,对数据按从小到大进行排序,确定前k个距离最小元素所在的主要分类。

猜你喜欢

转载自blog.csdn.net/qq_41635352/article/details/79956430