type
status
date
slug
summary
tags
category
icon
password
线性回归算法(回归)、logistics回归算法(分类)、KNN(分类)、朴素贝叶斯(分类)、决策树(分类)、支持向量机(分类)、K均值聚类(聚类)、神经网络(深度学习、多层感知机)
python机器学习算法
机器学习的最主要的一项工作就是“训练模型”,训练模型的过程就是机器学习算法实现的过程,这里的算法和我们经常提及的算法有些区别,比如插入排序、归并排序等,它们的结果都是“计算出来的”,只要确定输入,就可以给定一个值,而机器学习的算法是“猜”出来的,既然是猜,那么就会有对有错,机器学习会根据猜的“结果”,不断的优化模型,从而得出正确率最高的“结果”。
机器学习的学习形式可以分为两大类:
- 有监督学习
- 无监督学习
每一类学习形式都对应着相应的算法,比如线性回归算法、KNN 分类算法、朴素贝叶斯分类算法、支持向量机算法等等,并且这些算法都有与其相适用的场景。
什么是人工智能
人工智能
“人工智能”(Artificial Intelligence),英文缩写为 AI 从字面意思来看,它指的是让机器获得像人一样的智慧。
由于互联网和云计算的兴起,计算机硬件、性能也得到了大幅度提升,因此“人工智能”在经历了数十年的低谷期后终于迎来了第三次发展热潮。
互联网和云计算之所以让“人工智能”再次复兴,其原因主要有两点:一是互联网能够提供海量的数据;二是云计算提供了超强的计算能力。
机器学习&深度学习
机器学习是人工智能的一部分,而深度学习又是机器学习的一部分。人工智能的范围最为广泛,机器学习是人工智能的核心分支,也是当前发展最迅猛的一部分,而关于深度学习,它之前也属于“机器学习”的一个分支,其主要研究对象是神经网络算法。
单从定义上来说,机器学习是一种功能、方法,或者更具体的说是一种算法,它能够赋予机器进行学习的能力,从而使机器完成一些通过编程无法直接实现的功能。但从具体的实践意义来说,其实机器学习是利用大量数据训练出一个最优模型,然后再利用此模型预测出其他数据的一种方法。比如要识别猫、狗照片就要拿它们各自的照片提炼出相应的特征(比如耳朵、脸型、鼻子等),从而训练出一个具有预测能力的模型。
学习形式分类
机器学习是人工智能的主要表现形式,其学习形式主要分为:有监督学习、无监督学习、半监督学习等,监督一词可以理解为习题的“参考答案”,专业术语叫做“标记”。比如有监督学习就是有参考答案的学习,而无监就是无参考答案。
1) 有监督学习
有监督学习(supervised learning),需要你事先需要准备好要输入数据(训练样本)与真实的输出结果(参考答案),然后通过计算机的学习得到一个预测模型,再用已知的模型去预测未知的样本,这种方法被称为有监督学习。这也是是最常见的机器学习方法。简单来说,就像你已经知道了试卷的标准答案,然后再去考试,相比没有答案再去考试准确率会更高,也更容易。
2) 无监督学习
理解了有监督学习,那么无监督学习理解起来也变的容易。所谓无监督学习(unsupervised learning)就是在没有“参考答案”的前提下,计算机仅根据样本的特征或相关性,就能实现从样本数据中训练出相应的预测模型。
除了上述两种学习形式外,还有半监督学习和强化学习。
预测结果分类
根据预测结果的类型,我们可以对上述学习形式做具体的问题划分,这样就可以具体到实际的应用场景中,比如有监督学习可以划分为:回归问题和分类问题。如果预测结果是离散的,通常为分类问题,而为连续的,则是回归问题。
1) 回归&分类
连续和离散是统计学中的一种概念,全称为“连续变量”和“离散变量”。比如身高,从 1.2m 到 1.78m 这个长高的过程就是连续的,身高只随着年龄的变化一点点的长高。那么什么是“离散变量”呢?比如超市每天的销售额,这类数据就是离散的,因为数据不是固定,可能多也可能少。
2) 聚类
无监督学习是一种没有“参考答案”的学习形式,它通过在样本之间的比较、计算来实现最终预测输出,比如聚类问题,那什么是“聚类”?其实可以用一个成语表述“物以类聚,人以群分”,将相似的样本聚合在一起后,然后进行分析。
机器学习常用术语
机器学习术语
1) 模型
它是机器学习中的核心概念。你可以把它看做一个“魔法盒”,你向它许愿(输入数据),它就会帮你实现愿望(输出预测结果)。整个机器学习的过程都将围绕模型展开,训练出一个最优质的“魔法盒”,它可以尽量精准的实现你许的“愿望”,这就是机器学习的目标。
2) 数据集
数据集,从字面意思很容易理解,它表示一个承载数据的集合,如果说“模型”是“魔法盒”的话,那么数据集就是负责给它充能的“能量电池”,简单地说,如果缺少了数据集,那么模型就没有存在的意义了。数据集可划分为“训练集”和“测试集”,它们分别在机器学习的“训练阶段”和“预测输出阶段”起着重要的作用。
3) 样本&特征
样本指的是数据集中的数据,一条数据被称为“一个样本”,通常情况下,样本会包含多个特征值用来描述数据,比如现在有一组描述人形态的数据“180 70 25”如果单看数据你会非常茫然,但是用“特征”描述后就会变得容易理解,如下所示:
由上图可知数据集的构成是“一行一样本,一列一特征”。特征值也可以理解为数据的相关性,每一列的数据都与这一列的特征值相关。
4) 向量
向量是机器学习的关键术语。向量在线性代数中有着严格的定义。向量也称欧几里得向量、几何向量、矢量,指具有大小和方向的量。您可以形象地把它的理解为带箭头的线段。箭头所指:代表向量的方向;线段长度:代表向量的大小。与向量对应的量叫做数量(物理学中称标量),数量只有大小,没有方向。
在机器学习中,模型算法的运算均基于线性代数运算法则,比如行列式、矩阵运算、线性方程等等。其实对于这些运算法则学习起来并不难,它们都有着一定运算规则,只需套用即可,因此你也不必彷徨,可参考向量运算法则。
向量的计算可采用 NmuPy 来实现。
简而言之,数据集中的每一个样本都是一条具有向量形式的数据。
5) 矩阵
矩阵也是一个常用的数学术语,你可以把矩阵看成由向量组成的二维数组,数据集就是以二维矩阵的形式存储数据的,你可以把它形象的理解为电子表格“一行一样本,一列一特征”表现形式如下:
如果用二维矩阵的表示的话,其格式如下所示:
假设函数&损失函数
机器学习在构建模型的过程中会应用大量的数学函数,从编程角度来看,这些函数就相当于模块中内置好的方法,只需要调用相应的方法就可以达成想要的目的。而要说难点,首先你要理解你的应用场景,然后根据实际的场景去调用相应的方法,这才是你更应该关注的问题。
假设函数和损失函数是机器学习中的两个概念,它并非某个模块下的函数方法,而是我们根据实际应用场景确定的一种函数形式,就像你解决数学的应用题目一样,根据题意写出解决问题的方程组。下面分别来看一下它们的含义。
1) 假设函数
假设函数(Hypothesis Function)可表述为
y=f(x)
其中 x 表示输入数据,而 y 表示输出的预测结果,而这个结果需要不断的优化才会达到预期的结果,否则会与实际值偏差较大。2) 损失函数
损失函数(Loss Function)又叫目标函数,简写为 L(x),这里的 x 是假设函数得出的预测结果“y”,如果 L(x) 的返回值越大就表示预测结果与实际偏差越大,越小则证明预测值越来越“逼近”真实值,这才是机器学习最终的目的。因此损失函数就像一个度量尺,让你知道“假设函数”预测结果的优劣,从而做出相应的优化策略。
3) 优化方法
“优化方法”可以理解为假设函数和损失函数之间的沟通桥梁。通过 L(x) 可以得知假设函数输出的预测结果与实际值的偏差值,当该值较大时就需要对其做出相应的调整,这个调整的过程叫做“参数优化”,而如何实现优化呢?这也是机器学习过程中的难点。其实为了解决这一问题,数学家们早就给出了相应的解决方案,比如梯度下降、牛顿方与拟牛顿法、共轭梯度法等等。因此我们要做的就是理解并掌握“科学巨人”留下的理论、方法。
对于优化方法的选择,我们要根据具体的应用场景来选择应用哪一种最合适,因为每一种方法都有自己的优劣势,所以只有合适的才是最好的。
上述函数的关系图如下所示:
图3:函数关系图
拟合&过拟合&欠拟合
拟合是机器学习中的重要概念,也可以说,机器学习的研究对象就是让模型能更好的拟合数据。
1)拟合
形象地说,“拟合”就是把平面坐标系中一系列散落的点,用一条光滑的曲线连接起来,因此拟合也被称为“曲线拟合”。拟合的曲线一般用函数进行表示,但是由于拟合曲线会存在许多种连接方式,因此就会出现多种拟合函数。通过研究、比较确定一条最佳的“曲线”也是机器学习中一个重要的任务。如下图所示,展示一条拟合曲线(蓝色曲线):
图4:曲线拟合
很多和数学相关的编程语言都内置计算拟合曲线的函数,比如 MATLAB 、Python Scipy 等
2) 过拟合
过拟合(overfitting)也是机器学习模型训练过程中经常遇到的问题,所谓过拟合,通俗来讲就是模型的泛化能力较差,也就是过拟合的模型在训练样本中表现优越,但是在验证数据以及测试数据集中表现不佳。
比如你训练一个识别狗狗照片的模型,如果你只用金毛犬的照片训练,那么该模型就只吸纳了金毛狗的相关特征,此时让训练好的模型识别一只“泰迪犬”,那么结果可想而知,该模型会认为“泰迪”不是一条狗。如下图所示:
图5:过拟合
过拟合问题在机器学习中经常遇到,主要是因为训练时样本过少,特征值过多导致的
3) 欠拟合
欠拟合(underfitting)恰好与过拟合相反,它指的是“曲线”不能很好的“拟合”数据。在训练和测试阶段,欠拟合模型表现均较差,无法输出理想的预测结果。如下图所示:
图6:欠拟合
造成欠拟合的主要原因是由于没有选择好合适的特征值,比如使用一次函数(y=kx+b)去拟合具有对数特征的散落点(y=log2x),示例图如下所示:
图7:欠拟合示例图
欠拟合和过拟合是机器学习中会遇到的问题,这两种情况都不是我期望看到的,因此要避免。
Python机器学习环境搭建
Python
对于编程人员来说,想到“机器学习”第一个关联起来的词汇就是“Python”。近几年, Python 之所成为炙手可热的“流量小生”,这与它对“人工智能”领域的“鲸吞”有很大关系。目前而言,在人工智能领域能与 “Python”一较高下的只有 R 语言。不过由于 Python 语言的简洁性、易读性,以及 Python 对科学计算和深度学习框架(Tensorflow、Pytorch 等)的良好支持等,使得 Python 处于远远领先的位置。
NumPy
NumPy(https://numpy.org/)属于 Python 的第三方扩展程序包,它是 Python 科学计算的基础库,提供了多维数组处理、线性代数、傅里叶变换、随机数生成等非常有用的数学工具。
Pandas
Pandas 属于 Python 第三方数据处理库,它基于 NumPy 构建而来,主要用于数据的处理与分析。我们知道对于机器学习而言数据是尤为重要,如果没有数据就无法训练模型。Pandas 提供了一个简单高效的 DataFrame 对象(类似于电子表格),它能够完成数据的清洗、预处理以及数据可视化工作等。除此之外,Pandas 能够非常轻松地实现对任何文件格式的读写操作,比如 CSV 文件、json 文件、excel 文件。
Scikit-Learn
Scikit-Leran(官网:https://scikit-learn.org/stable/),它是一个基于 Python 语言的机器学习算法库。Scikit-Learn 主要用 Python 语言开发,建立在 NumPy、Scipy 与 Matplotlib 之上,它提供了大量机器学习算法接口(API),因此你可以把它看做一本“百科全书”。由于 Scikit-Learn 的存在极大地提高了机器学习的效率,让开发者无须关注数学层面的公式、计算过程,有更多的更多的时间与精力专注于业务层面,从而解决实际的应用问题。
Scikit-Learn 的基本功能主要被分为六大部分:分类,回归,聚类,数据降维,模型选择和数据预处理。本教程将围绕机器算法的讲解 Scikit-Learn 实际的应用。
当你想要调用机器学习算法时也非常简单,Scikit-Learn 已经将算法按模型分类,比如线性回归算法可以从线性模型中调用,如下所示:
线性回归算法详解
线性回归:其中“线性”表线性模型,而“回归”则表示回归问题,也就是用线性模型来解决回归问题。
看完上述解释,您脑子中可能仍有许多“问号”,线性还可以理解,比如我们所熟知的直线、曲线、线性方程等,那么“回归”又代表什么呢?
其实“回归”一词最早由英国科学家弗朗西斯·高尔顿提出。1875 年,高尔顿利用子代豌豆与父代豌来确定豌豆尺寸的遗传规律。实验的大意是说:非常矮小的的父辈倾向于有偏高的子代,非常高大的的父辈倾向于有偏矮的子代。这表明子代的身高向着父辈身高的平均值回退,后来人们把这种研究方法称为“回归预测”。
线性回归是什么
线性回归主要用来解决回归问题,也就是预测连续值的问题。而能满足这样要求的数学模型被称为“回归模型”。最简单的线性回归模型是我们所熟知的一次函数(即 y=kx+b),这种线性函数描述了两个变量之间的关系,其函数图像是一条连续的直线。如下图蓝色直线:
图1:线性连续函数
还有另外一种回归模型,也就是非线性模型(nonlinear model),它指因变量与自变量之间的关系不能表示为线性对应关系(即不是一条直线),比如我们所熟知的对数函数、指数函数、二次函数等。
图2:非线性连续函数
我们知道“线性回归”就是利用线性模型来解决“回归问题”,那到底什么是回归问题呢?你可以把它理解为“预测”真实值的过程。
在《三国演义》中有一个非常精彩的片段“七星坛诸葛祭风”说的是诸葛亮借东风的故事。其实我们抛开历史,单从科学角度出发,诸葛亮借东风就是一个“回归问题”。首先诸葛亮需要掌握大量的天文地理知识,并凭借自己的知识对以往的天气数据进行大量研究,最后才能预测某个时间将有“东风来临”。这种相似的回归问题,在实际生活中我们经常遇到,比如根据历史行情预测股票走势、预测房屋售价以及电影票房预估等等,而要实现这些预测就需要大量的“历史数据”作为支撑点。
在上述讲解过程中,我们反复提起“预测”与“历史数据”,既然是预测,那么就不能说它是 100 % 精确,所以线性回归只是无限地逼近“真实值”,而这个逼近的过程需要大量“历史数据”提供支持。因此线性回归就是利用线性模型来“预测”真实值的过程。
线性回归方程
那么线性回归是如何实现预测的呢?其实主要是通过“线性方程”,或叫“回归方程”来实现。下面列举一个简单的例子,现有以下一组数据:
输入 | 输出 |
1 | 2 |
2 | 4 |
3 | 6 |
... | ... |
9 | ? |
根据上表中的规律预测出 9 所对应的输出值,并写出线性方程。这个示例是不是非常简单,我们很容易想到 9 对应的是“18”,这是一道小学生都能解出来题,但请您不要小看这么一个简单的示例,它同样说明了很多问题。线性方程如下所示:
Y=2*X
在上述线程方程中2代表权值参数,而求这个参数的过程就是“回归”,一旦有了这个参数,再给定输入,做预测就非常容易了。具体的做法就是用回归系数乘以输入值,这样就得到了预测值。上述示例的预测函数(或称假设函数)可记为:
y = w1x + b
在前面介绍专业术语时,我们提起过“假设函数”,上述函数就是线性模型的“假设函数”。其中 x 表示输入的样本数据,y 表示输出的预测结果,而 w1指的是线性回归模型的权值参数,b 指的是线性回归模型的“偏差值”。解决线性回归问题的关键就在于求出权值参数、偏差值。
权值,可理解为不同“特征”对于预测结果的重要性。权值系数越大,那么这一项属性值对最终结果的影响就越大。
在实际应用中,线性回归模型要更复杂一些,比如要分析实际特征值对结果影响程度的大小,从而调整相应特征值的回归系数。下面举一个简单的应用示例:
现在要判断一个西瓜是否是成熟,根据我们的日常经验可从以下几个特征来判断:外表色泽(x1)、根蒂(x2)、敲声(x3)。而以上三个特征所占用的权值参数也不同。如下所示:
y = 0.2x1+ 0.5x2+ 0.3 x3+1
上述表达式可以看出每一个特征值对预测结果的影响程度不同,根蒂是否“枯萎”对结果影响最大,而外表色泽是否鲜亮,敲声是否沉闷则占据次要因素。
当然采集数据的时也会存在一些无用数据,比如西瓜的外形、价格,这些特征不会对预测结果产生影响,因此它们权值参数为“0”。从这个例子可以得出“权值参数”是决定预测结果是否准确的关键因素。
实现预测的流程
1) 数据采集
任何模型的训练都离不开数据,因此收集数据构建数据集是必不可少的环节。比如现在要预测一套房子的售价,那么你必须先要收集周围房屋的售价,这样才能确保你预测的价格不会过高,或过低。如下表所示:
当然上述样本数量远远不足,如果想要更加准确的预测就要收集更多的数据,至少保证 100 条样本。表格中的最后一栏是“房屋售价”,这是“有监督学习”的典型特点,被称为“标签”,也就是我们所说的“参考答案”。表格中的面积、数量、距离市中心距离(km),以及是否是学区房,这些都是影响最终预测结果的相关因素,我们称之为“特征”,也叫“属性”。
你可能会认为影响房屋售价的不止这些因素,没错,不过采集数据是一个很繁琐的过程,因此一般情况下,我们只选择与预测结果密切相关的重要“特征”。
2) 构建线性回归模型
有了数据以后,下一步要做的就是构建线性回归模型,这也是最为重要的一步,这个过程会涉及到一些数学知识,至于如何构建模型,下一节会做详细介绍。
构建完模型,我们需要对其进行训练,训练的过程就是将表格中的数据以矩阵的形式输入到模型中,模型则通过数学统计方法计算房屋价格与各个特征之间关联关系,也就是“权值参数”。训练完成之后,您就可以对自己的房屋价格进行预测了。首先将数据按照“特征值”依次填好,并输入到模型中,最后模型会输出一个合理的预测结果。示意图如下所示:
图4:流程示意图
从上图可知,回归模型承担着非常重要的作用。
构建线性回归模型
一次函数
一次函数
一次函数就是最简单的“线性模型”,其直线方程表达式为
y = kx + b
其中 k 表示斜率,b 表示截距,x 为自变量,y 表示因变量。下面展示了 y = 2x + 3 的函数图像:
图1:函数图像y=2x+3
函数中斜率 k 与 截距 b 控制着“直线”的“旋转”与“平移”。如果斜率 k 逐渐减小,则“直线”会向着“顺时针”方向旋转,为 k= 0 的时候与 x 轴平行。截距 b 控制“直接”的上下平移,b 为正数则向上平移,b 为负数则表示向下平移。
在机器学习中斜率 k 通常用 w 表示,也就是权重系数,因此“线性方程”通过控制 w 与 b 来实现“直线”与数据点最大程度的“拟合”。如下图(黑色 x 号代表数据样本)所示:
图2:线性拟合
线性方程不能完全等同于“直线方程”,因为前者可以描述多维空间内直接,而后者只能描述二维平面内的 x 与 y 的关系。
构建线性模型
在线性回归问题中数据样本会呈现“线性”分布的态势,因此我们使用“线性方程”来最大程度的“拟合数据”。线性方程预测的结果具有连续性。下面通过示例简单说明:小亮今年 8 岁,去年 7 岁,前年 6 岁,那么他明年几岁呢?估计你闭着眼都能想到答案,但是我们要从机器学习的角度去看待这个问题。
首先年龄、时间是一组连续性的数据,也就是因变量随着自变量规律性地连续增长,显然它是一个“回归问题”。下面把上述数据以二维数组的形式表示出来,构建一个数据集,如下所示:
我们知道两个点就可以确定一条“直线”,因此将两组数据带入 y = kx + b,最终求得“线程方程”:
y = x - 2013
上述函数就是所谓的“假设函数”,通过它即可实现对结果的预测。这个函数的图像如下所示:
图3:假设函数图像
从上述函数图像可以看出,直线对数据样本恰好“拟合”。这是最标准的拟合直线,通过它就可以“预测”出小亮明年的年龄了。上述示例就构建了一个简单的的“线性模型”。读到这里你会惊叹“怎么如此简单”,其实线性模型就是这么简单。对于机器学习而言,最关键的就是“学习”,在大量的数据中,通过不断优化参数,找到一条最佳的拟合“直线”,最终预测出一个理想的结果。
提示:上述示例是一个理想化的“线性模型”,在实际应用中要复杂的多,不过“万变不离其宗”。
机器学习是一门数学、统计学、计算机科学的结合技术,因此它有着独特的知识体系,比如会将数据集分为“训练集”与“测试集”,而且还会通过“损失函数”来不断优化预测结果。
线性回归:损失函数和假设函数
通过前面内容的介绍,我相信你对线性回归算法已经有了初步的认识。那我们应该如何在一大堆数据中求解出“线性方程呢”比如前面提及的房价预测问题?这种问题才是符合实际应用的。数据样本会散落在“线性方程”的周围(下图 2 所示), 而我们要做就是让线性方程的“直线”尽可能“拟合”周围的数据点。本节我们将从数学角度解析线性回归模型。
假设函数
通过前面知识的学习,我们知道假设函数是用来预测结果的。前面讲述时为了让大家更容易理解“线性回归”,我们以“直线方程”进行了类比讲解,然而线性方程并不等同于“直线方程”,线性方程描绘的是多维空间内的一条“直线”,并且每一个样本都会以向量数组的形式输入到函数中,因此假设函数也会发生一些许变化,函数表达式如下所示:
乍一看你可能蒙圈了,记住不用紧张。其实它和 Y=wX + b 是类似的,只不过我们这个标量公式换成了向量的形式。如果你已经学习了 《NumPy 教程》,那么这个公司很好理解,
Y1
仍然代表预测结果, X1
表示数据样本, b
表示用来调整预测结果的“偏差度量值”,而wT
表示权值系数的转置。矩阵相乘法是一个求两个向量点积的过程,也就是按位相乘,然后求和,如下所示: 图1:矩阵乘法运算
矩阵 A 的每一行分别与矩阵 B 的每一列相乘,比如 15+25+37 =36 、12+26+36=32、16+27+3*4=32,即可得出结果的第一行数据。
转置操作的目的是为了保证第一个矩阵的列数(column)和第二个矩阵的行数(row)相同,只有这样才能做矩阵乘法运算。
您也可以将假设函数写成关于 x 的函述表达式,如下所示:
损失函数
我们知道,在线性回归模型中数据样本散落在线性方程的周围,如下图所示:
图2:线性回归模型
损失函数就像一个衡量尺,这个函数的返回值越大就表示预测结果与真实值偏差越大。其实计算单个样本的误差值非常简单,只需用预测值减去真实值即可:
但是上述方法只适用于二维平面的直线方程。在线性方程中,要更加复杂、严谨一些,因此我们采用数学中的“均方误差”公式来计算单样本误差:
公式是求“距离”因此要使用平方来消除负数,分母 2 代表样本的数量,这样就求得单样本误差值。当我们知道了单样本误差,那么总样本误差就非常好计算了:
最后,将假设函数带入上述损失函数就会得到一个关于 w 与 b 的损失函数(loss),如下所示:
在机器学习中使用损失函数的目的,是为了使用“优化方法”来求得最小的损失值,这样才能使预测值最逼近真实值。
在上述函数中 n、Y、X1 都是已知的,因此只需找到一组 w 与 b 使得上述函数取得最小值即可,这就转变成了数学上二次函数求极值的问题,而这个求极值的过程也就我们所说的“优化方法”。
梯度下降求极值
在《线性回归:损失函数和假设函数》一节,从数学的角度解释了假设函数和损失函数,我们最终的目的要得到一个最佳的“拟合”直线,因此就需要将损失函数的偏差值减到最小,我们把寻找极小值的过程称为“优化方法”,常用的优化方法有很多,比如共轭梯度法、梯度下降法、牛顿法和拟牛顿法。你可能对于上述方法感到陌生,甚至于害怕,其实大可不必,它们只不过应用了一些数学公式而已。
本节我们重点学习梯度下降法(Gradient Descent),在认识该方法之前,我们先复习一下高中时的数学知识。
导数
导数也叫导函数,或者微商,它是微积分中的重要基础概念,从物理学角度来看,导数是研究物体某一时刻的瞬时速度,比如你开车从家 8:00 出发到公司上班,9:00 到到达公司,这一个小时内的平均车速是 80km/h,而途中
8:15:30
这一时刻的速度,就被称为瞬时速度,此刻的速度可能是 100km/h,也可能是 20km/h。而从几何意义上来讲,你可以把它理解为该函数曲线在一点上的切线斜率。导数有其严格的数学定义,它巧妙的利用了极限的思想,也就是无限趋近于 0 的思想。设函数 y=f(x) 在点 x0 的某个邻域内有定义,当自变量 x 在 x0 处有增量 x0,(x0+Δx)也在该邻域内时,相应地函数取得增量 Δy=f(x0+Δx)-f(x0);如果 Δy 与 Δx 之比当 Δx→0 时极限存在,则称函数 y=f(x) 在点 x0 处可导,并称这个极限为函数 y=f(x) 在点 x0 处的导数记做 :
那么什么样的函数具有导数呢?是不是所有的函数都有导数?当然不是,而且函数也不一定在其所有点上都有导数。如果某函数在某一点导数存在,则称其在这一点可导,否则称为不可导。可导的函数一定连续;不连续的函数一定不可导。
导数的发明者是伟大的科学家牛顿与布莱尼茨,它是微积分的一个重要的支柱。在机器学习中,我们只需会用前辈科学家们留下来的知识就行了,比如熟悉常见的导函数公式,以下列举了常用的导数公式:
关于导数的的推断过程详细可参见百度百科。
偏导数
偏导数虽然和导数只有一字之差,但是却相差甚多,从它们的定义来看,偏导数是指对含有两个自变量的函数中的一个自变量求导,也就是说偏导数要求函数必须具备两个自变量。比如拿 z=f(x,y) 举例,如果只有自变量
x
变化,而自变量y
固定(即看作常量),这时它就是x
的一元函数,这函数对x
的导数,就称为二元函数z
对于x
的偏导数,记做 fx(x,y) 。有如下函数 z = x2+ 3xy + y2,分别求 z 对于 x 、y 的偏导数。如下所示:
当求 x 的偏导时就要把 y 当做常数项来对待,而当求 y 的偏导时就要把 x 当做常数项对待。关于偏导数还会涉及到高阶偏,如果感兴趣的话可以点击了解一下。
梯度下降
梯度下降是机器学习中常用的一种优化方法,主要用来解决求极小值的问题,某个函数在某点的梯度指向该函数取得最大值的方向,那么它的反方向自然就是取得最小值的方向。在解决线性回归和 Logistic(逻辑) 回归问题时,梯度下降方法有着广泛的应用。
梯度是微积分学的术语,它本质上是一个向量,表示函数在某一点处的方向导数上沿着特定的方向取得最大值,即函数在该点处沿着该方向变化最快,变化率最大。梯度下降法的计算过程就是沿梯度方向求解极小值,当然你也可以沿梯度上升的方向求解极大值。
那么如何能够更好的理解“梯度下降”呢?如果不考虑其他外在因素,其实你可以把它想象成“下山”的场景,如何从一个高山上以最快的时间走到山脚下呢?其实很简单,以你所在的当前位置为基准,寻找该位置最陡峭的地方,然后沿着此方向向下走,并且每走一段距离,都要寻找当前位置“最陡峭的地方”,反复采用上述方法,最终就能以最快的时间抵达山脚下。
在这个下山的过程中,“寻找所处位置最陡峭的地方,并沿此位置向下走”最为关键,如果把这个做法对应到函数中,就是找到“给定点的梯度”而梯度的方向就是函数值变化最快的方向。
图1:示意图
从上述描述中,你可能感觉到平淡无奇,其实每一个词语都蕴含着数学知识,比如“以当前所在位置为基准,找到最陡峭的地方”从数学角度来讲就是找到所在点的“切线”方向,也就是对这点“求导”,然后循着切线轨迹点反复使用此方法,就可以到达极小值点。
在《线性回归:损失函数和假设函数》一节,我们讲解了线性回归的损失函数,而梯度下降作为一种优化方法,其目的是要使得损失值最小。因此“梯度下降”就需要控制损失函数的
w
和b
参数来找到最小值。比如控制 w 就会得到如下方法:通过梯度下降计算极小值时,需要对损失函数的
w
求偏导求得,这个偏导也就是“梯度”,通过损失值来调节w
,不断缩小损失值直到最小,这也正是梯度下降的得名来由。“学习率”是一个由外部输入的参数,被称为“超参数”,可以形象地把它理解为下山时走的“步长”大小,想要 w 多调整一点,就把学习率调高一点。不过学习率也不是越高越好,过高的学习率可能导致调整幅度过大,导致无法求得真正的最小值。当损失函数取得极小值时,此时的参数值被称为“最优参数”。因此,在机器学习中最重要的一点就是寻找“最优参数”。
梯度下降是个大家族,它有很多成员,比如批量梯度下降(BGD)、随机梯度下降(SGD)、小批量梯度下降(MBGD),其中批量梯度下降是最常用的。
sklearn应用实现线性回归算法
Scikit-learn 简称 sklearn是基于 Python 语言实现的机器学习算法库,它包含了常用的机器学习算法,比如回归、分类、聚类、支持向量机、随机森林等等。同时,它使用 NumPy 库进行高效的科学计算,比如线性代数、矩阵等等。
Scikit-learn 涵盖了常用的机器学习算法,而且还在不断的添加完善,你可以根据不同的模型进行针对性的选择。下面介绍 sklearn 中常用的算法库:
- ·linear_model:线性模型算法族库,包含了线性回归算法,以及 Logistic 回归算法,它们都是基于线性模型。
- .naiv_bayes:朴素贝叶斯模型算法库。
- .tree:决策树模型算法库。
- .svm:支持向量机模型算法库。
- .neural_network:神经网络模型算法库。
- .neightbors:最近邻算法模型库。
实现线性回归算法
线性回归步骤
线性回归适用于有监督学习的回归问题,首先在构建线性模型前,需要准备好待输入的数据集,数据集按照需要可划分为训练集和测试集,使用训练集中的向量 X 与向量 Y 进行模型的训练,其中向量 Y 表示对应 X 的结果数值(也就是“参考答案”);而输出时需要使用测试集,输入测试 X 向量输出预测结果向量 Y。
其实线性回归主要解决了以下三个问题:
- 第一,为假设函数设定了参数 w,通过假设函数画出线性“拟合”直线。
- 第二,将预测值带入损失函数,计算出一个损失值。
- 第三,通过得到的损失值,利用梯度下降等优化方法,不断调整 w 参数,使得损失值取得最小值。我们把这个优化参数值的过程叫做“线性回归”的学习过程。
线性回归算法简单,且容易理解,但这并不影响它的广泛应用,比如经济金融领域实现股票的预测,以及著名的波士顿房价预测,这些都是线性回归的典型应有,因此我们要走出一个误区,不要感觉算法简单就不重要,机器学习虽然算法众多,但每一种算法都有其存在的理由,而掌握了线性回归就相当于拿到了算法世界的入场券。
Logistic回归算法(分类问题)
有监督学习分为“回归问题”和“分类问题”。
Logistic回归算法
也许乍一看算法名字,你会认为它是用来解决“回归问题”的算法,但其实它是针对“分类问题”的算法。
Logistic 回归算法,又叫做逻辑回归算法,或者 LR 算法(Logistic Regression)。分类问题同样也可以基于“线性模型”构建。“线性模型”最大的特点就是“直来直去”不会打弯,而我们知道,分类问题的预测结果是“离散的”,即对输出数据的类别做判断。比如将类别预设条件分为“0”类和“1”类(或者“是”或者“否”)那么图像只会在 “0”和“1”之间上下起伏,如下图所示:
图1:离散型数据
此时你就可能会有很多疑问,线性回归函数不可能“拟合”上述图像。没错,所以接下来我们要学习另一个线性函数 Logistic 函数。
注意:在机器学习中,Logistic 函数通常用来解决二元分类问题,也就是涉及两个预设类别的问题,而当类别数量超过两个时就需要使用 Softmax 函数来解决。
19 世纪统计学家皮埃尔·弗朗索瓦·韦吕勒发明了 Logistic 函数,该函数的叫法有很多,比如在神经网络算法中被称为Sigmoid 函数,也有人称它为Logistic 曲线。
其函数图像如下所示:
图2:Logistic曲线函数
该函数图像的数学表达式如下:
e 称为自然常数,也就是一个固定值的“常量”,e-z 是以 e 为底、z 为变量的指数函数,还可以写为 e-x,在编写程序代码时,通常将其写为 exp(-x)。至于这个表达式是如何推断出来的,我们没有必要深究,学会站在“巨人”的肩膀上学习也是一种难得的品质。
Logistic 函数也称为 S 型生长曲线,取值范围为 (0,1),它可以将一个实数映射到 (0,1) 的区间,非常适合做二元分类。当 z=0 时,该函数的取值为 0.5,随着 z 的增大,对应的函数值将逼近于 1;而随着 z 的减小,其函数值将逼近于 0。
对于 Logistic 函数而言,坐标轴 0 是一个有着特殊意义坐标,越靠近 0 和越远离 0 会出现两种截然不同的情况:任何大于 0.5 的数据都会被划分到 “1”类中;而小于 0.5 会被归如到 “0”类。因此你可以把 Logistic 看做解决二分类问题的分类器。如果想要 Logistic 分类器预测准确,那么 x 的取值距离 0 越远越好,这样结果值才能无限逼近于 0 或者 1。
下面通过极限的思想进一步对上述函数展开研究:我们可以考虑两种情况:当 x 轴坐标取值缩小时就会出现以下图像:
图3:Logistic函数
由此可见 Logistic 回归算法属于“线性”模型。而当 x 逐渐放大时则会出现以下情况:
图4:Logistic函数
由上图可知,当 x 增大到一定程度时,Logistic 函数图像变成了“台阶”式图像,由此可知,该函数能够很好的“拟合”二分类问题函数图像。在数学上,我们把具有如图 4 所示,这种“阶梯式”图像的函数称为“阶跃函数”。
数学解析Logistic回归算法
logistic回归原理解析--一步步理解:(博客文章,将得非常好)https://blog.csdn.net/lgb_love/article/details/80592147
这里我们也便可以总结一下线性回归模型和logistic回归的关系:
logistic回归分类模型的预测函数是在用线性回归模型的预测值的结果去逼近真实标记的对数几率!这样也便实现了上面说的将线性回归的预测值和分类任务的真实标记联系在了一起!
在《Logistic回归算法(分类问题)》一节,我们学习了 Logistic 回归算法,并且重点认识了 Logistic 函数。我们知道分类问题的预测结果是离散型数据,那么我们在程序中要如何表述这些数据呢,再者我们要如何从数学角度理解 Logistic 算法,比如它的损失函数、优化方法等。
分类数据表示形式
1) 向量形式
在机器学习中,向量形式是应用最多的形式,使用向量中的元素按顺序代表“类别”。现在有以下三个类别分别是 a/b/c,此时就可以使用 [1,2,3] 来分别代表上述三类,预测结果为哪一类,向量中的元素就对应哪个元素,比如当预测结果为 c 类的时候,则输出以下数据:
[0,0,3]
2) 数字形式
数字形式是一种最简单的分类方式,我们可以用 0 代表“负类”(即 x < 0时的取值),而用“1”代表正类(即 x>0 时的取值),那么当预测结果输出“1”就代表正类,而预测结果输出“0”代表“负类”。当然这里选择的数字只是形式,你可以选择任意其他数字,不过按照约定俗成,我们一般采用 “1”代表正类,而 “-1”或者“0”代表“负类”。 如果用代码的表示数字形式的中心思想,如下所示:
3) 概率形式
在有些实际场景中,我们无法准确的判断某个“样本”属于哪个类别,此时我们就可以使用“概率”的形式来判断“样本”属于哪个类别的几率大,比如对某个“样本”有如下预测结果:
[0.8,0.1,0.1]
从上述输出结果不难看出,该样本属于 a 类的概率最大,因此我们可以认定该样本从属于 a 类。
Logistic函数数学解析:
1) 假设函数
经过上一节的学习得知 Logistic 函数能够很好的拟合“离散数据”,因此可以把它看做“假设函数”,但是还需要稍稍的改变一下形式,如下所示:
上述公式和 Logistic 函数基本一致,只不过我们它换成了关于x的表达式,并将幂指数x换成了 “线性函数”表达式。H(x) 的函数图像呈现 S 形分布,从而能够预测出离散的输出结果。
2) 损失函数
LogIstic 回归算法的损失函数有点复杂,也许你会感动莫名其妙,损失函数的表达式如下:
想要理解损失函数,我们需要继续分析假设函数。我们知道假设函数的值域是从 (0,1) 之间的数值,而这个数据区间恰好与概率值区间不谋而合。如果我们把预测结果看做概率,则可以得到另外一种写法的损失函数。
上述函数是根据概率设计出来的,它由 H(xi)yi 和 (1-H(xi))1-yi 两部分组成,由于 y 值的取值只会是 0 或者 1,所以每次只有一个部分输出值,因此可以达到分类的目的。
我们知道 y 输出值概率值只能为 0 或者 1,因此上述函数只会有一部分输出数值。即当 y=1 时候,1-y 就等于 0,因此上述表达式的第二部分,也就是 (1-H(xi))1-yi的值为 1,相乘后并不会对函数值产生影响。当 y = 0 时,同理。
综上所述:当 y=1 时,如果预测正确,预测值则无限接近 1,也即 H(xi)yi的值为 1,损失值则为 -1;如果预测错误,H(xi)yi的值为 0,损失值也为 0。预测错误的损失值确实比预测正确的损失值大(0 > -1),满足要求。
虽然上述函数能够表达预测值和实际值之间的偏差,但它有一个缺点就是不能使用梯度下降等优化方法。因此,在机器学习中要通过取对数的方法来解决此问题,这样就得到了最开始的损失函数。如下所示:
3) 优化方法
如果将 Logistic 函数的输出记做 z 可得如下公式:
z = w0x0+w1x1<+....+wnxn
采用向量的形式可以写为:
z=wTx
它表示将这两个数值向量对应元素相乘然后全部加起来即得到 z 值。其中的 x 是分类器的输入数据,向量 w (最佳参数)会使得分类器尽可能的精确。为了寻找该最佳参数就需要用到优化方法,下面我们简单介绍梯度上升优化方法。
梯度上升优化方法
度上升与梯度下降同属于优化方法,它们两者有着异曲同工之妙,梯度下降求的是“最小值”,而梯度上升求的是“最大值”。梯度上升基于的思想是:要找到某函数的最大值,最好的发放是沿着该函数的梯度方向寻找,如果把梯度记为▽,那么关于 f(x,y) 有以下表达式:
上述公式是其实并不难理解,该函数分别对 x 与 y 求的偏导数,其中关于 x 的偏导数表示沿着 x 的方向移动,而关于 y 的偏导数一个表示沿 y 的方向移。其中,函数f(x,y) 必须要在待计算的点上可导。在梯度上升的过程中,梯度总是指向函数值增长最快的方向,我们可以把每移动一次的“步长”记为α 。用向量来表示的话,其公式如下:
w1= w + α▽wf(w)
在梯度上升的过程中,上述公式将一直被迭代执行,直至达到某个停止条件为止,比如达到某个指定的值或者某个被允许的误差范围之内。
sklearn应用实现Logistic回归算法
在 Scikit-Learn 机器学习库中,有关线性模型的算法族都在
linear_model
模块下,不同的算法又会分化为很多类,但它们都是经过几种基本算法调整和组合而成,因此基本上都是大同小异,换汤不换药,下面介绍经常用到回归类算法,其中就包含了 Logistic 回归算法。在这之前我们需要先熟悉几个概念,比如“正则化”。什么是范数?
范数又称为“正则项”,它是机器学习中会经常遇到的术语,它表示了一种运算方式,“范数”的种类有很多,不过常见的范数主要分为两种:L1 和 L2。下面我们来分别认识一下它们。
1) L1范数
L1 范数非常容易理解,它表示向量中每个元素绝对值的和,根据定义,L1 范数的计算分两步,首先逐个求得元素的绝对值,然后相加求和即可。下面给出了 L1 范数正则化定义的数学表达式,如下所示:
注意:此时两个绝度值符号,是符合范数规定的,两个绝对值符号表示范数。
2) L2范数
L2 范数出现的频率更高,表示向量中每个元素的平方和的平方根。根据定义,L2 范数的计算分三步,首先逐个求得元素的平方,然后相加求和,最后求和的平方根。L2范数正则化定义的数学表达式如下:
回归类算法
除了“线性回归算法” 也就是“最小二乘法”之外,还有以下常用算法:
1) Ridge类
Ridge 回归算法,又称“岭回归算法”主要用于预测回归问题,是在线性回归的基础上添加了 L2 正则项,使得权重 w 的分布更加均匀,其损失函数如下:
损失函数的左侧与线性回归算法的损失函数一致。只是在最后添加右侧的 L2 正则项,其中 a 只是一个常数,需要根据经验设置。
注意,线性回归函数的 1/n 在优化过程的运算中不会影响结果,它只是一个常量而已,而常量的导数是 0。
2) Lasso类
Lasso 回归算法:我们知道,常用的正则项有 L1 和 L2,而使用了 L1 正则项的线性回归是 Lasso 回归算法,它可以预测回归问题,其损失函数的表达式如下(求最小损失值):
上述表达式的左侧与 Ridge 回归算法的损失函数基本一致,只是将右侧的 L2 范数替换成了 L1 范数,而且左侧式子相比线性回归表达式而言,多了一个1/2,但实际的优化过程中,它并不会对权重 w 产生影响。
实现Logistic回归
scikit-learn 中的 train_test_split 函数可以打乱数据集,并对其进行拆分。该函数默认将 75% 的行数据及对应标签作为训练集,另外 25% 数据作为测试集。
注意:75% 和 25% 这两个数值可以根据实际的情况做相应的调整。
最后,我们对 Logistic 算法做一下简单总结:首先 Logistic 算法适用于分类问题,该算法在处理二分类问题上表现优越,但在多分类(二个以上)问题上容易出现欠拟合。Logistic 算法除了适用于回归分类问题,还可以作为神经网络算法的激活函数(即 Sigmoid 函数)。
机器学习中有许多的算法,我们不能评价一个算法的优劣性,因为算法只有合适与不合适,每个算法都有其适用的场景。因此,我们不能仅依据模型评分来评价模型的好与坏。
KNN最邻近分类算法
K 最邻近分类算法,简称 KNN(K-Nearest-Neighbor),它是有监督学习分类算法的一种。所谓 K 近邻,就是 K 个最近的邻居。比如对一个样本数据进行分类,我们可以用与它最邻近的 K 个样本来表示它,这与俗语“近朱者赤,近墨者黑”是一个道理。
少数服从多数”,另一个是“距离”,它们是实现 KNN 算法的核心知识。
KNN算法原理
为了判断未知样本的类别,以所有已知类别的样本作为参照来计算未知样本与所有已知样本的距离,然后从中选取与未知样本距离最近的 K 个已知样本,并根据少数服从多数的投票法则(majority-voting),将未知样本与 K 个最邻近样本中所属类别占比较多的归为一类。这就是 KNN 算法基本原理。
在 scikit-learn 中 KNN 算法的 K 值是通过 n_neighbors 参数来调节的,默认值是 5。
KNN 算法原理:如果一个样本在特征空间中存在 K 个与其相邻的的样本,其中某一类别的样本数目较多,则待预测样本就属于这一类,并具有这个类别相关特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
KNN 算法简单易于理解,无须估计参数,与训练模型,适合于解决多分类问题。但它的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有很能导致当输入一个新样本时,该样本的 K 个邻居中大容量类的样本占多数,而此时只依照数量的多少去预测未知样本的类型,就会可能增加预测错误概率。此时,我们就可以采用对样本取“权值”的方法来改进。
KNN算法流程
下面对 KNN 算法的流程做简单介绍。KNN 分类算法主要包括以下 4 个步骤:
- 准备数据,对数据进行预处理 。
- 计算测试样本点(也就是待分类点)到其他每个样本点的距离(选定度量距离的方法)。
- 对每个距离进行排序,然后选择出距离最小的 K 个点。
- 对 K 个点所属的类别进行比较,按照少数服从多数的原则(多数表决思想),将测试样本点归入到 K 个点中占比最高的一类中。
注意:在机器学习中有多种不同的距离公式,下面以计算二维空间 A(x,y),B(x1,y1) 两点间的距离为例进行说明,下图展示了如何计算欧式距离和曼哈顿街区距离。(PS:要理会名字,名字都是纸老虎)如下图所示:
在前面提到过欧氏距离,它表示两点之间最短的距离,其计算公式如下:
曼哈顿街区距离计算公式如下:
那么你会考虑它们两者的区别是什么呢?其实很容易理解,我们知道两点之前线段最短,A 和 B 之间的最短距离就是“欧式距离”,但是在实际情况中,由于受到实际环境因素的影响,我们有时无法按照既定的最短距离行进,比如你在一个楼宇众多的小区内,你想从 A 栋达到 B 栋,但是中间隔着其他楼房,因此你必须按照街道路线行进(图中红线),这种距离就被称作“曼哈顿街区距离”。
注意:除上述距离外,还有汉明距离、余弦距离、切比雪夫距离、马氏距离等。在 KNN 算法中较为常用的距离公式是“欧氏距离”。
KNN预测分类
通过上述介绍我们理解了 KNN 算法的基本工作流程,它主要利用“多数表决思想”与“距离”来达到分类的目的,那么我们应该如何确定 K 值呢?因为不同的 K 值会影响分类结果,如下所示:
图1:KNN算法分类核心
如图 1 所示,有三角形和菱形两个类别,而“灰色圆”是一个未知类别,现在通过 KNN 算法判断“灰色圆”属于哪一类。如果当 K 的取值为 3 时,按照前面讲述的知识,距离最近且少数服从多数,那“灰色圆”属于菱形类,而当 K= 6 时,按照上述规则继续判断,则“灰色圆”属于三角形类。
KNN 分类算法适用于多分类问题、OCR光学模式识别、文本分类等领域。
sklearn实现KNN分类算法
通俗地理解贝叶斯公式(定理)
朴素贝叶斯(Naive Bayesian algorithm)是有监督学习的一种分类算法,它基于“贝叶斯定理”实现,该原理的提出人是英国著名数学家托马斯·贝叶斯。贝叶斯定理是基于概率论和统计学的相关知识实现的。
贝叶斯定理
贝叶斯定理的发明者托马斯·贝叶斯提出了一个很有意思的假设:“如果一个袋子中共有 10 个球,分别是黑球和白球,但是我们不知道它们之间的比例是怎么样的,现在,仅通过摸出的球的颜色,是否能判断出袋子里面黑白球的比例?”
上述问题可能与我们高中时期所接受的的概率有所冲突,因为你所接触的概率问题可能是这样的:“一个袋子里面有 10 个球,其中 4 个黑球,6 个白球,如果你随机抓取一个球,那么是黑球的概率是多少?”毫无疑问,答案是 0.4。这个问题非常简单,因为我们事先知道了袋子里面黑球和白球的比例,所以很容易算出摸一个球的概率,但是在某些复杂情况下,我们无法得知“比例”,此时就引出了贝叶斯提出的问题。
在统计学中有两个较大的分支:一个是“频率”,另一个便是“贝叶斯”,它们都有各自庞大的知识体系,而“贝叶斯”主要利用了“相关性”一词。下面以通俗易懂的方式描述一下“贝叶斯定理”:通常,事件 A 在事件 B 发生的条件下与事件 B 在事件 A 发生的条件下,它们两者的概率并不相同,但是它们两者之间存在一定的相关性,并具有以下公式(称之为“贝叶斯公式”):
看到上述公式,你可能一头雾水,不过不必慌张,下面我们来了解一下“贝叶斯”公式。
例如:一座别墅在过去的 20 年里一共发生过 2 次被盗,别墅的主人有一条狗,狗平均每周晚上叫 3 次,在盗贼入侵时狗叫的概率被估计为 0.9,问题是:在狗叫的时候发生入侵的概率是多少?
我们假设 A 事件为狗在晚上叫,B 为盗贼入侵,则以天为单位统计,P(A) = 3/7,P(B) = 2/(20*365) = 2/7300,P(A|B) = 0.9,按照公式很容易得出结果:P(B|A) = 0.9*(2/7300) / (3/7) = 0.00058
符号意义
首先我们要了解上述公式中符号的意义:
- P(A) 这是概率中最基本的符号,表示 A 出现的概率。比如在投掷骰子时,P(2) 指的是骰子出现数字“2”的概率,这个概率是 六分之一。
- P(B|A) 是条件概率的符号,表示事件 A 发生的条件下,事件 B 发生的概率,条件概率是“贝叶斯公式”的关键所在,它也被称为“似然度”。
- P(A|B) 是条件概率的符号,表示事件 B 发生的条件下,事件 A 发生的概率,这个计算结果也被称为“后验概率”。
有上述描述可知,贝叶斯公式可以预测事件发生的概率,两个本来相互独立的事件,发生了某种“相关性”,此时就可以通过“贝叶斯公式”实现预测。
条件概率
条件概率是“贝叶斯公式”的关键所在,那么如何理解条件概率呢?其实我们可以从“相关性”这一词语出发。举一个简单的例子,比如小明和小红是同班同学,他们各自准时回家的概率是 P(小明回家) = 1/2 和 P(小红回家) =1/2,但是假如小明和小红是好朋友,每天都会一起回家,那么 P(小红回家|小明回家) = 1 (理想状态下)。
上述示例就是条件概率的应用,小红和小明之间产生了某种关联性,本来俩个相互独立的事件,变得不再独立。但是还有一种情况,比如小亮每天准时到家 P(小亮回家) =1/2,但是小亮喜欢独来独往,如果问 P(小亮回家|小红回家) 的概率是多少呢?你会发现这两者之间不存在“相关性”,小红是否到家,不会影响小亮的概率结果,因此小亮准时到家的概率仍然是 1/2。
贝叶斯公式的核心是“条件概率”,譬如 P(B|A),就表示当 A 发生时,B 发生的概率,如果P(B|A)的值越大,说明一旦发生了 A,B 就越可能发生。两者可能存在较高的相关性。
先验概率
在贝叶斯看来,世界并非静止不动的,而是动态和相对的,他希望利用已知经验来进行判断,那么如何用经验进行判断呢?这里就必须要提到“先验”和“后验”这两个词语。我们先讲解“先验”,其实“先验”就相当于“未卜先知”,在事情即将发生之前,做一个概率预判。比如从远处驶来了一辆车,是轿车的概率是 45%,是货车的概率是 35%,是大客车的概率是 20%,在你没有看清之前基本靠猜,此时,我们把这个概率就叫做“先验概率”。
后验概率
在理解了“先验概率”的基础上,我们来研究一下什么是“后验概率?”
我们知道每一个事物都有自己的特征,比如前面所说的轿车、货车、客车,它们都有着各自不同的特征,距离过远的时候,我们无法用肉眼分辨,而当距离达到一定范围内就可以根据各自的特征再次做出概率预判,这就是后验概率。比如轿车的速度相比于另外两者更快可以记做 P(轿车|速度快) = 55%,而客车体型可能更大,可以记做 P(客车|体型大) = 35%。
如果用条件概率来表述 P(体型大|客车)=35%,这种通过“车辆类别”推算出“类别特征”发生的的概率的方法叫作“似然度”。这里的似然就是“可能性”的意思。
朴素+贝叶斯
了解完上述概念,你可能对贝叶斯定理有了一个基本的认识,实际上贝叶斯定理就是求解后验概率的过程,而核心方法是通过似然度预测后验概率,通过不断提高似然度,自然也就达到了提高后验概率的目的。
我们知道“朴素贝叶斯算法”由两个词语组成。朴素(native)是用来修饰“贝叶斯”这个名词的。按照中文的理解“朴素”意味着简单不奢华。朴素的英文是“native”,意味着“单纯天真”。
朴素贝叶斯是一种简单的贝叶斯算法,因为贝叶斯定理涉及到了概率学、统计学,其应用相对复杂,因此我们只能以简单的方式使用它,比如天真的认为,所有事物之间的特征都是相互独立的,彼此互不影响。
朴素贝叶斯分类算法原理
我们知道解决分类问题时,需要根据他们各自的特征来进行判断,比如区分“一对双胞胎不同之处”,虽然他们看起来相似,但是我们仍然可以根据细微的特征,来区分他们,并准确地叫出他们的名字。就像一句非常有哲理的话,“世界上没有完全相同的两片树叶”,因此被分类的事物会存在许多特征。
比如现在有 A1和 A2两个类,其中 A1 具有 b、c 两个特征,A2 具有 b、d 两个 特征,如果是你会怎么区分这两个类呢?很简单看看是存在 c ,存在的就是 A1,反之则是 A2。但是现实的情况要复杂的多,比如 100 个 A1样本中有 80% 的样本具有特征 c,而且剩余的 20% 具有了特征 d,那么要怎么对它们分类呢?其实只要多加判断还是可以分清,不过要是纯手工分类,那就恐怕得不偿失了。
多特征分类问题
统计学是通过搜索、整理、分析、描述数据等手段,以达到推断、预测对象的本质,统计学用到了大量的数学及其它学科的专业知识,其应用范围几乎覆盖了社会科学和自然科学的各个领域。
下面我们使统计学的相关知识解决上述分类问题,分类问题的样本数据大致如下所示:
解决思路:
这里我们先简单的采用 1 和 0 代表特征值的有无,比如当 X1的特征值等于 1 时,则该样本属于 A1的类别概率;特征值 X2值为 1 时,该样本属于类别 A1的类别的概率。依次类推,然后最终算出该样本对于各个类别的概率值,哪个概率值最大就可能是哪个类。上述思路就是贝叶斯定理的典型应用,如果使用条件概率表达,如下所示:
P(类别A1|特征X1,特征X2,特征X3,…)
上述式子表达的意思是:在特征 X1、X2、X3等共同发生的条件下,类别 A1发生的概率,也就是后验概率,依据贝叶斯公式,我们可以使用似然度求解后验概率,某个特征的似然度如下:
P(特征X1|类别A1,特征X2,特征X3,…)
但是要收集对个特征值共同发生的情况,这并不容易,因此我们就需要使用“朴素”贝叶斯算法。
朴素贝叶斯算法
上一节我们已经了解了贝叶斯公式,下面使用贝叶斯公式将多特征分类问题表达出来,如下所示:
数据集有时并不是很完全的,总会因为某些原因存在一些缺失和收集不全的现象,所以特征 x 越多这个问题就会越突出,统计这些特征出现的概率就越困难。为了避免这一问题,朴素贝叶斯算法做了一个假设,即特征之间相互独立,互不影响,由此以来,就可以简化为以下式子来求解某个特征的似然度:
“朴素贝叶斯算法”利用后验概率进行预测,其核心方法是通过似然度预测后验概率。在使用朴素贝叶斯算法解决分类问题,其实就是不断提高似然度的过程,你可以理解为后验概率正比于似然度,如果提高了似然度,那么也会达到提高后验概率的目的,记做如下式子:
上述式子中∝表示正比于,而∏则是连乘符号(即概率相乘)表示了不同特征同时发生的概率。
朴素贝叶斯优化方法
你也许会发现,在学习过朴素贝叶斯的过程中,我们并未提到“假设函数”和“损失函数”,其实这并不难理解。朴素贝叶斯算法更像是一种统计方法,通过比较不同特征与类之间的似然度关系,最后把似然度最大的类作为预测结果。
每个类与特征的似然度是不同的,也就是 P(xi|y) 不同,因此某一类别中某个特征的概率越大,我们就更容易对该类别进行分类。根据求解后验概率的公式,可以得出以下优化方法:
此时将后验概率记做类别 y,我们知道 P(y) 是一个固定的概率值,因此要想让 y 取得最大值,只能通过 P(xi|y) 实现,不妨把被统计的数据看成是一张大表格,朴素贝叶斯算法就是从中找到P(xi|y) 值最大的那一项,该项对应的 y 是什么,则最终输出的预测结果就是什么。
sklearn应用实现朴素贝叶斯算法
简单应用案例
假设一个学校有 45% 的男生和 55% 的女生,学校规定不能穿奇装异服,男生的裤子只能穿长筒裤,而女生可以穿裙子或者长筒裤,已知该学校穿长筒裤的女生和穿裙子的女生数量相等,所有男生都必须穿长筒裤,请问如果你从远处看到一个穿裤子的学生,那么这个学生是女生的概率是多少?
看完上述问题,你是不是已经很快的计算出了结果呢?还是丈二和尚,摸不到头脑呢?下面我们一起来分析一下,我们根据贝叶斯公式,列出要用到的事件概率:
学校女生的概率:P(女生)= 0.55 女生中穿裤子的概率:P(裤子|女)= 0.5 学校中穿裤子的概率:P(裤子)= 0.45 + 0.275= 0.725
知道了上述概率,下面使用贝叶斯公式求解 P(女生|裤子) 的概率:
P(女|裤子) = P(裤子|女生) * P(女生) / P(裤子) = 0.5 * 0.55 / 0.725 = 0.379
利用上述公式就计算除了后验概率 P(女生|裤子) 的概率,这里的 P(女生) 和 P(裤子)叫做先验概率,而 P(裤子|女生) 就是我们经常提起的条件概率“似然度”。
sklearn实现朴素贝叶斯
在 sklearn 库中,基于贝叶斯定理的算法集中在 sklearn.naive_bayes 包中,根据对“似然度 P(xi
|y)”计算方法的不同,我们将朴素贝叶斯大致分为三种:多项式朴素贝叶斯(MultinomialNB)、伯努利分布朴素贝叶斯(BernoulliNB)、高斯分布朴素贝叶斯(GaussianNB)。另外一点要牢记,朴素贝叶斯算法的实现是基于假设而来,在朴素贝叶斯看来,特征之间是相互独立的,互不影响的。
高斯朴素贝叶斯适用于特征呈正态分布的,多项式贝叶斯适用于特征是多项式分布的,伯努利贝叶斯适用于二项分布。
1) 算法使用流程
使用朴素贝叶斯算法,具体分为三步:
- 统计样本数,即统计先验概率 P(y) 和 似然度 P(x|y)。
- 根据待测样本所包含的特征,对不同类分别进行后验概率计算。
- 比较 y1,y2,...yn 的后验概率,哪个的概率值最大就将其作为预测输出。
2) 朴素贝叶斯算法应用
决策树分类算法(if-else原理)
策树算法在“决策”领域有着广泛的应用,比如个人决策、公司管理决策等。其实更准确的来讲,决策树算法算是一类算法,这类算法逻辑模型以“树形结构”呈现,因此它比较容易理解,并不是很复杂,我们可以清楚的掌握分类过程中的每一个细节。
if-else原理
想要认识“决策树算法”我们不妨从最简单的“if - else原理”出发来一探究竟。作为程序员,我相信你对 if -else 原理并不感到陌生,它是条件判断的常用语句。下面简单描述一下 if -else 的用法:if 后跟判断条件,如果判断为真,也即满足条件,就执行 if 下的代码段,否则执行 else 下的代码段,因此 if-else 可以简单的理解为“如果满足条件就....,否则.....”
if-else 有两个特性:一是能够利用 if -else 进行条件判断,但需要首先给出判断条件;二是能无限嵌套,也就是在一个 if-else 的条件执行体中,能够再嵌套另外一个 if-else,从而实现无限循环嵌套。
下面我看一个简单的应用示例,相信你能从中体会到“决策树”的魅力。古人有“伯乐识别千里马”那么“伯乐”是如何“相马”的呢?下表列出了 A、B、C 、D 四匹马,它们具有以下特征:
如果你是“伯乐”会如何从中挑选出那匹“千里马”呢?毫无疑问,我们要根据马匹的相应特征去判断,而这些特征对应的值叫做“特征维度值”,下面是一位“伯乐”利用 if -else 原理,最终成功的审识别出“千里马”的全过程,如下所示:
图1:决策树流程图
上图 1 所示是一颗典型的树形结构“二叉树”,而决策树一词中的“树”指的就是这棵树。上图展示了伯乐“识别”千里马的全过程,根据特征值的有无(if-else原理)最终找出“千里马。你可能会问为什么并没囊括所有的特征值?
这是因为某些特征值对于结果的判断而言,并不是最为关键的特征值,比如马的“体型”,“骨瘦如柴”并不能决定某一匹马不是“千里马”。而“马腿”的长短没有作为判断条件,这是因为使用前三个特征值就已经完成了结果的分类,如果此时再使用“马腿”长短作为判断条件,则有点多此一举。
如果将上述判断的流程用 if-else 的伪代码写出来,如下所示:
决策树算法关键
决策树算法涉及了几个重要的知识点:“决策树的分类方法”,“分支节点划分问题”以及“纯度的概念”。在学习过程中还会涉及到“信息熵”、“信息增益”、“基尼指数”的概念。
特征维度&判别条件
我们知道分类问题的数据集由许多样本构成,而每个样本数据又会有多个特征维度,比如前面例子中马的“声音”,“眼睛”都属于特征维度,在决策算法中这些特征维度属于一个集合,称为“特征维度集”。数据样本的特征维度与最终样本的分类都可能存在着某种关联,因此决策树的判别条件将从特征维度集中产生。
在机器学习中,决策树算法是一种有监督的分类算法,我们知道机器学习其实主要完成两件事,一个是模型的训练与测试,另外一个是预测数据的(分类问题,预测类别),因此对于决策树算法而言,我们要考虑如何学会自动选择最合适的判别条件,如图 1 所示,只利用前三个特征就完成了分类的预测。
决策树算法:选择决策条件
首先来看一个“我想你来猜”的游戏,游戏规则很简单:一个人从脑海中构建一个事物,另外几个人最多可以向他提问 20 个问题,游戏规定,问题的答案只能用是或者否来回答。问问题的人通过回答者的“答案”来推分析、逐步缩小待猜测事物的范围,从而来判断他想的是什么。其实这个游戏与决策树工作过程相似。
那么你有没有考虑过要怎样选择“问什么问题”呢,在这里“问什么问题”就相当于决策树算法中的“判别条件”。选择什么判别条件,可以让我们又快又准确的实现分类。
纯度的概念
决策树算法引入了“纯度”的概念,“纯”指的是单一,而“度”则指的是“度量”。“纯度”是对单一类样本在子集内所占重的的度量。
在每一次判别结束后,如果集合中归属于同一类别的样本越多,那么就说明这个集合的纯度就越高。比如,二元分类问题的数据集都会被分成两个子集,我们通过自己的纯度就可以判断分类效果的好与坏,子集的纯度越高,就说明分类效果越好。
上一节我们提到过,决策树算法是一类算法,并非某一种算法,其中最著名的决策树算法有三种,分别是 ID3、C4.5 和 CART。虽然他们都属于决策树算法,不过它们之间也存在着一些细微的差别,主要是体现在衡量“纯度”的方法上,它们分别采用了信息增益、增益率和基尼指数。
纯度度量规则
那么我们应该采取什么样的方法去“衡量”某个集合中某一类别样本的纯度呢?当我们学习完机器学习之后,我们总不能还使用人工的方式去验证吧,那可真是徒劳无功了。
要想明确纯度的衡量方法,首先我们要知道一些度量“纯度”的规则。下面我们将类别分为“正类与负类”,如下所示:
- 某个分支节点下所有样本都属于同一个类别,纯度达到最高值。
- 某个分支节点下样本所属的类别一半是正类一半是负类,此时,纯度取得最低值。
- 纯度代表一个类在子集中的占比多少,它并不在乎该类究竟是正类还是负类。比如,某个分支下不管是正类占比 60% 还是负类占比 60%,其纯度的度量值都是一样的。
决策树算法中使用了大量的二叉树进行判别,在一次判别后,最理想的情况是分支节点下包含的类完全相同,也就是说不同的类别完全分开,但有时我们无法只用一个判别条件就让不同的类之间完全分开,因此选择合适判别条件区划分类是我们要重点掌握的。
纯度度量方法
1) 纯度函数
现在我们做一个函数图像,横轴表示某个类的占比,纵轴表示纯度值,然后我们根据上面提出的“纯度度量规则”来绘制函数图像:
首先某个类达到最大值,或者最小值时,纯度达到最高值,然后,当某一个类的占比达到 0.5 时,纯度将取得最低值。由这两个条件,我们可以做出 a/b/c 三个点,最后用一条平滑的曲线将这三个点连接起来。如下所示:
图1:纯度函数图像
如上图,我们做出了一条类似于抛物线的图像,你可以把它看做成“椭圆”的下半部分。当在 a 点时某一类的占比纯度最小,但是对于二元分类来说,一个类小,另一个类就会高,因此 a 点时的纯度也最高(与 b 恰好相反),当某类的纯度占比在 c 点时,对于二元分类来说,两个类占比相同,此时的纯度值最低,此时通过 c 点无法判断一个子集的所属类别。
2) 纯度度量函数
前面在学习线性回归算法时,我们学习了损失函数,它的目的是用来计算损失值,从而调整参数值,使其预测值不断逼近于误差最小,而纯度度量函数的要求正好与纯度函数的要求相反,因为纯度值越低意味着损失值越高,反之则越低。所以纯度度量函数所作出来的图像与纯度函数正好相反。如下图所示:
图2:纯度度量函数
上图就是纯度度量函数,它与纯度函数恰好相反。纯度度量函数图像适应于所有决策树算法,比如 ID3、C4.5、CART 等经典算法。
信息熵是什么
我们将从数学角度解析如何选择合适的“特征做为判别条件”,这里需要重点掌握“信息熵”的相关知识。
信息熵这一概念由克劳德·香农于1948 年提出。香农是美国著名的数学家、信息论创始人,他提出的“信息熵”的概念,为信息论和数字通信奠定了基础。
在理解“信息熵”这个词语前,我们应该理解什么是“信息”。信息是一个很抽象的概念,比如别人说的一段话就包含某些“信息”,或者我们所看到的一个新闻也包含“信息”,人们常常说信息很多,或者信息较少,但却很难说清楚信息到底有多少。比如一篇 10 万字的论文到底包含多少信息量?信息熵就是用来解决对信息的量化问题的。
熵”这一词语从热力学中借用过来的,热力学中的“热熵”是表示分子状态混乱程度的物理量,香农使用“信息熵”这一概念来量化“信息量”。信息的计算是非常复杂的,具有多重前提条件的信息,更是无法计算,但由于信息熵和热力熵紧密相关,所以信息熵可以在衰减的过程中被测定出来。
理解信息熵
想要非常清楚地讲明白“信息熵”到底是什么?需要结合物理上的知识,不过这样就有点“舍本逐末”,所以我们只要理解香农给出的相关结论即可:
信息熵是用于衡量不确定性的指标,也就是离散随机事件出现的概率,简单地说“情况越混乱,信息熵就越大,反之则越小”
。比如“台湾是中国的固有领土”和“台湾不是中国的固有领土”,你感觉哪一句话传递的信息量更大?当然是后者,因为前者属于既定事实,而后者若要发生的话,可能是发生了巨大的变革而导致的。如果一件事 100% 发生,那么这件事就是确定的事情,其信息熵无限接近于最小,但如果这件事具有随机性,比如抛硬币,其结果可能正面也可能反面,那么这件事就很不确定,此时的信息熵就无限接近于最大值。
再比如,封闭的房间一直不打扫,那么房间不可能越来越干净,只能不断的落灰和结下蜘蛛网,如果想要让它变得整洁、有序就需要外力介入去打扫房间。这个过程中趋向于混乱的房间其信息熵不断增大,而打扫后的房间,则趋向于信息熵最小。伟大数学家香农给出了信息熵的计算公式,如下所示:
其中 p 代表概率的意思,这里 “X” 表示进行信息熵计算的集合。在决策树分类算法中,我们可以按各个类别的占比(占比越高,该类别纯度越高)来理解,其中 N 表示类别数目,而 Pk表示类别 K 在子集中的占比。理解了上述含义,再理解信息熵的计算过程就非常简单了,分为三次四则运算,即相乘、求和最后取反。
信息熵公式计算
下面我们举一个简单的例子,对上述信息熵计算公式进行简单的应用,在二元分类问题中,如果当前样本全部属于 k 类别,那么该类别在子集节点中的占比达到 100%(而另一个类别占比为 0),即 pk= 1,此时信息熵的计算公式如下:
关于对数函数的运算法则这里不再赘述,以 2 为底 1 的对数为 0,因此最终两个类别的信息熵求和结果为 0。信息熵为 0 说明子集内的类别一致“整齐有序”。由此也可以得知 pk=0.5 时候信息熵的取得最大值。下面根据上述信息,我们绘制信息熵的函数图像,如下所示:
ID3算法—信息增益
决策树算法和剪枝原理
我们知道,决策树算法是一种树形分类结构,要通过这棵树实现样本分类,就要根据 if -else 原理设置判别条件。因此您可以这样理解,决策树是由许多 if -else 分枝组合而成的树形模型。
决策树算法原理
决策树特征属性是 if -else 判别条件的关键所在,我们可以把这些特征属性看成一个集合,我们要选择的判别条件都来自于这个集合,通过分析与计算选择与待分类样本最合适的“判别条件”。通过前面文章的学习,我们可以知道被选择的“判别条件”使得样本集合的某个子树节点“纯度”最高。
上述过程就好比从众多的样本中提取“类别纯度”最高的样本集合,因此我们可以起一个形象化的名字“提纯”,过程示意图如下所示:
图1:决策树流程图
通过上述流程图可以得知,决策树算法通过判别条件从根节点开始分裂为子节点,子节点可以继续分裂,每一次分裂都相当于一次对分类结果的“提纯”,周而复始,从而达到分类的目的,在这个过程中,节点为“否”的不在分裂,判断为“是”的节点则继续分裂。那么你有没有考虑过决策树会在什么情况下“停止”分裂呢?下面列举了两种情况:
1) 子节点属于同一类别
决策树算法的目的是为了完成有效的样本分类。当某个数据集集合分类完成,也就分类后的子节点集合都属于同一个类别,不可再分,此时代表着分类任务完成,分裂也就会终止。
2) 特征属性用完
我们知道,决策树依赖特征属性作为判别条件,如果特征属性已经全部用上,自然也就无法继续进行节点分裂,此处可能就会出现两种情况:一种是分类任务完成,也就是子节点属于同一类别,还有另外一种情况就是分类还没有完成,比如,在判断为“是”的节点集合中,有 8 个正类 3 个负类,此时我们将采用占比最大的类作为当前节点的归属类。
3) 设置停止条件
除上述情况外,我们也可以自己决定什么时候停止。比如在实际应用中我们可以在外部设置一些阈值,把决策树的深度,或者叶子节点的个数当做停止条件。
决策树剪枝策略
决策树算法是机器学习中的经典算法。如果要解决分类问题,决策树算法再合适不过了。不过决策树算法并非至善至美,决策树分类算法最容易出现的问题就是“过拟合”。什么是“过拟合”我们在教程的开篇已经提及过,它指的机器学习模型对于训练集数据能够实现较好的预测,而对于测试集性能较差。
过拟合”使决策树模型学习到了并不具备普遍意义的分类决策条件,从而导致模型的分类效率、泛化能力降低。
决策树出现过拟合的原因其实很简单,因为它注重细节。决策树会根据数据集各个维度的重要性来选择 if -else 分支,如果决策树将所有的特征属性都用完的情况下,那么过拟合现象就很容易出现。
我们知道,每个数据集都会有各种各样的属性维度,总会出现一些属性维度样本分类实际上并不存在关联关系的情况。因此,在理想情况下决策树算法应尽可能少地使用这些不相关属性,但理想终归是理想,在现实情况下很难实现。那么我们要如何解决这种过拟合问题呢?这时就要用到“剪枝策略”。
“剪枝策略”这个名字非常的形象化,它是解决决策树算法过拟合问题的核心方法,也是决策树算法的重要组成部分。剪枝策略有很多种,我们根据剪枝操作触发时间的不同,可以将它们分成两种,一种称为预剪枝,另一种称为后剪枝。
1) 预剪枝
所谓预剪枝,就是将即将发芽的分支“扼杀在萌芽状态”即在分支划分前就进行剪枝判断,如果判断结果是需要剪枝,则不进行该分支划分。
2) 后剪枝
所谓后剪枝,则是在分支划分之后,通常是决策树的各个判断分支已经形成后,才开始进行剪枝判断。
上述两个剪枝策略,我们重要理解“预”和“后”。“预”就是打算、想要的意思,也就是在分支之前就被剪掉,不让分支生成,而“后”则是以后、后面,也就是分支形成以后进行剪枝操作。那么我要如何判断什么时候需要进行剪枝操作呢?其实很容易理解,如果剪枝后决策树模型在测试集验证上得到有效的提升,就判断其需要剪枝,否则不需要。
剪枝的操作对象是“分支的判别条件”,也就是减少不必要特征属性的介入,从而提高决策树分类效率,和测试集的预测能力。下面通过一个简单的例子进行说明:
某个样本数据集有两个类别(正类与负类),2 个特征属性,现在我们对 20 个样本进行分类。首先,在应用所有“特征属性”的情况下对样本进行分类。如下所示:
图2:决策树过拟合问题
上图 2 使用了两个特征属性对样本集合进行分类,最后正确分类的概率是 12/20。如果只通过特征 1 进行分类,也就是剪掉冗余特征 2,最后的结果又是怎样呢?如下图所示:
图3:决策树剪枝策略流程
通过后剪枝策略后,正确分类概率变成了 16/20。显而易见,剪枝策略使得正确分类的概率得到提高。
剪枝策略较容易理解,在实际情况中后剪枝策略使用较多。在分支生成后,使用后剪枝策略将冗余的子树及其判别条件直接剪掉,然后使用上个节点中占比最大的类做为最终的分类结果。
sklearn决策树分类算法应用实现
决策树实现步骤
通过前面内容的学习,我们已经大体掌握了决策树算法的使用流程。决策树分类算法的关键在于选择合适的“判别条件”,该判别条件会使正确的分类的样本“纯度”最高。想要选取合适的特征属性就需要使用“信息熵”与“信息增益”等计算公式。
1) 确定纯度指标
确定纯度指标,用它来衡量不同“特征属性”所得到的纯度,并选取使得纯度取得最大值的“特征属性”作为的“判别条件”。
2) 切分数据集
通过特征属性做为“判别条件”对数据集集合进行切分。注意,使用过的“特征属性”不允许重复使用,该属性会从特征集合中删除。
3) 获取正确分类
选择特征集合内的特征属性,直至没有属性可供选择,或者是数据集样本已经完成分类为止。切记要选择占比最大的类别做为分类结果。
初识支持向量机SVM分类算法
支持向量机,英文全称“Support Vector Machines”(简称 SVM),它是机器学习中最常用的一种“分类算法”。SVM 是一种非常优雅的算法,有着非常完善的数学理论基础,其预测效果,在众多机器学习模型中可谓“出类拔萃”。在深度学习没有普及之前,“支持向量机”可以称的上是传统机器学习中的“霸主。
初识支持向量机
支持向量机是有监督学习中最有影响力的机器学习算法之一,该算法的诞生可追溯至上世纪 60 年代, 前苏联学者 Vapnik 在解决模式识别问题时提出这种算法模型,此后经过几十年的发展直至 1995 年, SVM 算法才真正的完善起来,其典型应用是解决手写字符识别问题。
支持向量机组成
首先对支持向量机做一个直观的描述:支持向量机是一个分类器算法,主要用于解决二分类的问题,最终告诉我们一个样本属于 A 集合还是属于 B 集合,这和之前学习过的分类算法别无二致。
一个算法模型就好比一台精巧的机器,有许多零部件组成,支持向量机也是如此。对于支持向量机而言有三个重要构件,分别是:
- 最大间隔
- 高维映射
- 核函数
上述三者是 SVM 支持向量机的核心,三者之间彼此独立,又互相依存,如果缺少了其中任何一个部件,都不能驱动支持向量机这台“机器”。如果用一句话来总结这三个部件的作用,那就是“最大间隔是标尺,高维映射是关键,最终结论看核函数”。
支持向量机本质
支持向量机本质上是从在线性分类算法的基础上发展而来的,就如同已经学习过的 Logistic 逻辑回归算法一样,只需给线性函数“套”上一层 Logistic “马甲”,就可以用线性模型来解决离散数据的分类问题。对于支持向量机来说,要解决分类问题,其过程则更为复杂。下面剖析一下支持向量机的本质,从而帮助您更好的理解它的算法思想。
1) 间隔和支持向量
支持像向量机算法中有一个非常重要的角色,那就是“支持向量”,支持向量机这个算法名字也由它而来(机,指的是“一种算法”),要想理解什么是“支持向量”就首先要理解“间隔”这一个词。
支持向量机中有一个非常重要的概念就是“间隔最大化”,它是衡量 SVM 分类结果是否最优的标准之一。下面通过“象棋”的例子来理解什么是“间隔”:
中国象棋是我国独有的一类娱乐活动,棋子分为黑子和红子,并用“楚河汉界”将其分开。如果用一条直线将不同颜色的棋子进行分类,这显然信手拈来,只需要在楚河汉界的空白附带画一条“中轴线”就能以最佳的方式将它们分开,这样就能保证两边距离最近的棋子保有充分的“间隔”。
上述示例中产生的“间隔”实际上是依据两侧不同颜色的棋子划分而成的,我们把这些棋子统称为“样本点”。虽然这些样本点都参与了分类,但对于分类效果影响最大的是处于间隔“边缘”的样本,只要将处于边缘的样本正确分类,那么这两个类别也就分开了,因此我们把处于边缘样本点称为“支持向量”。
2) 软间隔和硬间隔
间隔,又分为软间隔和硬间隔,其实这很好理解,当我们使用直线分类时会本着尽可能将类别全都区分开来的原则,但总存在一些另类的“样本点”不能被正确的分类,如果您允许这样的“样本点存在”,那么画出的间隔就成为“软间隔”,反之态度强硬必须要求“你是你,我是我”,这种间隔就被称为“硬间隔”,在处理实际业务中,硬间隔只是一种理想状态。
3) 最大间隔
上述所说的保有充分的“间隔”,其实就是“最大间隔”,你可能会问,为什么是最大间隔呢,两个类别只要能区分开不就行了吗?其实这涉及到算法模型最优问题,就像常时所说的一样,做事要给自己留有余地,不能将自己至于危险的边缘。
如果将数据样本分割的不留余地,就会对随机扰动的噪点特别敏感,这样就很容易破坏掉之前的分类结果,学术称为“鲁棒性差”,因此我们在分类时要尽可能使正负两类分割距离达到最大间隔。
支持向量机应用
支持向量机是一种使得样本点达到最佳分类效果的算法,但上述示例并非支持向量机的应用场景,通过上述示例我们只是知道了“什么是间隔”以及什么是“支持向量”,那支持向量应用场景到底是怎么的呢?通过下面形象化的描述,您也许能体会到 SVM 的强大之处:
当对弈双方在下棋之前,需要将散落在棋盘上的棋子放在各自的位置上,此时这些棋子并非按照颜色排列在“楚河汉界”两边,而是“杂乱无章”的放在棋盘上,那么如何快速地将这些棋子分呢?你应该如何做呢?当然你也许会想到用手一个个的挑出来,但是这里的棋子只是类比数据样本点,在实际的业务中你可能面对的是成千上亿的数据样本,要想解决这个问题,支持向量机就派上了用场。
如果用画“直线”的方法,一定不能解决上述问题,因此简单粗暴的线性函数“貌似”派不上用场,那么到低如果解决呢?
我们不妨回忆一下 Logistic 回归分类算法,通过给线性函数“套”上一层 Logistic 函数就解决了离散数据的分类问题,SVM 能否按照同样的思维方式来解决呢,答案是肯定的。
支持向量机类似于逻辑回归,这个模型也是基于线性函数 wTx + b 的,不同于逻辑回归的是,支持向量机不输出概率,只是输出类别。当 wTx + b 为正时,支持向量机预测属于正类;而当 wTx + b 为负时,支持向量机预测属于负类。当然,在判断类别的过程中还要用到 SVM 的另外两个重要部件,也就是“高维映射”和“核函数”,否则无法实现利用线性函数解决分类问题,至于是如何解决的,后续知识会做详细讲解。
注意:上述示例中“棋子”只是形象化的比喻,在具体的业务中,我们处理的是“数据样本点”。
本节初步认识了“支持向量机(SVM)算法”,了解了组成支持向量机的三个重要部件。通过对支持向量机本质的讲解,我们知道支持向量机是从线性函数的基础上发展而来的,因此我们可以得出,支持向量机(SVM)是一种利用线性函数解决线性不可分(分类)问题的算法。
SVM解决线性不可分问题
SVM高维映射
宋朝的苏轼有诗云“横看成岭侧成峰,远景高低各不同,不识庐山真面目,只缘身在此山中”诗的前两句指的从不同的角度看待一个事物会得到不一样的结果,用这句诗来引出的“高维映射”这个概念再合适不过了。
支持向量机的三大核心构件分别是最大间隔、高维映射以及核函数,高维映射则是支持向量机的第二个核心构件。我们知道线性分类器最大的特点就是简单,说白了就是“一根筋”,当面对非线性分类问题时不知变通,因此就需要帮助它疏通一下,就像解决 Logostic 逻辑回归问题一样,高维映射就是我们要寻找的方法。
1) 超平面
高维映射主要是用来解决“你中我,我中有你”的分类问题的,也就是前面所说的“线性不可分问题”,所谓高维映射就是站在更高的维度来解决低维度的问题。我们都知道点线面可以构成三维立体图,比如棋子是棋盘上的“点",“间隔”是棋盘上的一条线,棋盘则是一个“面”,而当我们拍盘而起,棋子飞升就会形成一个多维的立体空间,示意图如下:
图1:超平面示意图
如图所示经过高维映射后,二维分布的样本点就变成了三维分布,而那张恰好分开棋子的纸(图 1 呈现绿色的平面), SVM 统称其为“超平面”。
通过增加一个维度的方法(给平面增加一个高度,使其变成三维空间),解决“线性不可分的问题”。在上述过程中仍存在一些问题会令你困惑,比如为什么映射到高维后就一定能保证正负类分开,还有一个更令人挠头的问题,这个高维空间应该如何找呢,以及在新的空间中,原有的数据点的位置是如何确定的呢?
SVM核函数
要想解决上述问题,就必须要了解支持向量机的另外一个重要部件——核函数(Kernel Function)。
核函数是一类功能性函数,类似于 Logistic 函数。SVM 规定,只要能够完成高维映射功能的数学函数都称为“核函数”,它在支持向量机中承担着两项任务,一是增加空间的维度,二是完成现有数据从原空间到高维空间的映射。接下来对其做详细的介绍。
首先我们再次强调 SVM 是一种使用线性方法来处理线性不可分问题的算法。明确了这一点,下面再来看一个实例说明,对于 “你中有我,我中有你”这句话来说,最为经典的案例,当属一类数据包围了另外一类数据。如下图 2 所示:
深蓝色的的球,被另外一种淡蓝色的球体包裹住了,在这种情况下,任何一条直线都不能将它们分开,因此就无法使用线性函数直接实现类别划分。
图2:SVM核函数应用
现在我们变通一下使用高维映射的思维来解决一下,看看能否找到解决问题的突破口。
接下来,我们将深蓝色的数据点全部映射到一个三维空间内,使之与浅蓝色的数据点形成高度差,这样就可以使用线性函数完成不同样本点的分类了,就如同倒扣的漏斗,深蓝色的数据点全部集中与上方,而浅蓝色的则分布在漏斗底部,此时可以用一个平面(此处平面就是超平面)将它们分开,如图 3 所示中间的分割线。
图3:SVM高维映射
上述高维映射过程是通过核函数(或称映射函数)来实现的,通过这个函数就可以找到一个三维空间,并确定数据点分布,至于能否保证样本点完全分开,这也是由核函数决定的。那么这个核函数要怎么确定呢,这就要通过实际案例的分析、运算才能得到。
在 Pyhthon Sklearn 库提供了多种核函数,使用不同的核函数会对最终的分类效果带来不同程度影响,因此要选择使得分类效果最优的核函数。
因此高维映射和核函数看似是两个分开的部件,其实是一个整体,高维映射的核心就是“核函数”。更通俗地讲,高维映射只是一种指导思想,而核函数才是具体实践者。
SVM 的重要组成部分是间隔最大化和高维映射(将它与核函数看做一体)。
SVM 算法是用来解决线性不可分的“非线性”问题, 从而突破线性分类的局限性,使得线性分类器依然可以适用于“非线性”问题。在这个过程中起到关键作用的就是“高维映射”。而“间隔最大化”可以看做支持向量机的损失函数,它衡量分类效果是否最佳的“标尺”,让间隔达到最大就是 SVM 追求的至臻境界,要实现这个目标就要不断地训练模型,使模型的泛化能力最佳。
最后对 SVM 算法进行分类的大致过程进行总结,大致分为以下三步:
- 选取一个合适的数学函数作为核函数;
- 使用核函数进行高维映射,解决样本点线性不可分的问题;
- 最后用间隔作为度量分类效果的损失函数,找到使间隔最大的超平面,最终完成分类的任务。
从数学角度理解SVM分类算法
Python Sklearn库SVM分类算法应用实现
SVM 是一种有监督学习分类算法,输入值为样本特征值向量和其对应的类别标签,输出具有预测分类功能的模型,当给该模型喂入特征值时,该模型可以它对应的类别标签,从而实现分类。
Sklearn库SVM算法
下面我看一下 Python 的 Scikit -Learn(简称 Sklearn) 库是如何实现 SVM 算法的。
支持向量机算法被包含在 sklearn.svm 模块中,该模块提供了 7 个常用类,这些不同的类分别应用了不同的核函数,因此它们可以解决不同的问题,比如分类问题、回归问题以及无监督学习中的异常点检测等。下表对它们做了简单的介绍:
SVM算法类别 | 描述 |
LinearSVC类 | 基于线性核函数的支持向量机分类算法 |
LinearSVR类 | 基于线性核函数的支持向量机回归算法 |
SVC类 | 可选择多种核函数的支持向量机分类算法,通过“kernel”参数可以传入linear:选择线性函数;polynomial:选择多项式函数;rbf:选择径向基函数;sigmoid:选择 Logistics 函数作为核函数;precomputed:使用预设核值矩阵,SVC 类默认以径向基函数作为核函数。 |
SVR类 | 可选择多种核函数的支持向量机回归算法 |
NuSVC类 | 与 SVC 类非常相似,但可通过参数“nu”设置支持向量的数量。 |
NuSVR类 | 与SVR类非常相似,但可通过参数“nu”设置支持向量的数量。 |
OneClassSVM类 | 用支持向量机算法解决无监督学习的异常点检测问题 |
SVM 主要用于解决二分类的问题,上述表格中最常使用的是 SVC 类。下面对使用该算法的步骤进行总结:
- 读取数据,将原始数据转化为 SVM 算法所能识别的数据格式;
- 将数据标准化,防止样本中不同特征数值大小相差较大影响分类器性能;
- 选择核函数,在不清楚何种核函数最佳时,推荐使用“rbf”(径向基核函数)
- 利用交叉验证网格搜索寻找最优参数;(交叉验证的目的是防止过拟合,利用网格搜索可以在指定的范围内寻找最优参数)
- 使用最优参数来训练模型;
- 测试得到的分类模型。
支持向量机算法在分类问题中有着非常出色的表现,它的特点是够解决非线性问题,并且训练模型的时候不必依赖于全部数据,主要使用处于分类边缘的样本点,因此它也适用解决小样本群体的分类问题,并且泛化能力较强。
当然,SVM 也有一些不足之处,比如核函数的寻找难度较大,并且最原始的 SVM 算法只适用于二分类问题。后经过不断的拓展、延伸,目前的 SVM 算法可以解决多分类问题,同时能够解决文本分类问题。
什么是K-means聚类算法
机器学习算法主要分为两大类:有监督学习和无监督学习,它们在算法思想上存在本质的区别。
有监督学习,主要对有标签的数据集(即有“参考答案”)去构建机器学习模型,但在实际的生产环境中,其实大量数据是处于没有被标注的状态,这时因为“贴标签”的工作需要耗费大量的人力,如果数据量巨大,或者调研难度大的话,生产出一份有标签的数据集是非常困难的。再者就算是使用人工来标注,标注的速度也会比数据生产的速度慢的多。因此要想对没有被标注的数据进行分类,就要使用无监督学习算法。
常见的无监督学习算法,包括 K-means 聚类算法、均值漂移聚类算法、主成分分析法(即 PCA 算法)、EM算法(期望最大化算法)等。本节介绍无监督学习中最为经典的 K-means 算法,它是聚类算法簇中的一个,也是最为经典的聚类算法,其原理简单、容易理解,因此得到广泛的应用。通过对该算法的学习,您将掌握什么是聚类问题,以及如何解决聚类问题。
聚类和分类的区别
聚类算法与分类算法的最终的目的都是将数据区分开来,但是两者的实现过程完全不同。分类问题,通过对已有标签的数据进行训练来确定最佳预测模型,然后对新样本的所属类别进行预测,在这个过程中算法模型只要尽可能的实现最佳拟合就 OK 了。与分类问题不同,聚类问题没有任何标签,可谓是一遍茫然,就像做练习题没有参考答案一样,不知道自己做的是否正确。在这种情况下,如果您想证明自己做的题目是否对,在没有参考答案的情况下,您会怎么做呢?没错,您可以多找同学几位同学,甚至找全班同学去对比。
举个简单的例子:一道选择题,你的选择答案是 A,通过询问后您发现全班 85% 以上同学都选择的 A,其余 15% 都选择的 C,那么您心里就会认为自己选择的是正确的,毕竟选择 A 选项占了多数,但是在老师没有公布正确答案之前,什么也说不准,也许会发生“真理只掌握在少数人手里”的事情,因此选择 C 的同学也并不一定就是是错误的,通过这种“找相似”的方法即使在没有“参考答案”的前提下,也能实现分类。因此“找相似”是解决聚类问题的核心方法。
找相似
俗话说“物以类聚,人以群分”,从这句成语中就能体会到“找相似”奥妙,兴趣相投人总会相互吸引,相似的物也总会放在一起。同样的道理,在一份数据集中拥有相似特征的数据也要聚集在一起,这样才便于将这些数据区分开来,但世界上并不存在完全相同的两片叶子,因此聚类算法在实现分类时,只能尽可能找相同点,相同点越多,说明他们就属于同一类,而不同点越多,就说明两者不是同一类。
我们知道,动物种类可以按照科属进行划分,比如豹子、老虎、猫咪都属于猫科动物,有时你可能无法相信,温顺的猫咪竟然和凶猛的老虎同属猫科动物,这就说明他们身上有相似的地方,比如都善于攀爬以及跳跃、皮毛柔软、爪子锋利并可伸缩等等。其实,科学家们最初也没有一个明确的答案知道什么是“猫科动物”,他们通过找相似特征的方法,最终将动物们分门别类,因此这个过程也可以看做是“无监督学习”。
通过上述知识的学习,我们知道解决聚类问题的关键就是“找相似”,下面我们来看一看,K-means 聚类算法是如何在数据集中寻找相同点的。
簇是什么
在聚类问题中,有一个非常重要的概念“簇”(Cluster),那到底什么是簇呢,样本数据集通过聚类算法最终会聚集成一个个“类”,这些类在机器学习中的术语称为“簇”(注意,这里的前提是使用“聚类算法”),因此“簇”是解决聚类问题的表现形式,数据集中的数据样本最终会以“簇”的形式分开。那么当要解决一个聚类问题时,到底要汇集成多少簇呢?
对于分类问题而言,由于有参考答案,因此要分成多少类是已知的,但是聚类则不同,由于没有参考答案,所以形成多少个簇,事先谁也不知道。
举个简单的例子:有同样大小的正方形和圆形各 3 个,每个方形和圆形的颜色两两相同,分别是黄色、红色、绿色,如果按照形状分类的话,可以分为圆形和正方形两个簇,如果按照颜色分类的话,可以分为黄色、红色、绿色三个簇。由此可见选择的分簇条件不同,形成的簇的数量也不同,从而聚类的结果也不同。
不同聚类算法采取了不同的思路,主要分为划分法、层次法、密度法和网格法,这些方法大致可总结为两类,一类是预先设定有多少个簇,另一类则是在聚类的过程中形成。
理解K的含义
K-means 就是一种采用了划分法的聚类算法,K-means 聚类算法与前面的 KNN 分类算法一样,都带有字母“K”,前面我们说过,机器学习喜欢用字母“K”来表示“多”,就像数学中常用字母“n”来表示是同样的道理,但 K-means 中的 K 究竟是什么意思呢?不妨先回顾一下 KNN 分类算法中的 K。
我们知道,KNN 分类算法采用了“多数表决的方法”,最终样本类能够完成分类,完全依赖于该方法,比如 KNN 中的 K 表示有多少个样本点参与表决,这里的 K 对于样本的分类起到了关键性的作用,因此可以换个说法,多数表决是需要限定在 K 规定范围内的。
再说 K-means 中的 K,由于该算法是没有参考标准的。如果不加以限定的话,它会形多任意数量的“簇”,这就要求我们要预先设定“簇”的数量,就像田忌赛马一样,根据马的自身的特点,将其分为上、中、下三个档次,因此 K-means 中 K 是聚集成几个“簇”,形成几个“类”的意思。
如何量化“相似”
前面我们提到过解决“聚类问题”的关键是找到“相似”之处,只有找到了相同点才可以实现类别的划分,说的直白一点,聚类的过程就是让相似的样本互相抱团的过程,这个过程看上去很简单,但实际上要怎样去操作呢?
注意,这里所说的“相似”有时也称之为“相似度”与之含义相反的是“相异度”,相异度越低,相似度就越高,这些词语主用于是衡量对象之间的相似程度。
不妨先回顾一下 KNN 最近邻分类算法,该算法以待分类样本点为中心,通过度量距离找出与其最近邻的 K 个样本点,哪个类别的样本点数量多,那么就认为待分类的样本点属于哪一类。在这个过程中有两点是解决分类问题的关键,一是以待分类样本为“中心点”;二是通过度量距离来确定 K 个最邻近中心的样本点,从而找到哪几个样本点拥有表决权。
在聚类算法中“相似”其实并不是一个具体的指标,就像“人以群分”这句成语,它没有提供具体的划分标准,即“以什么分”,可能是性格、爱好,也可能是志向,甚至是人的高低贵贱,因此量化相似也要根据具体的场景,也就是确定比较的标准(即度量相似的标准)。
K-means 聚类算法与 KNN 算法有许多相似之处(即使在本质它们并不相同),KNN 通过度量距离确定距离自己最近的“朋友圈”,其实换个角度来看的话,这个“朋友圈”就相当于 K-means 中的“簇”,因此我们可以采用与 KNN 相同的度量工具作为量化“相似”的标准。
1) 随机选择质心
从 KNN 解决分类问题的过程不难看出,要想解决 K-means 聚类问题,同样需要一个“中心点”。
假设聚类问题的样本数据也能找出 K 个中心点,就能以该点为中心,以距离为度量画出范围来,将同一范围内的样本点作为一个簇,从而解决聚类问题,在 K-means 聚类算法中,这样的中心点称为“质心”。
聚类算法是无监督学习,因此数据中的样本点完全不知道自己属于哪一个簇, 就更别谈缺点“质心”了,为了解决这一问题,K-means 算法通过随机选择方式来确定质心,但由于是随机选择,因此无法保证随机选择的 K 个质心就恰好是完成聚类后的 K 个簇的中心点,这时就用到了“mean”,它是“均值”的意思,通过均值可以不断的调整质心,由此可知质心在 K-means 算法中是不断改变的。
2) 求出新质心点
假设现在随机了 K 个质心得到了 K 个簇,接下来要怎样让这 K 个簇形成新的质心呢?做法有很多,K-means 算法选择了最简单的一种,求平均。
每个簇都有若干数据点,求出这些数据点的坐标值均值,就得到了新质心的坐标点,比如一个簇中有三个数据点,分别 (3,2),(3,1),(2,3),那么新质心点位于:
x:(3+3+2)/3 约等于 2.666
y:(2+1+3)/3 = 2
质心坐标:(2.666,2)
这其实也是一种变相的多数表决。根据全体拥有表决权的数据点的坐标来共同决定新的质心在哪里,而表决权则由簇决定。
在 K-means 聚类的过程中会经历多次质心计算,数据点到底归属于哪个簇可能会频繁变动,比如同一个数据点可能在本轮与一群样本点进行簇 A 的质心计算,而在下一轮就与另一群样本点进行簇 B 的质心计算,这也是 K-means 算法与 KNN 算法最大的不同之处。
K-means 聚类算法的聚类过程,可以看成是不断寻找簇的质心的过程,这个过程从随机设定 K 个质心开始,直到找到 K 个真正质心为止。
K-means 聚类算法的大致过程如下所示:
- 第一步,既然现在有了 K 个质心,对于其他数据点来说,根据其距离哪个质心近就归为哪个簇的办法,可以聚成 K 个簇。但请注意,这只是第一步,并不是最后完成聚类的结果;
- 第二步,对于聚成的 K 个簇,需要重新选取质心。这里运用了多数表决原则,根据一个簇内所有样本点各自的维度值来求均值,得到该簇的新的坐标值;
- 第三步是生成新的质心,其实就是重复上述过程。对于根据均值计算得到的 K 个新质心,重复第一步中离哪个质心近就归为哪个簇的过程,再次将全部样本点聚成 K 个簇,经过不断重复,当质心不再变化后,就完成了聚类。
K-means 算法首先逐个计算数据集中的点到各自质心的距离,根据距离的远近,将数据样本点分别划归到距离最近的质心,从而形成 K 个类,然后继续选取新的质心,即对聚类内所有数据点求均值。最后重复上述两个过程:生成新质心后重新进行聚类,然后根据聚类结果再次生成新的质心,直至划分的“类”不再变化时结束。
K-means聚类算法原理解析
K-means 聚类算法的聚类过程,其实就是不断寻找簇的质心的过程,该过程从随机设定 K 个质心开始,直到找到 K 个最合适的质心为止。本节我们透过算法流程直击算法的本质,帮助您彻底理解 K-means 算法。
上述链接内容,从数学的角度对 K-means 算法的原理进行了深入剖析,下面我们对 K-means 算法的流程进行回顾,可分以下四步:
- 随机选取 K 个对象,并以它们为质心;
- 计算数据集样本点到质心的距离;
- 根据样本点距离质心的距离将其分簇(类),距离哪个近,划分到哪个簇(类);
- 以簇内所有样本点的均值重新计算质心,,然后重复第二步,直到划分的簇(类)不在变化后停止。
K-means 算法是属于无监督学习算法,常用于解决聚类问题,通过给算法模型输入一个包含多种特征信息的样本点,会返回一个相应的类别编号(或称簇别),从而完成样本数据点的类别划分。
注意,判定聚类任务完成的终止条件并不是唯一的,常用方法有三个:
- 簇内数据点向质心靠拢、收敛,使得质心点不再发生明显的变化;
- 使用误差平方和(即 SSE)来衡量,当误差平和的值越小时,表示数据点越接近于他们的质心,聚类效果越好;
- 设定指定的定迭代次数,即最多选取几次质心点,不过这种方法,未必能达到最好的分类效果。
K-means聚类算法的应用以及实现
K-means 聚类算法属于无监督学习,它会将相似的对象归到同一个簇中,该算法原理简单,执行效率高,并且容易实现,是解决聚类问题的经典算法。
尽管如此,任何一款算法都不可能做到完美无瑕,K-measn 算法也有自身的不足之处,比如 K-means 需要通过算术平均数来度量距离,因此数据集的维度属性必须转换为数值类型,同时 K-means 算法使用随机选择的方式来确定 K 的数量和初始化质心 ,因此不同的随机选择会对最终的分簇结果产生一定程度的影响。
算法应用场景
每一种算法都有各自适用的场景,对于 K-means 算法也不例外,它适合于解决特征维度为数值型的聚类问题。
举个简单的例子,一个赛季结束后,篮球队要对队员的整体表现进行聚类分析,此时每位队员的特征维度都是可以量化的,比如某队员的上场时间、得分数、助攻数、失误数等。
K-means 算法也适用于文本聚类,比如新闻网站会将相同话题的新闻聚集在一起,并自动生成一个个不同话题的新闻专栏,其实这就是利用聚类算法实现的,但是文本的特征维度并非数值类型,因此需要对其进行数值转化操作,将文本数据转换为数学信息,此时可以使用 TF-IDF 加权技术计算单个词的权值。
TF-IDF 是一种用于信息检索与数据挖掘的常用加权技术。TF 是词频(Term Frequency),IDF 是逆文本频率指数(Inverse Document Frequency)。
下表对 K-means 聚类算法的特点做了简单说明:
项目 | 内容 |
优点 | 原理简单,实现容易,运算效率高。 |
不足 | 需要人为设置簇的个数与随机初始化质心点可能影响聚类的最终效果,同时 K-measn 算法对孤立点(离群点)特别敏感,会对最终的聚类结果产生明显扰动。 |
应用领域 | 适用于特征维度为数据类型的聚类问题,比如体育赛事等,而对特征维度不是数据类型的需要提前进行转换,比如文本分类等。 |
Sklearn使用K-means算法
在 Sklearn 机器学习库中,与聚类相关的算法模型都在 cluster 模块下,除 k-measn 外,还有十种聚类最近邻算法,下表对最常用的算法做了简单介绍:
类名 | 说明 |
KMeans 类 | 本节介绍的算法,也是应用最多的聚类算法 |
MiniBatchKMeans 类 | 该算法是 K-measn算法变形算法,使用 mini-batch(一种采样数据的思想) 来减少一次聚类所需的计算时间,mini-batch 也是深度学习常使用的方法。 |
DBSCAN 类 | DBNSCAN 算法是一种比较有代表性的基于密度的聚类算法,它的主要思想是将聚类的类视为被低密度区域分割的高密度区域。与划分聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇。 |
MeanShift 类 | MeanShift 算法流程,以任意点作为质心的起点,根据距离均值将质心不断往高密度的地方移动,也即所谓均值漂移,当不满足漂移条件后说明密度已经达到最高,就可以划分成簇。 |
AffinityPropagation 类 | AffinityPropagation 算法(简称 AP 算法),该算法是层次聚类的典型应用,聚类实现过程是一个“不断合并同类项”的过程,用类似于归纳法思想来完成聚类。 |
通过表格不难看出,每一种算法所采用的思想均不相同,但最终都能解决聚类问题,这也是整个聚类算法族的特点之一。
下面我们对Kmeans.Kmeans()的常用参数做简单介绍:
参数 | 说明 |
algorithm | 字符串参数值,有三种选择:1) "auto" :默认值,自动根据数据值是否稀疏,来决定使用 "full"还是"elkan",采用默认值即可;2) "full":表示使用传统的 K-measn 算法;3) "elkan":表示使用 elkan-Means 算法,该算法可以减少不必要的距离计算,加快计算效率。 |
n_cluster | 整型参数,表示分类簇的数量,默认值为 8 |
max_iter | 整型参数,表示最大的迭代次数,默认值为 300 |
n_init | 整型参数,表示用不同的质心初始化值运行算法的次数,默认值为 10 |
init | 字符串参数,有三个可选参数:1)" k-means++" ,默认值,用一种特殊的方法选定初始质心从而能加速迭代过程的收敛,效果最好;2) "random" 表示从数据中随机选择 K 个样本作为初始质心点;3) 提供一个 ndarray 数组,形如 (n_cluster,n_features),以该数组作为初始质心点。 |
precompute_distance | 有三个可选值,分别是 "auto", True, False:1) "auto" :如果样本数乘以聚类数大于 12 million 的话则不予计算距离;2) True:总是预先计算距离;3) False:永远不预先计算距离。 |
tol | 浮点型参数(float),表示算法收敛的阈值,默认值为 1e-4 |
n_jobs | 整型参数,指定计算所用的进程数量,1) 若值为 -1,则用所有 CPU 进行运算;2) 若值为 1 ,则不进行并行运算,方便调试;3) 若值小于 -1,则用到的 CPU 数为(n_cpus+1+n_jobs),因此若为 -2 ,则用到的 CPU 数为总 CPU 数减去1 |
random_state | 表示随机数生成器的种子,参数值为整形或 numpy.RandomState 类型 |
verbose | 整型参数,默认值为 0,表示不输出日志信息;1 表示每隔一段时间打印一次日志信息;如果大于 1时,打印次数变得频繁。 |
聚类算法博大精深,每一种算法都有自己的实现原理,单拿 K-means 算法来说,就有多种基于它的衍生算法,比如二分 K-means 算法、K-means++ 算法、K-measn|| 算法、Canopy 算法,以及 Mini Batch K-means 算法等,这些算法的出现主要是为了弥补 K-means 算法的不足,比如随机选择初始簇质心点,以及 K 值敏感等问题。
不过世界上并没有十全十美的算法。
人工神经网络是什么
在本教程的开篇《人工智能是什么》一节中详细的阐述了深度学习发展历程,以及人工智能、机器学习、深度学习三者间的关系。就目前而言,这三者中红到发紫的当属“深度学习”。
深度学习(Deep Learning)这一概念是由 Geoffrey Hinton(深度学习之父)于 2006 年提出,但它的起源时间要早得多,可追溯至 20 世纪四五十年代,也就是人类刚刚发明出电子计算机时就已经提出来了,但当时并非叫做深度学习,而是人工神经网络(artificial neural network, ANN),简称神经网络(NN),它是一种算法模型,其算法的构思灵感来源于生物神经网络。
深度学习作为一个新兴概念,谈起时都会涉及如何搭建神经网络,由此可见深度学习的核心思想仍是人工神经网络模型。目前的神经网络算法与刚刚诞生时相比有了很大的变化,但总的来说,基本的算法思想并没有改变。
MP神经元模型
人工神经网络是一种有监督学习算法,它试图通过模拟人脑神经系统对复杂信息的处理机制来构建一种数学模型。我们知道,神经元是构成生物神经系统的基本单元,而人工神经网络也不例外,它也是从神经元模型的基础上发展而来的。
1943 年,美国心理学家麦克洛奇(Mcculloch)和数学家皮兹(Pitts)提出了 M-P 神经元模型(取自两个提出者姓名的首字母),这是最早、也是最简单的神经网络算法的模型,该模型意义重大,从此开创了神经网络模型的理论研究。在正式介绍 MP 神经元模型前,我们不妨先了解一下大脑神经元。
1) 生物神经元
神经元是大脑神经系统重要组成单位,主要由细胞体、树突、轴突、突触组成。神经元是一种多输入单输出的信息处理单元,输入的电信号有两种,分别是兴奋性信号和抑制性信号。
树突,可以看作输入端,接受从从其他细胞传递过来的电信号;轴突可以看作输出端,传递电信号给其他细胞;突触,则可以看成 I/O 接口,用于连接不同神经元,单个神经元可以和上千个神经元进行连接;细胞体内存在膜电位,外界传递过来电流时会使膜电位发生变化,当电位升高到一个阈值时,神经元就会被激活,产生一个脉冲信号,传递到下一个神经元。
图1:生物神经元组成
为了便于大家理解神经元传递信号的过程,我们不妨把神经元看成一个水桶。水桶一侧的下方连接着多根水管(看做树突),水管即可以把桶里的水排出去,也可以将其他桶内的水输入进来,水管的粗细不同(理解为权重大小),对桶内水位的影响程度不同,当桶内的水位达到某一范围时(阈值),就能通过水桶另一侧的排水管将水(轴突)排出,从而降低水桶的水位。
2) M-P神经元
M-P 模型就是基于生物神经构建的一种数学模型,只过不它将生物神经元信息传导过程进行了抽象化,并以网络拓扑相关知识来表示。
M-P 模型是神经网络的基本组成单位,在神经网络中也称为『节点(node)』或者『单元(unit)』。节点从其他节点接受输入,或从外部源接受输入(即 x1、x2、1),每个输入都带有一个权重值(weight,即 w),权重大小取决于输入值的相对重要性。函数 f 位于节点处,它是一个关于 ω、x 的线性函数,记做 f(x,ω) ,输入 b 表示函数的偏置项,最后经过 f(w,x) 的计算得输出 Y。模型如下所示:
图2:神经元模型示例图
上述模型对于神经网络说来说具有重要的意义,它是神经网络研究的开端。您可能会很诧异,几个带有箭头线段、一个圆形竟然就能表示 M-P 神经元模型? 正所谓大道至简,它的确就是神经元模型,上图所示模型由 3 部分组成,从左往右依次为:神经元的输入、输入信号处理单元,以及神经元的输出。
M-P 模型采用数学模型模拟了生物神经元所包含的细胞体、树突、轴突和突出等生理特征。通过 M-P 模型提出了神经元的形式化数学描述和网络结构方法,从而证明了单个神经元能执行逻辑功能,但由于模型中的权重和偏置是人为设置的,因此该模型并不具备学习的能力。
3) M-P模型解析
我们知道,神经元是一种多端输入单端输出的信息处理单元,因此 M-P 神经元模型也遵循这个原理。神经元的输入端通常会被给予不同的权重,来权衡不同输入信号的重要程度,如图 2 所示是一个有 3 个输入,一个输出的神经元模型,该神经元模型接收 3 个输出信号,然后给予输入信号不同的权重,神经元的输入信号经过处理后得到神经元输出。注意,这里所说的信号可以理解为数据集中的数据样本。
4) 信息处理单元
介于输入和输出之间的圆圈称为输入信息处理单元(即节点),之所以画成圆圈也是一种约定俗成的表示方式,而这个信息处理单元可以看成一个函数,当给这个模型“喂入”一个数据时,就会产生一个对应的输出。早期的 MP 神经元模型可以看成一种线性分类器,通过检验 f(x,ω) 的正负来识别两种不同类别的时输入。由此可知,该模型需要正确设置权重参数,才能使模型的输出对应所期望的类别。
注意:这里的 x 是表示输入值,ω 是输入的权重值,f(x,ω) 是一个线性函数,这也决定了该模型只能解决简单的线性问题,而对于复杂的数据分布,就无法达到理想的拟合效果。
感知机模型
新事物的诞生需要大众的一个认知过程,并非一问世就能一鸣惊人,虽然早在 1943 年基于 M-P 神经元人工神经网模型就被提出,但当时并没有引起人们的重视。直到 20 世纪 50年代(1957年),美国学者罗森勃拉特提出了感知器(或称感知机)模型,这才引发了一次 AI 领域的研究热潮,因此从某种意义上来说,感知器模型是第一个具有学习能力的神经网络,该模型能根据每个类别的输入样本来学习权重。
1) 感知器模型
感知器模型,也可称为单层感知器,它是最简单的神经网络,它包含输入层和输出层,并且层与层之间直接相连。该模型从神经元模型的基础上发展而来,单层感知器能模拟逻辑与、逻辑或、逻辑非和逻辑与非等操作,单层感知器模型如下:
图3:感知器模型
虽然具备了学习的能力,但该模型只能解决简单的线性分类和线性回归问题,对于线性不可分问题(即异或问题,xor)仍无法解决(1969年,科学家明斯基和佩珀特证明)。如下图所示,无法找到一条直线可以把圆形和菱形分开:
图4:线性不可分问题
感知器模型算法与神经元模型类似,是一个单层神经元结构,它首先对输入的数据进行加权求和,然后将得到的结果与阈值进行比较,假如与所期望的输出有较大误差,就对权值参数进行调整,反复多次,直到误差满足要求时为止。由上图可知单层感知器的输出为:
2) 激活函数
由上述函数表示式可知,感知器是一个二分类的线性模型,输入与输出结果是一组线性组合,这极大的限制了感知器的应用范围。但这一问题很快便得到了解决,我们只需将非线性函数以“激活函数”的身份加入神经网络算法中,就可以扩展感知器模型的应用范围。通过它对线性函数的输入结果进行非线性映射,然后将结果作为最终值输出。激活函数的加入对后期神经网络的发展提供了很大支持,目前这种算法思想仍在神经网络算法中广泛使用。下图展示了带有激活函数的感知器模型:
图5:感知器模型
上述感知器模型依然模拟了神经元结构,有输入(input)、权重(weight)、前馈运算(feed forward)、激活函数(activation function)、输出(output)等部分组成。注意,这里的前馈运算指的是图 5中的『加权求和』,即在没有使用激活函数时输入值的加权求和结果,有时也记做『logit』。
通过上述模型很容易实现二分类。只需将对加权求和的结果值进行判断即可,比如 x>0 为 1 类,若 x <=0 则为 0 类,这样就将输出结果值映射到了不同类别中,从而完成了二分类任务。激活函数公式如下:
若想采用感知器模型解决线性回归问题就可以使用 sigmoid 函数,该函数在《Logistic回归算法(分类问题)》 一节进行了介绍,激活函数公式如下:
注意:常用非线性激活函数有多种,比如 sigmoid 函数、Tanh 函数、Relu 函数等
3) 多层感知器模型
由于单层感知器模型无法解决非线性可分问题,即 xor 问题(1969年,马文·明斯基证明得出),这也导致了神经网络热潮的第一次大衰退。直至 20 世纪 80 年代,多层感知器模型(Multi -Layer Perceptrons,缩写为 MLP)的提出(1981年,韦伯斯提出),神经网络算法再次回归大众视野。
与单层感知器模型相比,该模型在输入层与输出层之间增加了隐藏层(Hidden),同时输出端,由原来一个增至两个以上(至少两个),从而增强了神经网络的表达能力。注意,对于只有一层隐藏层的神经网路,称为单隐层神经网络或者二层感知器,网络拓扑图如下所示:
图6:多层感知器模型
从图 6 不难发现,多层感知器模型是由多个感知器构造而成的,模型中每一个隐藏层节点(或称单元)都可以看做成一个感知器模型,当我们将这些感知器模型组合在一起时就可以得到“多层感知器模型”。输入层、隐藏层与输出层相互连接形成了神经网络,其中隐藏网络层、输出层都是拥有激活函数的功能神经元(或称节点)。
在神经网络中的隐藏层可以有多层,当隐藏层有多层,且形成一定“深度”时,神经网络便称为深度学习(deep learning),这就是“深度学习”名字的由来。因此,深度学习就是包含了多个隐藏层的多层感知器模型。如下图所示,是具有两个隐藏层的神经网络:
图7:多层感知器模型(两个隐藏层)
但『深度学习』这一概念直到 2006 年才被提出,在这之前多层感知器模型被称为“人工神经网络”。从神经元模型到单层感知器模型再到多层感知器模型,这就是人工神经网络的发展过程。在神经网络中每层的节点与下一层节点相互连接,节点之间不存在同层连接,也不存跨层连接,这样的网络结构也被称为“多层前馈神经网络”(multi-layer feedforward neural),如果层与层之间的节点全部相互连接,则称为“全连接神经网络”,如下所示:
图8:全连接神经网络
多层感知器的诞生,解决了单层感知器模型无法解决的异或问题。下面简单分析一下解决过程。如图所示是包含了一个隐藏层的多层感知器模型:
图8:多层感知器解决异或问题
在多层感知器模型中,隐藏层中的每一个节点都是想当于一个感知器模型。下面将输入值(x1 和 x2)带入隐藏层节点,可得以下函数式(这里的函数指的是激活函数):
由此可知输出层的函数式如下:
根据异或法则“同为 0,异为 1”,分别将 (0,1),(1,0),(0,0),(1,1) 带入上述三个函数分别进行计算,可得以下结果(正数为 1,负数为 0):
可以看出输出层 f3函数的结果完全符合异或运算法则,因此多层感知器可以解决“异或问题”。从函数图像上来看,多层感知器使用两条直线解决了线性不可分问题:
图9:分类区域
上图所示,位于红色直线之间的属于正类,而位于区域之外则属于负类。当然图像中只是包含了四个点而已,若是复杂的数据则可以选择不同的激活函数,比如 sigmoid 函数等。
反向传播算法
多层感知器的虽然解决了线性不可分问题,但随着隐藏层网络的加深,多层网络的训练和参数计算也越来越困难,因此多层感知器也显得“食之无味”。简单来说,就是当时的人们还不知道应该怎么训练多层神经网络,甚至不相信多层神经网络也是同样能被训练的。
直到 1986 年,深度学习教父 Hinton 等人对反向传播算法(Backpropagation algorithm,即误差逆向传播算法,简称 BP算法)进行了重新描述,证明了该算法可以解决网络层数过深导致的参数计算困难和误差传递等问题。
反向传播算法是一种用于训练神经网络的有监督学习算法,基于梯度下降(gradient descent)策略,以目标的负梯度方向对参数进行调整。但受限于当时(20世纪80年代)计算机算力不足等因素的影响,BP 算法只能以简单低效的方式来解决少数层神经网络训练问题,但即使如此,也已经弥足珍贵。
BP 算法的出现再次引发了 AI 研究的热潮,它是一款非常成功的神经网络算法,直到今天,该算法仍在深度学习领域发挥着重要的作用(用于训练多层神经网络)。
经过几十年的发展,到目前为止,人工神经网络的发展进入了深度学习阶段,在这一阶段提出了许多新的神经网络模型,比如循环神经网络、卷积神经网络、生成对抗网络、深度信念网络等等。同时,深度学习又为人工神经网络引入了新的“部件”,比如卷积层、池化层等。
如今深度学习已非“人工神经网络”一词所能完全替代,可谓是“青出于蓝,而胜于蓝”,它已发展出一整套复杂的知识体系。
纵观人工神经网络的发展历程,从生物神经元起源,再到多层感知器模型,历经三起两落,终于成为机器学习算法中的佼佼者。理解人工神经网络的发展历程,同时掌握各个模型的核心思想,对于后续知识的学习非常重要。
神经网络分类算法原理详解
在神经网络算法还没流行前,机器学习领域最受关注的算法是“支持向量机算法(即 SVM 算法)”,如今神经网络方兴未艾,您也许会好奇,神经网络各层的原理和结构都高度相似,为什么要堆叠这么多的神经网络层呢?就好比为什么单层感知器模型不能解决异或问题,但只要加上隐藏层就能解决呢?到底是谁赋予了神经网络如此奇妙的魔力。
一般来说,神经网络的层数越多,网络模型的学习能力就越强,就越能拟合复杂的数据分布。但这只是一种理想状态,因为随着网络的加深,也会带来其他问题,比如计算的难度也会增加,同时模型理解起来也比较晦涩。因此选择恰当的网络层数去解决适合的场景,这是神经网络算法中的难点。
神经网络工作流程
下面通过一个简单的示例来理解神经网络究竟是如何工作的:
图1:人工神经网络模型
如图 1 所示, A、B、C、D 是四位盲人,他们要玩“盲人摸象”的游戏。在数据集中有以下四个动物:大象、野猪、犀牛、麋鹿。四个人中 A、B、C 负责去摸动物(即动物特征),D 负责汇总分析 A、B、C 传递给他的信息,同时还会有人告诉 D,这一轮他们摸到是什么动物。此外,规定只有当 A、B、C 三个人摸到一下三个特征的时候向 D 汇报:
注意,游戏在理想状态下进行的,不考虑其他外界因素。下面按照有监督学习的流程,先训练再预测。摸动物的过程,其实就是获取动物部位特征的过程,因为有 4 只动物,因此此处需要轮询 4 次,下面是四轮完成后 D 汇总的信息,如下所示:
通过对上述汇总信息的分析,D 认为,C 汇报的最没有价值(即权重小),因为无论是不是大象,他所汇报的内容都是一样的。D 认为,相比之下,A 和 B 的报告更有价值(权重大),但各自汇报也会有错误的时候。经过 D 研究发现,只要将 A 和 B信息进行汇总,当两人同时说摸到【柱子和蒲扇】时,那么被摸的动物就是大象,这样即便是盲人也能通过精诚团结摸出大象来。
对于上述示例来说,A/B/C/D 其实构成了一个简单的神经网络模型,它们就想当于四个神经元,A/B/C 负责去“摸”,也就是回去不同维度的输入数据,构成了神经网络的输入层。当它们三个人获取数据后都会告诉 D,通过 D 汇总分析,给出最终预测结果,即判断是不是大象,这相当于神经网络的输出层。神经网络能够把分散的信息进行汇总,从而提取出最有价值、权威的信息。若只是将网络中的一个独立节点拎出来都是以偏概全,比如 C 认为尾巴像鞭子的都是大象,这显然不合理的。
神经网络通过赋予输入信息不同的权重值来区别不同信息的重要程度。在模型训练过程中通过调节线性函数的相应权值,增加有价值信息的输入权值,降低其他价值信息较低的输入权值,这是【调优权值】的核心思想,通过上述方法能够提高网络模型预测的预测准确率。
神经元节点的个数和层数越多,神经网络的表达能力就越强,或者说拟合数据的能力就越强,这也是神经网络算法与其他机器学习学习算法相比,为什么适合处理图像识别、语音识别等复杂任务的根本原因。
反向传播算法
在神经网络模型中有两个重要部件,分别是:激活函数和反向传播 BP 算法,关于激活函数的相关概念,在《人工神经网络是什么》一节已经做了相关介绍,那到底什么是反向传播算法呢?在讲解反向传播之前,有必要先了解一下正向传播的概念。
我们知道,人工神经网络是由一个个的神经元节点构成的,这些节点的作用就是负责接受和传导信息,如同大脑神经元一样,接受外接刺激,传递兴奋信号。
在一个人工神经网络模型中,从输入层开始,传递到输出层,最后返回结果,这种信号传播方式被称为“正向传播”(或称前向运算、前向传播)。在神经网络模型中,若输入一层层的传递下去的,直到输出层产生输出,正向传播就结束了。
反向传播的与前向传播类似,但由于传播方向相反,因此被称为反向传播算法(简称 BP 算法),该算法最早出现在 20 世纪 60 年代,但当时并没有引起重视,直到 1986 年经 Hinton 等人进行了重新描述,才再次进入大众的视野。该算法成功解决了少数层神经网络【权值参数】计算的问题。
图2:前向运算和反向传播示意图
1) 反向传播原理
反向传播算法(BP)是一种有监督学习算法,即通过有标记的训练数据来学习,它是训练人工神经网络模型的常用方法之一。简单的来说,BP 算法就是从错误中学习,直至将错误程度降到最低时结束,从而提高模型的可靠性。
BP 算法的学习过程由正向传播过程和反向传播过程两部分组成。在正向传播过程中,输入信息通过输入层经隐含层,逐层处理并传向输出层,如果输出值与标记值存在误差,则将误差由输出层经隐藏层向输入层传播(即反向传播),并在这个过程中利用梯度下降算法对神经元的各个权值参数进行调优,当误差达到最小时,网络模型训练结束,也即反向传播结束。流程图如下所示:
图3:神经网络模型训练
对上述过程进行总结:输入层接受一个输入数据 x,同时初始化一个权重参数 ω,通过隐藏层计算之后,由输出层输出结果,前向运算完成。之后,将输出层结果与标记值进行比较,获取偏差值,将此偏差值由输出层向输入层传播(反向传播阶段),这个阶段利用梯度下降算法对权值参数进行反复调优,当偏差值最小时,获得一组最优的权值参数(ω)。
2) 应用示例
反向传播算法(过程及公式推导)_深度学习基础之反向传播算法过程:
- 前向运算阶段
- 反向传播阶段(梯度下降算法):使误差优化:loss最小化
神经网络分类算法是一种有监督学习算法,使用神经网络分类算法,大致需要以下五步:
- 初始化神经网络中所有神经元节点的权值;
- 输入层接收输入,通过正向传播产生输出;
- 根据输出的预测值,结合实际值计算偏差;
- 输出层接收偏差,通过反向传播机制(逆向反推)让所有神经元更新权值;
- 从第 2 步到第 4 步是一次完整的训练模型的过程,重复该过程,直到偏差值最小。
神经网络算法通过反向传播机制让所有神经元实现了权值更新,当我们不断迭代上述训练过程,直到偏差值最小,最终就会得到一个最优的网络模型,实现了对数据的最佳拟合。
神经网络分类算法的应用及其实现
在深度学习大热的当下,神经网络算法是最知名、应用最为广泛的机器学习算法。可以毫不夸张地说,你所能接触到的人工智能产品,绝大部分都使用了神经网络算法,比如手机经常用到的刷脸解锁、美颜修图、照片中的人物识别等,都是基于神经网络分类算法实现的。
神经网络算法特点
我们知道,深度学习的本质就是神经网络算法(深度学习是神经网络算法的一个分支)。理论上来说,在数据量和隐藏层足够多的情况下,神经网络算法能够拟合任何方程(函数)。神经网络算法是一种具有网络结构的算法模型,这决定了它具有非常好的延展性,通过调节神经网络中各个节点的权值参数使得分类效果明显提升。总的来说,神经网络算法具有以下特点:
1) 黑盒算法
神经网络算法,也被称为“黑盒算法”,这是因为人们无法从外部得知神经网络模型究竟是如何完成训练的,比如使用一个预测准确率为 97% 的猫脸识别模型,有时会将小狗的脸部照片归纳到小猫中,而这种情况是无法解释的,因此神经网络算法又被人们形象地称之为“黑盒算法”。
图1:黑盒算法
由于神经网络算法的这一特性,导致一些场景并不适合使用神经网络算法,比如银行不会使用神经网络算法来评判用户的是否具备信用,因为一旦出现预测错误,银行根本无法溯源找到评判错误的原因,也就无法向客户做出合理的解释。
2) 数据量
在互联网并不发达的七八十年代,数据量不足是阻碍神经网络发展的一大因素。与传统的机器学习算法相比,要想训练一个优秀的神经网络模型,往往需要更多的数据(至少需要数千甚至数百万个标记样本)。
比如人脸识别,需要各种姿态样式的人脸,发怒的、喜悦的、悲伤的、戴眼镜的、模糊的等等,总之越多越好。海量数据集对于训练一个优秀的神经网络模型非常重要,神经网络获得数据越多,表现能力就越好,这样训练出来的模型才具有更好的泛化能力。
注意:经过长达几十年的积累,直到目前,已经有大量的公开数据集可以使用,比如 Kaggle 数据集、Amazon 数据集、UCI 机器学习资源库、微软数据集等等。
3) 算力和开发成本高
在计算方面,比传统算法下相比,神经网络算法要耗费更多的计算机资源,对于复杂的深度学习模型来说,若想训练出一个优秀的模型,甚至需要几周的时间。但以 20 世纪七八十年代的计算机硬件水平,想要实现如此大规模的计算,几乎是不可能的。因此计算机的硬件性能也是影响神经网络发展的因素之一。
进入 21 世纪以后,计算机的硬件性能获得了飞速发展,这为神经网络的发展创造了有利的外部环境。
2017 年 5 月,围棋高手 AlphaGo 机器人,从空白状态学起,自我训练 3 天,对弈 490 万次,便打败了人类第一围棋高手柯洁。AlphaGo Zero 作为 AlphaGo 的进阶版,它自我训练 40 天,对弈 2900 万次,最终以 100:0 的战绩,打败了它的前辈 AlphaGo 机器人。而这些数据的背后,是强大算力作为支撑。
同时神经网络模型搭建过程较为复杂,激活函数的选择,权值的调节,都是一个比较费时的过程,因此其开发周期相对较长。总之,神经网络算法是一种成本较高的算法,这也决定了它能够解决比传统机器学习算法更为复杂的问题。下表对神经网络的特点做了简单的总结:
项目 | 说明 |
优点 | 网络结构延展性好,能够拟合复杂的数据分布,比如非线性函数,通过调节权值参数来获取泛化能力较强的模型。 |
缺点 | 可解释性差,调参依赖于经验,可能会陷入局部最优解,或者梯度消失、梯度爆炸等问题。 |
应用领域 | 神经网络算法拟合能力强,应用领域广,比如文本分类等,而深度学习作为神经网络的分支,也是当前最为热门研究方向,在图像处理、语言识别和自然语言处理等多个领域都有着非常突出的表现。 |
神经网络算法应用
讲了这么多有关神将网络的相关知识,一切的都是为了解决实际的问题,那应该如何在编程中使用它呢?Python 机器学习 Sklearn 库提供了多层感知器算法(Multilayer Perceptron,即 MLP),也就是我们所说的神经网络算法,它被封装在 sklearn.neural_network 包中,该包提供了三个神经网络算法 API,分别是:
- neural_network.BernoulliRBM,伯努利受限玻尔兹曼机算法,无监督学习算法;
- neural_network.MLPClassifier,神经网络分类算法,用于解决分类问题;
- neural_network.MLPRgression,神经网络回归算法,用于解决回归问题。
下面使用神经网络分类算法解决鸢尾花的分类问题。在这之前有必要先了解 neural_network.MLPClassifier 分类器常用参数,如下所示:
名称 | 说明 |
hidden_layer_sizes | 元组或列表参数,序列内元素的数量表示有多少个隐藏层,每个元素的数值表示该层有多少个神经元节点,比如(10,10),表示两个隐藏层,每层10个神经元节点。 |
activation | 隐藏层激活函数,参数值有 identity、logistic、tanh、relu,默认为 'relu' 即线性整流函数(校正非线性) |
solver | 权重优化算法,lbfgs、sgd、adam,其中 lbfg 鲁棒性较好,但在大型模型或者大型数据集上花费的调优时间会较长,adam 大多数效果都不错,但对数据的缩放相当敏感,sgd 则不常用 |
alpha | L2 正则项参数,比如 alpha = 0.0001(弱正则化) |
learning_rate | 学习率,参数值 constant、invscaling、adaptive |
learning_rate_init | 初始学习率,只有当 solver 为 sgd 或 adam 时才使用。 |
max_iter | 最大迭代次数 |
shuffle | 是否在每次迭代时对样本进行清洗,当 solver 参数值为 sgd 或 adam 时才使用该参数值 |
random_state | 随机数种子 |
tol | 优化算法中止的条件,当迭代先后的函数差值小于等于 tol 时就中止 |
什么是集成学习算法
准确来讲,集成学习算法并非一种机器学习算法,它更像是一种模型优化方法,是一种能在各种机器学习任务上提高准确率的强有力技术,这种技术的关键体现在“集成”两个字上,所谓集成就是“捏在一起”,因此集成学习算法可以理解成是一套组合了多种机器学习算法模型的框架,它关注的是框架内各个模型之间的组织关系,而非某个模型的具体内部结构。
可以说集成学习算法是“集”百家之长,使预测模型获得较高准确率,当然这也导致了模型的训练过程会稍加复杂,效率降低了一些,但在硬件性能发达的今天,几乎可以忽略不计。
当下深度学习大行其道,将任何一款传统机器学习算法单拎出来与之一较高下,几乎都会败下阵来,而集成学习算法的出现打破了这个平衡,它几乎能与深度学习平分秋色。在 Kaggle、天池等著名机器学习竞赛中,选手使用最多当属集成学习算法,而非 SVM、KNN 或者 Logistic 逻辑回归等单个算法,由此可见集成学习算法具有更广泛的适应场景,比如分类问题、回归问题、特征选取和异常点检测等各类机器学习任务。
集成学习发展史
集成学习算法的理论、应用体系的构建与完善经历一个漫长的过程,下面进行简单地介绍。
集成学习最早出现于 1979 年,Dasarathy 提出了集成系统(Ensemble system) 的思想,他使用线性分类器和最近邻居分类器组成的复合模型进行训练,得到了比单个分类器训练更好的预测效果。
1988 年 Kearns 提出了“弱学习器”概念,引发了“能否用一组弱学习器创造一个强学习器”的广泛讨论。(学习器,指的是某种机器学习算法模型),注意,所谓弱学习器,指的是一个个单独的算法模型,比如 KNN 算法模型、线性回归模型、朴素贝叶斯等,而强学习器指的是由多个不同类别的“弱学习器”集成的学习器,也称“异质集成”,这类学习器的预测准确率在 90% 以上。除此之外,还有一种“基学习器”(也称同质集成),它是由同一款机器学习算法组成的。
1990 年 Schapire 对这问题给出了答案,并且研发了著名的 Boosting 算法,该算法是集成学习常用方法之一;1992 年 Wolpert 首次提出“堆叠泛化”这一概念,即“堆叠”弱学习器训练的模型比任何单个弱学习器训练的模型具有更好的性能。
1996年,Breiman 开发了另一个集成学习方法 —— Bagging 算法(也称装袋算法),并对其原理和训练过程进行了详细的描述,并明确指出 Bagging 算法能够提高预测的准确性。其后几年,Breiman 在 Bagging 算法的基础上对“随机决策森林”进行另外重新描述,提出了集成学习中最广为人知的算法 —— 随机森林算法(RandomForest),该算法通过集成学习的思想将多棵“决策树”集成为一片“森林”,使其兼顾了解决回归问题和分类问题的能力。
截止到目前,已经有越来越多的集成学习算法被提出,比如 2010 年 Kalal 等人提出的 P-N 学习,以及近几年提出的以堆叠方式构建的深度网络结构、XGBoost 等算法,它们都能显著提升模型的预测效果。
集成学习组织方式
集成学习不是一种独立的机器学习算法,而是把互相没有关联的机器学习算法“集成”在一起,从而取得更好的效果。我们知道,每个算法模型都有各自的局限性,集成学习方式的出现正好弥补了这一不足之处,其实就算是大神也有“折戟沉沙”的时候,但人多力量大,多找几个大神凑在一起,就算遇到难题,最终也能比较好的解决。
前面,我们介绍的机器算法都是“个人”的单打独斗,而集成学习是“团队协作”,大家可以集思广益。这种方式固然好,但是如果没有统一的协调,也很容易出现问题,比如一个开发团队遇到问题时,总能通过相互沟通很快地推举出一个擅长解决该问题的人。但机器学习算法是无法使用语言来沟通的,那怎样才能使集成学习发挥出团队威力呢?这就要通过集成学习的组织结构来解决这一问题。
总的来说,集成学习算法主要使用两种结构来管理模型与模型之间的关系,一种是并联,另一种是串联(这和物理上串联电路、并联电路似乎有些相似之处)。下面对这两种方式进行简单介绍(其实很好理解)。
1) 并联组织关系
所谓并联,就是训练过程是并行的,几个学习器相对独立地完成预测工作,彼此互不干扰,当所有模型预测结束后,最终以某种方法把所有预测结果合在一起。这相当于学生拿到试卷后先分别作答,彼此不讨论、不参考,当考试完成后,再以某种方式把答案整合在一起。并行式集成学习的典型代表是 Bagging 算法。并行结构示意图如下所示:
图1:集成学习并联结构
2) 串联组织关系
串联结构也很好理解,指的是训练过程是串行的,几个学习器串在一起,通力合作一起来完成预测任务。第一个学习器拿到数据集完成预测,然后把预测结果以及相关数据传递给第二个学习器,第二个学习器也是在完成预测后把结果和相关数据继续传递下去,直至传递到最后一个学习器,这个过程很像是传声筒游戏,第一个人先听一段旋律,然后复述给第二个队员,依次进行下去,直到最后一个人给出歌曲的名字。串行式集成学习的典型代表是 Boosting 算法。串行结构示意图如下所示:
图2:集成学习串联结构
注意:串联与并联的最大区别在于,并联的学习器彼此独立,而串联则是把预测结果传递给后面的学习器。
串联和并联各有各的优势,那么我们到底该如何选择呢?其实,如果各个学习器势均力敌,分不出主次优劣,在这种情况下建议选择并联结构;如果学习器已经有了明确的分工,知道谁负责主攻,谁负责辅助,则可以使用串联结构。
预测结果的方式
不管是串联结构,亦或是并联结构,最终都要输出一个预测结果,而在一个组织结构会有多个学习器,因此就会产生多个预测结果,那么我们要怎么将这些结果整合成一个结果对外输出呢,也就是使用什么方式来整合每个学习器的输出结果呢。对于集成学习算法来说,把多个结果整合成一个结果的方法主要有两种,分别是平均法和投票法,下面分别对它们进行介绍。
1) 平均法
平均法,又分为简单平均法和加权平均法,简单平均法就是先求和然后再求均值,而加权平均则多了一步,即每个学习器通过训练被分别赋予合适的权值,然后求各个预测结果的加权和,最后再求均值。
2) 投票法
投票法,具体分为三种:简单多数投票法、绝对多数投票法和加权投票法。
简单多数投票法就是哪个预测结果占大多数,就把这个结果就作为最终的预测结果;绝对多数投票法就多了一个限制,这个“多数”必须达到半数,比如有共有 6 个学习器,得出同一预测结果的必须达到 3 个及以上,否则就拒绝进行预测。下面重点理解一下加权投票法。
加权投票法,有点类似加权平均,首先给不同的学习器分配权值,其次是查看哪个结果占大多数,注意,此处有一点儿不同,这里的“大多数”是权值相加后再比较得到的大多数,最后以得票最多的作为预测结果。
关于加权投票法举一个简单的例子,比如预测结果为 A 的有 3 个学习器,权值分别为 0.1、0.2 和 0.3,那么结果 A 的票数就为三者之和,即 0.6,而预测结果为 B 的只有 2 个学习器,但权值分别为 0.4 和 0.5,那么结果 B 的票数就为 0.9,也就是结果 B 的票数高于结果 A,最终预测结果就是结果 B。
集成学习实现方法
根据个体学习器生成方式的不同,目前集成学习的实现方式主要分为两种,一种是 Bagging 算法为代表的并行式集成学习方法,其中最典型的应用当数“随机森林算法”;另一种是以 Boosting 算法为代表的串行式集成学习方法,其中应用频率较高的有两个 AdaBoost 算法和 XGBoost 算法。除上述两种主要的方法外,还有一种 Stacking 分层模型集成学习算法。
1) Bagging算法
Bagging 算法又称为“装袋算法”最初由 Leo Breiman 于 1996 年提出,它是并行式学习的典型代表,该算法主要是从数据层面上进行设计。并联结构中的每个学习器所 使用的数据集均采用放回重采样的方式生成,也就是说,每个学习器生成训练集时,每个数据样本都有相同的被采样概率。训练完成后,Bagging 采用投票的方式进行预测。
通过放回重采样的方式来构建样本量相等、且相互独立的数据集,从而在同一算法中训练出不同的模型。Bagging 算法的集成策略比较简单,对于分类问题,一般通过投票法,以多数模型预测结果为最终结果;而对于回归问题,一般采用算术平均法,对所有模型的预测结果做算术平均得到最终结果。
2) Boosting算法
与 Bagging 算法相比,Boosting 是一种串行式集成学习算法,该算法基于错误来提升模型的性能,根据前面分类器分类错误的样本,调整训练集中各个样本的权重来重新构建分类器。
Boosting 可以组合多个弱学习器来形成一个强学习器,从而在整体上提高模型预测的准确率。在模型训练过程中,Boosting 算法总是更加关注被错误分类的样本,首先对于第一个弱学习器预测发生错误的数据,在后续训练中提高其权值,而正确预测的数据则降低其权值,然后基于调整权值后的训练集来训练第二个学习器,如此重复进行,直到训练完成所有学习器,最终将所有弱学习器通过集成策略进行整合(比如加权法),生成一个强学习器。
Boosting 算法的训练过程是呈阶梯状的,后一个学习器会在前一个学习器的基础上进行学习,最终以某种方式进行综合,比如加权法,对所有模型的预测结果进行加权来产生最终的结果。
3) Stacking算法
相比于前两种算法,Stacking 集成学习算法要更为复杂一些,该算法是一种分层模型框架,由 Wolpert 于1992 年提出。Stacking 算法可以分为多层,但通常情况下分为两层,第一层还是由若干个弱学习器组成,当原始训练集经过第一层后,会输出各种弱学习器的预测值,然后将预测结果继续向下一层传递,第二层通常只有一个机器学习模型,该层对第一层的各种预测值和真实值进行训练,从而得到一个集成模型,该模型将根据第一层的预测结果,给出最终的预测结果。
集成学习思想在机器学习算法中应用广泛,它对于提升模型预测准确率,有着不可忽视的作用。
集成学习应用:随机森林算法实现
随机森林(Random Forest,简称RF)是通过集成学习的思想将多棵树集成的一种算法,它的基本单位是决策树模型,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。我们知道,集成学习的实现方法主要分为两大类,即 Bagging 和 boosting 算法,随机森林就是通过【Bagging 算法+决策树算法】实现的。前面已经学习过决策树算法,因此随机森林算法会很容易理解。
决策树和随机森林
下面对决策树算法做简单的回顾:决策树(decision tree)是一个树结构(可以是二叉树或非二叉树)。
1) 决策树
决策树选取了一个特征维度作为判别条件,在数据结构中通常称之为“根节点”,根节点通过 if-else 形成最初的分支,如果这时分类没有完成,刚刚形成的分支还需要继续形成分支,这就是决策树的第一个关键机制:节点分裂。在数据结构中,分支节点通常称为叶子节点,如果叶子节点再分裂形成节点,就称为子树。
叶子节点可能不断分类形成子树,正如 if-else 语句可以不断嵌套 if-else,利用这个机制,一次判别不能完全达到把数据集划分成正类和负类的效果,那就在判别结果中继续进行判别。决策树通过叶子节点不断分裂形成子树,或者说通过 if-else 不断嵌套 if-else,每一次分裂都相当于一次对分类结果的“提纯”,不断重复这个过程,最终就达到分类目标了。
决策树一般有 ID3、ID4.5、CART 这三种算法。其中最常用的是 CART 树(classification and regression tree,即分类回归树算法),它是一棵二分树,在每个节点做出决策时只能选择是或否。CART 树生成的主要思想就是分裂。每个准备分裂的节点,都会从数据集中选择一个最优特征的最优值作为分裂的条件,将数据分成两部分想要了解更多地了解决策树可点击前往《决策树分类算法(if-else原理)》。
2) 随机森林
随机森林,顾名思义,即使用随机的方式建立一个森林,这个森林由很多的决策树组成,并且每一棵决策树之间是相互独立的。如果训练集有 M 个样本,对于每棵数而言,以随机且有放回的方式从训练集中抽取 N 个训练样本(N<M),作为该棵决策树的训练集。除了采用样本随机之外,随机森林还采用了特征随机。假设每个样本有 K 个特征,从所有特征中随机选取 k 个特征(k<=K),选择最佳分割属性作为节点建立 CART 决策树,重复该步骤,建立 m 棵 CART 树,这些树就组成了森林,这也是随机森林名字的由来。随机采样和随机特征选取在一定程度上避免了过拟合现象的发生。
当有一个新的输入样本进入森林时,就让森林中的每一棵决策树分别对其进行判断,看看这个样本应该属于哪一类(对于分类算法而言),然后使用少数服从多数的【投票法】,看看哪一类被选择最多,就预测该样本为哪一类。
举个形象化的例子:森林中召开动物大会,讨论某个动物是狼还是狗,每个树都要独立地发表对这个问题的看法,也就是每一棵树都要投票,并且只能投是或否。依据投票情况,最终得票数最多的类别就是对这只动物的认定结果。在这个过程中,森林中每棵数都是独立地对若干个弱分类器的分类结果进行投票选择,从而组成一个强分类器。
随机森林既可以处理属性为离散值的样本(即分类问题),也可以处理属性为连续值的样本(即回归问题),另外随机森林还可以应用于无监督学习的聚类问题,以及异常点检测。
算法应用及其实现
作为一种新兴的、高度灵活的机器学习算法,随机森林(Random Forest,简称 RF)拥有广泛的应用前景,它在金融、医疗等行业大放异彩,比如银行预测借贷顾客的风险等级,医药行业可以采用随机森林算法来寻找正确的药品成分组合,同时该算法业也可以对病人的既往病史进行分析,这非常有助于确诊病人的疾病。
在 Scikit-Learn 机器学习库中提供了 Bagging 和 Boosting 两种集成学习方法,且都在 ensemble 类库下,包括随机森林算法。除此之外,该类库下还包含了其他几类算法,较为知名有如下几种:
说明 | |
RandomForestClassifier类 | 使用随机森林(Random Forest)算法解决分类问题,随机森林可谓 Bagging 集成学习算法的典型代表,它选择以 CART 决策树算法作为弱学习器,是一种常用的机器学习算法。 |
RandomForestRegressor类 | 使用随机森林算法解决回归问题 |
ExtraTreesClassifier类 | 使用极端随机树(Extra Tree)算法解决分类问题,极端随机树算法可以看作随机森林算法的一种变种,主要原理非常类似,但在决策条件选择时采用了随机选择的策略。 |
ExtraTreesRegressor类 | 使用极端随机树算法解决回归问题。 |
AdaBoostRegressor类 | 使用AdaBoost算法解决分类问题,AdaBoost算法是最知名的Boosting算法之一。 |
AdaBoostRegressor类 | 使用AdaBoost算法解决回归问题。 |
GradientBoostingClassifier类 | 使用Gradient Boosting算法解决分类问题,Gradient Boosting算法常常搭配CART决策树算法使用,这就是有名的梯度提升树(Gradient Boosting Decision Tree,GBDT)算法。 |
GradientBoostingRegressor类 | 使用Gradient Boosting算法解决回归问题。 |
实现:
随机森林算法是集成学习方法的典型代表,该算法具有以下特点:
- 模型准确率高:随机森林既可以处理分类问题,也可以处理回归问题,即使存在部分数据缺失的情况,随机森林也能保持很高的分类精度;
- 能够处理数量庞大的高维度的特征,且不需要进行降维(因为特征子集是随机选择的);
- 能够评估各个特征在分类问题上的重要性:可以生成树状结构,判断各个特征的重要性;
- 对异常值、缺失值不敏感。
当然随机森林算法也存在一些不足,比如:
- 随机森林解决回归问题的效果不如分类问题;
- 树之间的相关性越大,错误率就越大;
- 当训练数据噪声较大时,容易产生过拟合现象。
每种算法各有千秋,在学习的时候,我们要更多的关注每种模型的原理、结构以及数学实现,只有在掌握了这些之后,我们才能提高自己认知能力,当遇到其他算法时,才能做到触类旁通、应对自如。
网格搜索
网格搜索是一项模型超参数优化技术,常用于优化三个或者更少数量的超参数,本质是一种穷举法。对于每个超参数,使用者选择一个较小的有限集去探索。然后,这些超参数笛卡尔乘积得到若干组超参数。网格搜索使用每组超参数训练模型,挑选验证集误差最小的超参数作为最好的超参数。
- 作者:Yinqi Yang
- 链接:https://yangyinqi.top/article/machine-learning-note
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。