机器学习
前面学了一堆的知识(主要都是计算机专业的知识,最近确实学不下去了,改一下学习方向),主要目的还是为了能够给学习人工智能打下一个坚实的基础,之前零零碎碎学过一些知识点也差不多忘完了,所以重头开始学(这篇博客也算是专业课的第一篇博客了,可能内容之类的会有点混乱…)
文章参考:
- 机器学习算法Python机器学习算法入门教程 (biancheng.net)
- 《机器学习》周志华
- 《动手学深度学习》《动手学深度学习》 — 动手学深度学习 2.0.0-beta1 documentation (d2l.ai)
- 大-道-至-简 - 博客园 (cnblogs.com)
- 刘建平Pinard - 博客园 (cnblogs.com)
前言
简单说一下,本科专业选的是人工智能专业,但是刚进入大学真的是什么都不懂(属于是那种软件尽量不要装C盘都不知道的小白),然后稀里糊涂的就开始学什么人工智能导论以及一系列让人懵逼的课程,完了上课也根本不听自己搁下面做其他事(当时真的对这个专业完全没有兴趣,然后感觉听老师讲课也是听天书一样,你试试让一个连算法和数据结构都搞不明白的学生去理解深度学习、决策树…现实吗???)。这期间其实也不是完全摆烂,大一大二就迷迷糊糊的学了点东西(跟着B站的李宏毅老师学了课程,也看了周志华老师的《机器学习》,学过李航的《统计学习方法》,但是因为没有一根“线”将这些知识点串起来,导致学完几乎就忘完),今年因为疫情原因上半年没去学校导致全程在家自学,然后就开始写博客,回头把以前学的东西给整理整理(基本上现在是达到学人工智能的门槛了),然后这段时间也学不进去其他东西了,决定对人工智能这个领域做一些深入的学习(主要还是把以前学了的忘了的有体系的整理一下),之后再学学Tensorflow等框架,毕竟自己的专业课不能一直水着。
我主要就是从一个完全人工智能小白的角度写这篇博客,介绍机器学习和人工智能有啥关系,一系列机器学习算法又有什么意义…需要注意的一点是当今市面上很多教材或者资料使用的术语都不严谨,导致阅读起来会有很多概念上的混淆,这点我在笔记中会注意尽量使用严谨的唯一的名词;
先简单介绍一下人工智能领域主要包含什么,人工智能领域可以简单分为以下三个部分,这三个部分又包含了许多小的方向,每个方向都是极具挑战的

用下面这幅图说明机器学习和人工智能什么关系,我们为什么要学机器学习

可以理解为机器学习是研究人工智能领域的核心方法,我们要步入人工智能领域就一定要学习机器学习;
从广义上来讲,任何关于使用大量数据训练模型的算法的相关研究都可以归纳于机器学习:
数据集:主要分为训练集、验证集和测试集,三者关系参考机器学习干货篇:训练集、验证集和测试集 - 知乎 (zhihu.com)
将训练数据分为训练集和验证集,算法根据训练集训练得到模型(自动),基于验证集上的性能进行模型选择和调参(手动);
用测试集上的判别效果来估计模型在实际使用时的泛化能力;
算法:对某种问题的求解过程,如线性回归、决策树、神经网络….
模型:通过算法最终学到的结果,如决策树算法的模型是一个具有特定值的if-then语句树;
机器学习按照学习形式来分类主要可以分为:
- 有监督学习:学习的数据是带标记的,用于解决
分类任务和回归任务; - 无监督学习:学习的数据不带标记,由计算机根据样本的特征或相关性自行探索规律训练出预测模型,用于解决
聚类任务和降维任务; - 强化学习:根据合理的情况给予“正向激励”和“负向激励”,具有动态规划的思想,旨在通过与环境交互并获取返回进而改进行为的学习过程;
- 深度学习:属于神经网络算法的衍生,旨在研究如何从数据中自动地提取多层特征表示;
一、机器学习
机器学习最主要的一项工作就是“训练模型”,也就是从数据中学得模型的过程,这个过程通过执行某个学习算法来完成
1.机器学习概述
1.1 基本术语
- 数据集:要进行机器学习,首先需要有数据,假如我们有一批关于西瓜的数据(色泽=青绿;根蒂=蜷缩;敲声=浑浊),这样的一对括号内的内容我们称为
一条“记录”或一个“示例”或一个“样本”或一个“特征向量”;色泽、根蒂被称为“属性”,在属性上的取值如“青绿”被称为“属性值”,由属性张成的空间称为“样本空间”、“属性空间”或“输入空间”;一个样本由d个属性描述,则d称为样本的“维数”;一组记录的集合称为一个“数据集”; - 标记空间/输出空间:在有监督学习中,样本x
i对应的标记为yi,我们将拥有标记的样本称为“样例”,而把所有训练样本对应的所有标记的集合称为“输出空间”或“标记空间”;
- 真值:理想概念下被测物体的真实数值;
- 噪声:真值与实际标记(测量值)的差值;
- 偏差:真值与算法获得值的差值;
- 假设空间:假如属性“色泽”有三种取值,“根蒂”有四种取值,“敲声”有四种取值,则假设空间的规模为3 * 4 * 4=48
- 版本空间:假设空间中删除与正例不一致的假设
1.2 任务分类
前言部分简单说了一下机器学习按照学习形式可以大致分为几个部分,这里我们举一些例子来简单说明一下;
1.2.1 有监督学习
监督学习(supervised learning)擅长在“给定输入特征”的情况下预测标签。 每个“特征-标签”对都称为一个样本(example)。 有时,即使标签是未知的,样本也可以指代输入特征(翻译问题,有特征、无标签的机器学习应该属于无监督学习,此处意思大概是对于没有标签的样本我们可以人工标记数据?)。 我们的目标是生成一个模型,能够将任何输入特征映射到标签,即预测。
即使使用简单的描述“给定输入特征的预测标签”,监督学习也可以采取多种形式的模型,并且需要大量不同的建模决策,这取决于输入和输出的类型、大小和数量。
(1)回归问题
回归(regression)是最简单的监督学习任务之一;
当标签取任意数值时,我们称之为回归问题。 我们的目标是生成一个模型,它的预测非常接近实际标签值。
生活中的许多问题都可归类为回归问题。 比如,预测用户对一部电影的评分可以被认为是一个回归问题。总而言之,判断回归问题的一个很好的经验法则是,任何有关“多少”的问题很可能就是回归问题。比如:
- 这个手术需要多少小时?
- 在未来六小时,这个镇会有多少降雨量?
(2)分类问题
这种“哪一个?”的问题叫做分类(classification)问题。 在分类问题中,我们希望模型能够预测样本属于哪个类别(category,正式称为类(class))。
最简单的分类问题是只有两类,我们称之为“二元分类”。当我们有两个以上的类别时,我们把这个问题称为多元分类(multiclass classification)问题(如手写数字识别)。
分类问题的常见损失函数被称为交叉熵;
在回归中,我们训练一个回归函数来输出一个数值; 而在分类中,我们训练一个分类器,它的输出即为预测的类别。
(3)标记问题
图中有一只猫,一只公鸡,一只狗,一头驴,背景是一些树。 取决于我们最终想用我们的模型做什么,将其视为简单分类问题可能没有多大意义。 取而代之,我们可能想让模型描绘输入图像的内容,一只猫、一只狗、一头驴,还有一只公鸡。

标记问题也可以称为多标签分类问题。传统分类问题是将一个样本划分到某一个给定的类别中,这是单标签分类(二分类和多分类都属于此类问题);在生活中,一个样本,被划分到多个类别中,多标签分类就是将一个样本分类到一个类别或多个类别的但标签分类中,是一个大小不定的类别标签集合。
(4)搜索问题
关于搜索问题,我们强调输出结果的顺序,搜索结果的排序十分重要,我们的学习算法需要输出有序的元素子集。
如今,搜索引擎使用机器学习和用户行为模型来获取网页相关性得分。
(5)推荐系统
另一类与搜索和排名相关的问题是推荐系统(recommender system),它的目标是向特定用户进行“个性化”推荐。 例如,对于电影推荐,科幻迷和喜剧爱好者的推荐结果页面可能会有很大不同。 类似的应用也会出现在零售产品、音乐和新闻推荐等等。
在某些应用中,客户会提供明确反馈,表达他们对特定产品的喜爱程度。 例如,亚马逊上的产品评级和评论。在其他一些情况下,客户会提供隐性反馈。例如,某用户跳过播放列表中的某些歌曲,这可能说明这些歌曲对此用户不大合适。
(6)序列学习
以上大多数问题都具有固定大小的输入和产生固定大小的输出,在这些情况下,模型只会将输入作为生成输出的“原料”,而不会“记住”输入的具体内容。
如果输入的样本之间没有任何关系,以上模型可能完美无缺。 但是如果输入是连续的,我们的模型可能就需要拥有“记忆”功能。
序列学习需要摄取输入序列或预测输出序列,或两者兼而有之。 具体来说,输入和输出都是可变长度的序列,例如机器翻译和从语音中转录文本。
常见类型的序列学习有:

1.2.2 无监督学习
(1)聚类问题
没有标签的情况下,我们是否能给数据分类呢?比如,给定一组照片,我们能把它们分成风景照片、狗、婴儿、猫和山峰的照片吗(根据类别对图像进行分类)?同样,给定一组用户的网页浏览记录,我们能否将具有相似行为的用户聚类呢?
(2)主成成分分析
我们能否找到少量的参数来准确地捕捉数据的线性相关属性?比如,一个球的运动轨迹可以用球的速度、直径和质量来描述。
(3)因果关系&概率图模型
我们能否描述观察到的许多数据的根本原因?例如,如果我们有关于房价、污染、犯罪、地理位置、教育和工资的人口统计数据,我们能否简单地根据经验数据发现它们之间的关系?
(4)生成对抗网络
为我们提供一种合成数据的方法,甚至像图像和音频这样复杂的非结构化数据。潜在的统计机制是检查真实和虚假数据是否相同的测试。
1.2.3 强化学习
强化学习问题是一类明确考虑与环境交互的问题,前面介绍的两种模型都被称为离线学习,因为所有的学习都是算法与环境断开后进行的。
与环境交互需要注意以下问题:
- 环境还记得我们以前做过什么吗?
- 环境是否有助于我们建模?例如,用户将文本读入语音识别器。
- 环境是否想要打败模型?例如,一个对抗性的设置,如垃圾邮件过滤或玩游戏?
- 环境是否重要?
- 环境是否变化?例如,未来的数据是否总是与过去相似,还是随着时间的推移会发生变化?是自然变化还是响应我们的自动化工具而发生变化?

当环境可被完全观察到时,我们将强化学习问题称为马尔可夫决策过程(markov decision process)。 当状态不依赖于之前的操作时,我们称该问题为上下文赌博机(contextual bandit problem)。 当没有状态,只有一组最初未知回报的可用动作时,这个问题就是经典的多臂赌博机(multi-armed bandit problem)。
1.2.4 深度学习
本质上,深度学习是神经网络算法的衍生,是总结大量数据的方法,旨在研究如何从数据中自动的提取多层特征元素。
深度学习的一个关键优势是它不仅取代了传统学习管道末端的浅层模型,而且还取代了劳动密集型的特征工程过程。 此外,通过取代大部分特定领域的预处理,深度学习消除了以前分隔计算机视觉、语音识别、自然语言处理、医学信息学和其他应用领域的许多界限,为解决各种问题提供了一套统一的工具。
1.3 一个简单的例子
我们这里举一个简单的例子来感受一下机器学习的整个过程,当然并不是所有的机器学习都是这样的模式(针对不同的机器学习算法有不同的学习流程),这里只是一个比较经典的例子;
从直观感受来说,机器学习的目的就是让机器具备一个寻找函数的能力;
从具体的实践意义来说,机器学习是
利用大量数据训练出一个最优模型,再利用此模型预测出其他数据的一种方法,那么根据这个定义可以简单的将机器学习分为训练阶段和预测阶段;
我们将训练过程分为以下几个阶段(假如我们的任务是找出一个function能够拟合red curve这条曲线):

根据domain knownledge写出含有未知参数的function(称为假设函数/模型函数)
- 粗略根据red curve选择用hard/soft sigmoid/Relu拟合写出function;
定义损失函数(又称为目标函数、代价函数):损失函数就像一个度量尺,反映“假设函数”训练结果的优劣,从而做出相应的优化策略(该过程在训练集上进行);
Optimization:介于假设函数和损失函数之间的桥梁,主要目的是调整假设函数中的参数以减小损失函数中的损失(此处选择了优化器之后训练过程中会自动进行);
模型评估、修改模型:将得到的模型在验证集/测试集上进行测试,对function进行修改(修改模型往往来自对问题的理解,这里指的是手动修改模型)
增加数据提高function的弹性;
增加激活函数的层数提高表征能力更好地拟合复杂曲线;
上述过程只是概念上的训练过程,与实际使用代码进行模型的训练还是有一些差异的,可以参考 https://www.aliyundrive.com/s/jcgTZ6EKjCd 这篇PDF了解如何使用代码训练一个简单的手写数字识别模型;
2.机器学习算法
本章主要介绍一些传统的机器学习算法
机器学习的目的是设计、分析一些让计算机可以自动“学习”的算法,最终让计算机拥有像人类一样的智慧,甚至于超越人类。这一结果的实现,要得益于机器学习算法,它提供了一整套解决问题的方案和思路,即先做什么、再做什么、最后做什么(机器学习算法是机器学习的“火车头”)。
2.1 线性回归算法
Q:函数(function)和方程(equation)的区别?
参考资料函数(数学术语)_百度百科 (baidu.com)| 方程(数学术语)_百度百科 (baidu.com)
A:很多时候其实我们都没有区分这两者的概念(毕竟x+y+1=0和y=-x-1的图象是完全一样的),硬要说区别的话,方程表示的思想是未知数之间相互平衡制约的关系,函数表示的是变量与因变量之间一一对应的映射关系;在很多机器学习的教程中是完全没有区分这两个概念的,个人认为这不是一个好的习惯,严格按照定义来说的话在机器学习中应该称呼为函数而非方程;
线性回归算法即使用线性模型来解决回归问题的算法,其中“线性”表示线性模型,“回归”表示回归问题(可以理解为预测真实值的过程,如预测房价、股价,简单来说就是选择一条函数曲线使其很好地拟合已知数据且很好地预测未知数据);
线性回归算法主要用于解决回归问题(即预测连续值的问题),满足这样要求的数学模型被称为“线性回归模型”。最简单的线性回归模型是我们熟知的一次函数,表达式为y=kx+b,其函数图像是二维平面中的一条直线,多维/多元线性回归可以用函数表达式y=a0+a1x1+a2x2+…+anxn表示;
线性回归模型表示一个函数,其函数图像是一条直线(不仅限于二维平面),通过寻找输入变量系数(k)的特定权重,拟合输入变量(x)和输出变量(y)之间的关系

2.1.1 线性回归的模型函数
一元线性回归:回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示(两者之间是线性关系);
多元线性回归:回归分析中,包括两个或两个以上的自变量,且因变量和自变量之间是线性关系;
线性回归的模型函数如下(当n=1的时候表示是一元线性回归)

我们默认x0等于1,使用矩阵形式化简可得

2.1.2 线性回归的损失函数
之前也说过,如果严格按照模型的定义来说的话其实上面我们介绍的只能称为“假设函数”(称之为“模型函数”无疑是最明智的选择),但在不引起混淆的前提下,我们可以称“假设函数”为模型;
拥有了最基础的模型之后我们就要根据已知的数据集在假设空间中选出最合适的线性回归模型,这一步需要借助损失函数(用来估量模型的预测值 f(x)与真实值 Y的不一致程度,损失函数越小,模型的效果就越好)
线性回归中常用的损失函数是均方误差(至于为什么要使用均方误差作为线性回归的损失函数可以参考 https://zhuanlan.zhihu.com/p/48205156),其代数表示如下:

2.1.3 损失函数的最小化
通过定义损失函数,我们将问题转化为找出参数 θ 使得损失函数最小,求解机器学习算法的模型参数(这里所说的求解就是损失函数最小化时的模型参数)常用的两种方法分别是:
梯度下降法:是一种搜索算法,先给 θ 赋初值,再根据使 J(θ) 更小的原则对 θ 进行修改,直到J(θ) 达到最小,求得此时的 θ ;求解方法参考梯度下降(Gradient Descent)小结 - 刘建平Pinard - 博客园 (cnblogs.com)
最小二乘法:是一种方程法,要使 J(θ) 最小,就对 θ 求导,使导数等于 0,求得此时的 θ;求解方法参考最小二乘法小结 - 刘建平Pinard - 博客园 (cnblogs.com)
最小二乘法通过使得推导结果为0直接求得极值,一步到位;
梯度下降法是将推导结果一步步代入迭代公式中,逐步进行,适合特征变量很多的情况使用;
2.1.4 损失函数的正则化
为了解决过拟合的问题,需要在损失函数中引入正则化,正则化参考什么是正则化、如何理解正则化以及正则化的作用? (360doc.com)
(1)Lasso回归
线性回归的L1正则化通常称为Lasso回归,它和一般线性回归的区别是在损失函数上增加了一个L1正则化的项,L1正则化的项有一个常数系数

(2)Ridge回归
L2正则化通常称为Ridge回归,它和一般线性回归的区别是在损失函数上增加了一个L2正则化的项,和Lasso回归的区别是Ridge回归的正则化项是L2范数,而Lasso回归的正则化项是L1范数

(3)Elasticnet回归
ElasticNet回归是对Lasso回归和岭回归的一个综合,它的惩罚项是L1范数和L2范数的一个权衡,正则化后的损失函数为

其中,α和ρ均为超参数,α≥0,1≥ρ≥0。而ρ影响的是性能下降的速度,因为这个参数控制着两个正则化项之间的比例;
Lasso回归(缩减系数):可以使得一些特征系数变小,甚至一些绝对值较小的系数直接变为零,从而增强模型的泛化能力。因此很适合与参数数目缩减与参数的选择,作为用来估计稀疏参数的线性模型。当进行模型选择的时候,如果特征特别多,需要进行压缩时,就可以选择Lasso回归。
Ridge回归(平滑系数):是在不抛弃任何一个特征的情况下,限制(缩小)了回归系数,使得模型相对而言比较复杂。和Lasso回归相比,这会使得模型保留的特别多,导致解释性差。
ElasticNet回归:则是对上面两个进行了权衡。实际上,L1L1正则项可以得到稀疏的θ⃗ θ→,L2L2正则项则可以得到比较小的θ⃗ θ→,ElasticNet回归就是将这两个结合着用。
Q_1:如何求解正则化之后的损失函数?
A:参考Lasso回归算法: 坐标轴下降法与最小角回归法小结 - 刘建平Pinard - 博客园 (cnblogs.com);
Q_2:为什么正则化可以防止过拟合?
A:过拟合是指模型在训练数据上表现很好,但在未见过的新数据上表现较差的情况。正则化的主要目标是防止模型变得过于复杂,以至于过多地适应了训练数据中的噪声或细微变化,而忽略了真正的模式。
正则化能够解决过拟合问题的主要原因如下:
- 惩罚复杂性: 正则化通过向模型的损失函数添加一个额外的项,通常是模型参数的平方和(L2正则化)或绝对值和(L1正则化),以惩罚模型的复杂性。这个额外的惩罚迫使模型更加趋向于简单的参数配置,减少了模型对训练数据中噪声的过度拟合。因此,正则化有助于控制模型的复杂性,避免它变得过于灵活。
- 权衡偏差和方差: 过拟合问题通常与高方差(模型对数据的敏感度)和低偏差(模型对真实模式的忽视)相关。正则化有助于权衡这两者。通过控制模型的复杂性,正则化可以减少方差,使模型在新数据上的泛化性能更好。与此同时,它也会引入一些偏差,但这种偏差通常是可接受的,因为它能够提高模型的整体性能。
- 特征选择: 在L1正则化中,正则化项的作用不仅在于惩罚参数的大小,还可以促使某些参数变为零,从而实现特征选择。这意味着模型可以自动选择最重要的特征,而忽略不重要的特征,进一步减少了过拟合的风险。
Q_3:深度学习中的Dropout也是一种正则化手段吗?
A:Dropout 是一种用于正则化神经网络的技术。它被设计用来减轻神经网络的过拟合问题,类似于传统的 L1 和 L2 正则化。
Dropout 的工作原理是在训练过程中随机地丢弃(或 “dropout”)神经网络中的一些神经元,意味着在每个训练迭代中,一部分神经元的输出被置为零。这个丢弃的比例是一个超参数,通常设置在0.2到0.5之间。当神经元被丢弃时,它们不参与前向传播和反向传播过程,因此它们的权重不会被更新。这导致了网络的每个训练迭代都会看到不同的子网络,这有助于减轻过拟合。
Dropout 的效果类似于在训练过程中对神经网络引入噪声,使得网络不会过于依赖任何一个特定的神经元或神经元组合。这有助于使网络更加鲁棒,能够更好地泛化到未见过的数据。
2.1.5 线性回归的拓展
当数据是非线性的形式时,使用线性回归很难拟合该函数,此时可以使用多项式回归(注意不是多元回归),线性模型的函数为

若此时xn的幂次为高次(而非仅仅是一次),则该模型就成为了多项式线性回归模型,比如有两个特征的二次多项式回归模型

2.1.6 总结
线性回归的优点:
建模速度快,不需要很复杂的计算,在数据量大的情况下依然运行速度很快;
可以根据系数给出每个变量的理解和解释;
对异常值很敏感;
线性回归的缺点:
- 不能很好的拟合非线性数据,所以需要先判断变量之间是否线性相关;
2.2 逻辑回归算法
线性回归既可以用于回归任务也可以用于分类任务(线性回归+阈值),但是作为分类器线性回归的性能确实很低,所以诞生了逻辑回归;
逻辑回归主要用于解决二分类问题(逻辑回归前提是假设数据服从伯努利分布),逻辑回归是一种广义的线性回归;
逻辑回归有两个重要的假设条件:
(1)假设数据服从伯努利分布;
(2)假设模型的输出值是样本为正例的概率;
那么基于这两个假设可以分别得到输出类别为1和0的后验概率估计(即逻辑回归模型函数的意义):

2.2.1 逻辑回归的模型函数
简单来说逻辑回归就是在线性回归的理论基础上引入非线性因素,我们熟知的线性回归模型为

引入sigmoid函数做转换得到逻辑回归的假设函数形式如下

其中x是样本输入,0是待求参数
2.2.2 逻辑回顾的损失函数
因为逻辑回归不是连续的,这里使用最大似然法推导逻辑回归的损失函数,我们已经知道逻辑回归模型函数h0(x)的意义,将这两个式子写成一个式子得到

推导出的损失函数形式如下

该损失函数也被称为“对数似然函数”,也称为“交叉熵”、“香农熵”,可以参考资料(23条消息) 交叉熵(Cross-Entropy)_rtygbwwwerr的博客-CSDN博客_cross entropy
2.2.3 损失函数的最小化
对于逻辑回归而言使用传统的最小二乘法求解是不合适的,常用梯度下降法,坐标轴下降法,等牛顿法等,具体求解过程参考【机器学习笔记】:从零开始学会逻辑回归(一) - 知乎 (zhihu.com)
2.2.4 总结
优点:
直接对分类可能性进行建模,无需实现假设数据分布,避免了假设分布不准确所带来的问题;
形式简单,便利的观测样本概率分数,模型的可解释性非常好,特征的权重可以看到不同的特征对最后结果的影响;
训练速度较快,分类速度很快;
内存占用少;
缺点:
一般准确率不是很高,因为形式非常的简单,很难去拟合数据的真实分布;
当特征空间很大时,逻辑回归的性能不是很好;
很难处理数据不平衡的问题;
2.3 KNN算法
KNN算法全称为K最近邻(k-Nearest Neighbor)算法,是一种分类算法(实际上也可以用于回归,只是效果不太好),其核心思想为:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性(简单理解就是近朱者赤近墨者黑);
举例来说,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,因此绿色圆被赋予红色三角形那个类;如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类

简单介绍一下KNN算法的实现步骤(这只是一个框架,具体的实现后面会介绍):
1)算距离:计算测试数据与各个训练数据之间的距离,按照距离的递增关系进行排序,此处的距离是欧氏距离,n维空间下欧式距离计算公式如下

2)找邻居:选取(圈定)距离最小的K个点,作为待分类样本的近邻;
3)做分类:确定前K个点所在类别的出现频率,返回前K个点中出现频率最高的类别作为测试数据的预测分类(根据这K个近邻中的大部分样本所属的类别来决定待分类样本该属于哪个分类);
实际上KNN算法既可以用作回归任务也可以用作分类任务,KNN做分类的时候使用的决策方式是多数表决法(最近的K个样本中类别数最多的类别作为预测的类别),KNN做回归的时候决策方法一般是选择平均法(最近的K个样本的输出的平均值作为回归预测值),两者的区别不是很大,这里主要对KNN算法做分类进行讲解;
2.3.1 KNN算法三要素
在上面已经简单的介绍了一下KNN算法的实现步骤,而这三个因素也是KNN算法的核心所在:K值的选取、距离度量方式以及分类决策规则
(1)K值的选择
因为KNN算法中只有一个超参数K,因此不需要像前面的回归算法一样求解最小化损失函数等操作,常规的求解方法是从较小的K值开始通过交叉验证选择一个合适的K值
k越小,即使用较小的领域中的样本进行预测,训练误差会减小,但模型会很复杂,以至于过拟合;
k越大,即使用较大的领域中的样本进行预测,训练误差会增大,模型会变得简单,容易导致欠拟合;
(2)距离度量方式
最常用的是欧氏距离,对于两个n维向量x和y,两者的欧式距离为

曼哈顿距离表达式为

闵可夫斯基距离表达式为

(3)决策规则
对于分类KNN来说可以选择多数表决法、加权多数表决法;对于回归KNN来说可以选择平均值法、加权平均值法;
一般使用的决策方式都是多数表决法;
2.3.2 KNN算法的实现
KNN算法的基本原理很简单,使用代码来实现KNN存在多种选择,这里主要介绍scikit-learn库中使用的几种实现方式(可以理解为KNN算法的几种分支);
(1)蛮力法
蛮力法顾名思义就是计算出训练集中所有样本与预测样本之间的距离,然后在最小的K个样本中采用多数多数表决法做出决策,当然这种方式只适合拥有少量样本的简单模型使用;
(2)KD树
KD树就是K个特征维度的树,注意这里的K不代表最近的K个样本,而是代表样本特征的维数;
KD树并没有像蛮力法一样一来就尝试对测试样本进行分类,而是先对训练集进行了建模,建立的模型就是KD树;
KD树的建立采用的是从m个样本的n个特征中,分别计算n个特征的取值的方差,用方差最大的第k个特征nk作为根节点,选择特征nk的取值的中位数对应的样本作为划分点:
- 对于所有第k维特征的取值小于n
k中位数的样本划入左子树; - 对于所有第k维特征的取值大于等于n
k的中位数的样本划入右子树; - 对于左子树和右子树,使用上述相同的方法寻找方差最大的特征作为根节点,递归生成KD树;
举个例子,这里有6个二维样本{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}:
- 6个数据点在x,y维度上的数据方差分别为6.97,5.37,所以在x轴上方差更大,所以用x维的特征建树;
- 根据x维上的值将数据排序,6个数据的中值(所谓中值,即中间大小的值)为7,所以划分点的数据是(7,2);
- 分割超平面x=7将整个空间分为两部分:x<=7的部分为左子空间,包含3个节点={(2,3),(5,4),(4,7)};另一部分为右子空间,包含2个节点={(9,6),(8,1)};
- 用同样的办法划分左子树的节点{(2,3),(5,4),(4,7)}和右子树的节点{(9,6),(8,1)},最终得到的KD树如下

生成了KD树之后就可以寻找测试样本的最近邻:对于一个目标点,我们首先在KD树里面找到包含目标点的叶子节点。以目标点为圆心,以目标点到叶子节点样本实例的距离为半径,得到一个超球体,最近邻的点一定在这个超球体内部。然后返回叶子节点的父节点,检查另一个子节点包含的超矩形体是否和超球体相交,如果相交就到这个子节点寻找是否有更加近的近邻,有的话就更新最近邻。如果不相交那就简单了,我们直接返回父节点的父节点,在另一个子树继续搜索最近邻。当回溯到根节点时,算法结束,此时保存的最近邻节点就是最终的最近邻。
当然上面的描述可能令人眼花,这里举例对点(2,4.5)寻找最近邻:
先进行二叉查找,先从(7,2)查找到(5,4)节点,在进行查找时是由y = 4为分割超平面的,由于查找点为y值为4.5,因此进入右子空间查找到(4,7),形成搜索路径<(7,2),(5,4),(4,7)>,但 (4,7)与目标查找点的距离为3.202,而(5,4)与查找点之间的距离为3.041,所以(5,4)为查询点的最近点; 以(2,4.5)为圆心,以3.041为半径作圆,如下图所示。可见该圆和y = 4超平面交割,所以需要进入(5,4)左子空间进行查找,也就是将(2,3)节点加入搜索路径中得<(7,2),(2,3)>;于是接着搜索至(2,3)叶子节点,(2,3)距离(2,4.5)比(5,4)要近,所以最近邻点更新为(2,3),最近距离更新为1.5;回溯查找至(5,4),直到最后回溯到根结点(7,2)的时候,以(2,4.5)为圆心1.5为半径作圆,并不和x = 7分割超平面交割,如下图所示。至此,搜索路径回溯完,返回最近邻点(2,3),最近距离1.5;
要选择K个最近邻则循环K次该算法,得到测试样本的K个最近邻,然后根据多数表决法的到最后的预测;
(3)球树
球树是在KD树的基础上改造而来,其分割块不是超矩形体而是超球体

具体的建树过程和寻找最近邻的方法这里就不再赘述,感兴趣可以参考K近邻法(KNN)原理小结 - 刘建平Pinard - 博客园 (cnblogs.com)
2.3.3 总结
KNN算法特点在于“非参”和“惰性”,其中非参表示KNN建立的模型结构是根据数据决定的而不会对对数据做出任何假设(与之相对的是线性回归中我们总假设数据是一条直线),惰性表示KNN算法不需要像逻辑回归一样对数据进行大量训练才能得到算法模型,KNN算法没有明确的训练数据的过程;
优点:
思想简单,理论成熟,易于理解,易于实现,既可以用来做分类也可以用来做回归(但是KNN的回归效果不好,很少用);
无需估计参数,即无数据输入假定(对数据没有假设),惰性的,无需训练(或者说模型的训练过程非常快);
精度高,预测效果好,对异常值不敏感;
特别适合于多分类问题(multi-modal,对象具有多个类别标签), kNN比SVM的表现要好;
缺点:
计算复杂度高:必须对数据集中的每个数据计算距离值,计算量大,时间开销大,预测阶段可能很慢;
空间复杂度高:必须保存全部数据集,存储空间需求大,需要大量的内存;
对于样本分类不均衡的问题会产生误判,即对样本容量较小的类域很容易产生误分;
输出的可解释性不强,无法给出任何数据的基础结构信息,无法知晓平均实例样本和典型实例样本具有什么特征;
2.4 朴素贝叶斯
(这章对于概率论的要求比较高,可先自行学习大学《概率论与数理统计》课程)
朴素贝叶斯是有监督学习的一种分类算法,基于“贝叶斯定理实现”和特征条件独立假设,而贝叶斯定理基于概率论和统计学实现;
下面先简单梳理一下概念:
- 贝叶斯分类器:一类分类算法的总称,这类算法以贝叶斯定理为基础;
- 朴素贝叶斯:全称为朴素贝叶斯分类器(NBC),是贝叶斯分类器中最简单、最常见的分类方法,该算法以自变量之间的独立性和连续变量的正态性假设为前提;
2.4.1 贝叶斯定理
贝叶斯的思想有点类似于逆向思维,主要用于求现实任务中难以直接获得的概率(逆概),贝叶斯公式表述如下

该公式表示在B事件发生的条件下A事件发生的条件概率,等于A事件发生条件下B事件发生的条件概率乘以A事件的概率,再除以B事件发生的概率。公式中,P(A)也叫做先验概率,P(A/B)叫做后验概率;
条件概率是指事件A在另外一个事件B已经发生条件下的发生概率。条件概率表示为:P(A|B),读作“在B条件下A的概率”。若只有两个事件A和B,那么

2.4.2 朴素贝叶斯的模型函数
朴素贝叶斯分类器采用了“属性条件独立性假设”:假设所有属性相互独立。基于属性条件独立性假设,贝叶斯公式可重写为

其中,d为属性数目,xi为x在第i个属性上的取值;
朴素贝叶斯分类器的训练过程就是基于训练集D来估计类先验概率P(c),并为每个属性估计条件概率P(x
i∣c)
2022/8/10 这章确实因为概率论的原因自己学不下去了,暂时放置一段时间;
2.5 决策树
如果完全不了解决策树我们可以先看这个视频[5分钟学算法] #03 决策树 小明毕业当行长_哔哩哔哩_bilibili
决策树算法既可以作为分类算法,也可以作为回归算法,同时也特别适合集成学习;
决策树算法是一类算法的集合,具体的常用的决策树算法有C4.5和CART算法(以基尼系数为核心);
决策树(decision tree)是一个树结构(可以是二叉树或非二叉树,二叉树并不是强制要求):
- 每个非叶节点表示一个特征属性上的测试(特征);
- 每个分支代表这个特征属性在某个值域上的输出(特征值);
- 每个叶节点存放一个类别(分类结果);
使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。

决策树的构造算法
构造决策树的关键步骤是选择分裂属性(也就是我们常说的分类标准)。所谓分裂属性就是在某个节点处按照某一特征属性的不同划分构造不同的分支,其目标是让各个分裂子集尽可能地“纯”。尽可能“纯”就是尽量让一个分裂子集中待分类项属于同一类别。分裂属性分为三种不同的情况:
属性是离散值且不要求生成二叉决策树。此时用属性的每一个划分作为一个分支;
属性是离散值且要求生成二叉决策树。此时使用属性划分的一个子集进行测试,按照“属于此子集”和“不属于此子集”分成两个分支;
属性是连续值。此时确定一个值作为分裂点split_point,按照x>split_point和x<=split_point生成两个分支(在没有具体的切割要求下,一般选择的split_point都是平均数)
决策树构建步骤(即选择具体的构造算法构造决策树,详细过程可以参考视频[5分钟学算法] #03 决策树 小明毕业当行长_哔哩哔哩_bilibili这个视频介绍的是CART的构建过程):
1.将所有的特征看成一个一个的节点;
2.遍历所有特征,遍历到其中某一个特征时:遍历当前特征的所有分割方式,找到最好的分割点,将数据划分为不同的子节点,计算划分后子节点的纯度信息;
3.在遍历的所有特征中,比较寻找最优的特征以及最优特征的最优划分方式,选择纯度最高的划分方式对当前数据集进行分割操作;
4.对新的子节点继续执行2-3步,直到每个最终的子节点都足够纯;
决策树算法构建的停止条件:
1.当子节点中只有一种类型的时候停止构建(会导致过拟合);
2.当前节点种样本数小于某个值,同时迭代次数达到指定值,停止构建,此时使用该节点中出现最多的类别样本数据作为对应值(比较常用);
2.5.1 决策树的构造算法
(1)ID3算法
信息熵:描述信源的不确定程度 —— 越不确定的事物它的熵就越大,随机变量X的熵的表达式如下:

其中n代表X的n种不同的离散取值,pi代表了X取值为i的概率,log是为以2或者e为底的对数,例题可以参考决策树算法原理(上) - 刘建平Pinard - 博客园 (cnblogs.com);
除了单个变量X的信息熵外,还可以推广到多个变量的联合熵,如变量X和Y的联合熵表达式

进而可以从联合熵得到条件熵的表达式H(X|Y),类似于条件概率,度量了在条件Y下X的不确定性

ID3算法用信息增益来判断当前节点应该用什么特征来构建决策树,信息增益越大则越适合用来分类,信息增益的表达式为H(X)-H(X|Y)也就是X在Y条件下的不确定性的减少程度;
上述概念的关系可以用下图表示

ID3算法就是利用信息增益大小来判断当前节点应该用什么特征来构建决策树,用计算出的信息增益最大的特征来选择决策树当前节点;
熟悉ID3的构造算法后,就可以构建决策树了,构建过程这里不做阐述,参考决策树算法原理(上) - 刘建平Pinard - 博客园 (cnblogs.com)
ID3算法存在诸多不足,如不能用于连续特征、对于缺失值的情况没有做考虑、没有考虑过拟合的问题、用信息增益作为标准容易偏向取值较多的特征等,于是出现了ID3算法的改进 —— C4.5算法
(2)C4.5算法
针对ID3无法处理连续化特征,C4.5将连续的特征离散化,离散化过程这里不做赘述,详情参考决策树算法原理(上) - 刘建平Pinard - 博客园 (cnblogs.com)
针对ID3用信息增益作为标准容易偏向取值较多的特征,C4.5引入信息增益比 —— 信息增益和特征熵的比值,表达式为

其中D为样本特征输出的集合,A为样本特征,特征熵的表达式为

其中n为特征A的类别数,Di为特征A的第i个取值对应的样本个数,|D|为样本个数
信息增益比为什么能够解决问题?因为对于特征取值多对应的特征熵就越大,作为分母可以校正分子的偏向问题;
如何处理ID3缺失值的问题呢?处理缺失值主要分为两种情况:
- 在样本某些特征缺失的情况下选择划分的属性;
- 选定了划分属性,对于在该属性上缺失特征的样本的处理;
对于第一种情况,C4.5将数据分为两部分,一部分是有特征值的数据,一部分是没有特征值的数据,将两部分数据辅助权重求信息增益比;
对于第二种情况,可以将缺失特征的样本同时划分入所有的子节点,将该样本的权重按各个子节点样本的数量比例来分配;
C4.5引入正则化系数进行初步剪枝处理过拟合问题;
C4.5仍然存在一些不足:
由于决策树算法非常容易过拟合,因此对于生成的决策树必须要进行剪枝。剪枝的算法有非常多,C4.5的剪枝方法有优化的空间。思路主要是两种,一种是预剪枝,即在生成决策树的时候就决定是否剪枝。另一个是后剪枝,即先生成决策树,再通过交叉验证来剪枝。
C4.5生成的是多叉树,即一个父节点可以有多个节点,多时候,在计算机中二叉树模型会比多叉树运算效率高;
C4.5只能用于分类,如果能将决策树用于回归的话可以扩大决策树算法的使用范围;
C4.5由于使用了熵模型,里面有大量的耗时的对数运算,如果是连续值还有大量的排序运算;
(3)CART算法
详细关于CART算法的介绍参考决策树算法原理(下) - 刘建平Pinard - 博客园 (cnblogs.com)
ID3算法中使用的是信息增益选择特征,C4.5算法中采用信息增益比来选择特征,两者都是基于信息论的熵模型,涉及大量的对数运算,而CART算法采用基尼系数代替C4.5的信息增益比;
基尼系数代表模型的“不纯度”,基尼系数越低则不纯度越低则特征越好,这与信息增益(比)相反;
假设某个分类问题种有K个类别,其中第k个类别的概率为pk,则基尼系数的表达式为

假设给定样本D,有K个类别,其中第k个类别的数量为Ck,则样本D的基尼系数表达式为

假设给定样本D,根据某个特征A的某个特征值将D分为D1和D2两部分,则在特征A的条件下D的基尼系数表达式为

基尼系数可以作为熵模型的一个近似替代,二分类问题中的基尼系数和熵之半的曲线如下所示

CART算法使用基尼系数选择决策树的特征,同时CART算法每次仅对某个特征的值进行二分,所以CART分类树一定是一个二叉树(ID3和C4.5不一定是二叉树)
CART算法相较于C4.5的另一个特点是既可以做回归也可以做分类,回归树与分类树的区别在于样本的输出:
- 如果样本的输出是离散值则是一棵分类树;
- 如果样本的输出是连续值则是一棵回归树;
当决策树建立后,CART分类树采用叶子节点中概率最大的类别作为当前节点的预测类别,CART回归树用最终叶子的均值或中位数来预测输出结果;
2.5.2 决策树的剪枝处理
剪枝是决策树算法应对“过拟合”的主要手段;
在建立决策树的过程中为了尽可能正确的分类训练样本,划分结点的过程将不断重复导致决策树的分支过多(构建的决策树过于具体了),此时可以通过主动去掉一些分支来降低过拟合的风险;
决策树的剪枝主要分为:
- 预剪枝:在决策树的生成过程中对每个结点在划分前进行估计,若当前结点的划分不能带来决策树泛化性能的提升则停止划分并将当前结点标记为叶结点;
- 后剪枝:从训练集中生成一棵完整的决策树后,自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化性能的提升则将该子树替换为叶结点;
至于如何判断决策树的泛化性能是否有提升可以使用验证集进行性能评估;
更加详细的剪枝策略这里不再赘述,可以参考《机器学习》周志华P80-P83;
2.5.3 总结
我们介绍了三种决策树算法,下面给出三者的对比

当然决策树算法并不仅仅只有这三种,还有利用一组特征来做分类决策的多变量决策树,它选择了最优的一个特征线性组合来做决策,代表算法是OC1(感兴趣可以自学);
决策树算法的优点(参考自决策树算法原理(下) - 刘建平Pinard - 博客园 (cnblogs.com)):
简单直观,生成的决策树很直观。
基本不需要预处理,不需要提前归一化,处理缺失值。
使用决策树预测的代价是O(log2m)O(log2m)。 m为样本数。
既可以处理离散值也可以处理连续值。很多算法只是专注于离散值或者连续值。
可以处理多维度输出的分类问题。
相比于神经网络之类的黑盒分类模型,决策树在逻辑上可以得到很好的解释
可以交叉验证的剪枝来选择模型,从而提高泛化能力。
对于异常点的容错能力好,健壮性高。
决策树算法的缺点:
决策树算法非常容易过拟合,导致泛化能力不强。可以通过设置节点最少样本数量和限制决策树深度来改进。
决策树会因为样本发生一点点的改动,就会导致树结构的剧烈改变。这个可以通过集成学习之类的方法解决。
寻找最优的决策树是一个NP难的问题,我们一般是通过启发式方法,容易陷入局部最优。可以通过集成学习之类的方法来改善。
有些比较复杂的关系,决策树很难学习,比如异或。这个就没有办法了,一般这种关系可以换神经网络分类方法来解决。
如果某些特征的样本比例过大,生成决策树容易偏向于这些特征。这个可以通过调节样本权重来改善。
2.6 感知机
感知机模型是一种古老的分类模型,尽管它的泛化能力不强,但是它作为之后神经网络、支持向量机的基础,其原理值得好好学习;
使用感知机的前提是数据是线性可分的且只能处理二分类问题(二维空间能找到一条直线,三维空间能找到一个超平面,将所有的二元类别隔离开);
2.6.1 感知机的模型函数
假设有m个样本,每个样本有n个特征且对应一个二元类别输出{1,-1}

感知机的模型是尝试找到这样的一个超平面

能够将1和-1两种类别的样本全部分开(感知机模型往往有多个解,因为数据线性可分对应的分类超平面往往不止一个),使用向量表示上述超平面就是(其中·表示内积)

进而定义感知机的模型函数为

其中

2.6.2 感知机的损失函数
为了便于定义损失函数,将满足 θ∙x>0 的样本类别输出值取为1,满足 θ∙x<0 的样本类别输出值取为-1,这样取值的好处是只要是正确分类的样本都满足 y·θ∙x>0,只要是错误分类的样本都满足 y·θ∙x<0;
对于每一个误分类的样本i,到超平面的距离是(其中||θ||2为L2范数)

假设所有误分类点的集合为M,则所有误分类点到超平面的距离之和为

当然这只是初步的损失函数,这个损失函数并不能真正反映点到超平面的距离(因为当分子成比例增长的时候分母同样成倍增长,我们称之为函数间隔)这里可以做一些化简(具体怎么化简的参考感知机原理小结 - 刘建平Pinard - 博客园 (cnblogs.com))得到最终的损失函数(称为几何间隔,这是点到超平面真正的距离)

2.6.3 损失函数的优化
损失函数的优化目标是:误分类的所有样本到超平面的距离之和最小
感知机的损失函数常用的优化方法是梯度下降法或拟牛顿法,注意普通的基于所有样本的梯度和均值的批量梯度下降法是行不通的,因为感知机的损失函数中只有误分类集合M中的样本才能参与损失函数的优化,因此这里只能采用随机梯度下降或者小批量梯度下降(详情参考梯度下降(Gradient Descent)小结 - 刘建平Pinard - 博客园 (cnblogs.com))
感知机模型采用的是随机梯度下降,即我们每次仅需要使用一个误分类点来更新梯度,具体步骤这里不再赘述;
感知机算法的整体执行步骤如下:
- 算法的输入是m个n维特征的二元样本,输出是分离超平面的模型系数θ向量;
- 定义所有x
0为1,选择θ向量的初值和步长α的初值。可以将θ向量置为0向量,步长设置为1; - 在训练集中选择一个误分类点;
- 对θ向量进行一次随机梯度下降的迭代;
- 检查训练集里是否还有误分类的点,如果没有,算法结束,此时的θ向量即为最终结果;如果有,折回第二步再次执行;
Q:随机梯度下降和梯度下降有什么区别?
A:随机梯度下降(Stochastic Gradient Descent,SGD)是一种用于优化机器学习模型的迭代优化算法。它是梯度下降算法的一种变种,用于寻找损失函数的最小值,以便调整模型参数以最好地拟合训练数据。
与传统的梯度下降不同,SGD 在每一次迭代中只使用训练数据集中的一个随机样本(或者是一个小批量随机样本)来估计梯度,然后更新模型参数。这种随机性使得SGD在处理大规模数据集时更加高效,因为它不需要计算整个数据集的梯度,而只需计算一个样本或小批量样本的梯度。
SGD的迭代过程如下:
- 随机选择一个训练样本或小批量样本。
- 计算该样本的损失函数关于模型参数的梯度。
- 使用梯度信息来更新模型参数,通常按照以下方式:新参数 = 旧参数 - 学习率 * 梯度。
- 重复步骤1至3,直到达到预定的迭代次数或收敛条件。
SGD的主要优点包括:
- 更高的计算效率,特别适用于大规模数据集。
- 在训练过程中引入了随机性,有助于逃离局部最小值,可能更容易收敛到全局最小值。
然而,SGD也有一些缺点:
- 随机性可能导致收敛速度不稳定,使得损失函数的下降路径不够平滑。
- 学习率的选择通常需要仔细调整,过小的学习率可能导致收敛缓慢,而过大的学习率可能导致不稳定的收敛。
为了应对SGD的一些问题,还有一些SGD的改进版本,如带动量的SGD、Adagrad、RMSprop和Adam等,它们对学习率进行自适应调整,提高了收敛速度和稳定性。
2.7 支持向量机
支持向量机(SVM)算法在分类领域属于性能非常优越的算法,SVM是一个二分类算法,同时支持线性分类和非线性分类,经过改进后也支持多元分类甚至回归问题;
Support Vector Machine中的Vector表示数据(在图像中就是点,距离超平面最近的哪些Vector称为支持向量),Machine表示分类器:
- 支持向量机的基本模型是定义在特征空间上的间隔最大的线性分类器,其中间隔最大使其区别于感知机;
- 支持向量机支持核技巧,这使得它可以处理非线性分类问题;
- 支持向量机的学习算法的过程等价于求解凸二次规划的最优算法的问题;
支持向量机按照学习方法分类主要分为以下几种:
- 线性可分支持向量机(硬间隔支持向量机):当训练数据线性可分时,通过硬间隔最大化,学习一个线性的分类器;
- 线性支持向量机(软间隔支持向量机):当训练数据近似线性可分时,通过软间隔最大化,学习一个线性的分类器;
- 非线性支持向量机:当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习一个非线性的分类器;
三者的关系如下:
- 线性可分SVM由线性分类器导出;
- 通过加入松弛变量和惩罚因子可以将SVM推广到线性不可分的情况,通过拉格朗日对偶可以将线性不可分的SVM的优化问题转换为对偶问题求解;
- 借助核函数可以将线性的SVM模型转换为非线性模型;

支持向量机学习的关键:求解能够正确划分训练集并且几何间距最大的分离超平面;
2.7.1 支持向量机的模型函数
我们知道感知机的超平面可能有多个,但是支持向量机的超平面只有一个(因为限定了这样的超平面是距离所有支持向量最远的一个超平面);
支持向量的模型是使所有的点到超平面的距离大于一定的距离,即所有的分类点要在各自类别的支持向量的两边:

2.7.2 模型函数的优化
(这里就不是对损失函数优化了,严格来说支持向量机没有损失函数,因为它已经能够正确分类,只是它还需要附带最大化间隔这个条件)
通常取函数间隔y`为1,因为支持向量机是固定分子优化分母,同时加上了支持向量的限制,故我们需要优化的函数为

2022/8/11 11:10 支持向量机的推导过程也异常复杂…暂时放一放先把其他知识点过了
2.8 K-means聚类
注意聚类任务与分类任务的区别:
- 分类是指在一群已经知道类别标号的样本中,训练一种分类器,让其能够对某种未知的样本进行分类,属于一种有监督的学习;
- 聚类是指在一群未知类别标号的样本上,用某种算法将他们分成若干类别,是一种无监督学习;
2.8.1 K-means算法原理
由聚类组成的簇是一组数据对象的集合,同一簇中的对象彼此相似,不同簇之间的对象相异

簇有两个重要的属性:
- Inertia:表示簇中的所有数据点相似程度,Inertia计算簇内所有点到该簇的质心的距离的总和,称为簇内距离(Intra cluster distance) —— Inertial越小,聚类越好;

- Dunn Index:表示不同簇中的数据点不同程度,Dunn Index考虑了两个簇之间的距离,两个不同簇的质心之间的距离称为簇间距离(Inter cluster distance),Dunn Index是簇间距离的最小值和簇内距离的最大值的比值 —— Dunn Index越大,聚类越好;

假设簇分为(C1、C2…Ck),则K-means的目标就是最小化平方误差E

其中ui是簇Ci的质心,表达式为

当然要直接求解上式是一个NP难的问题,所以我们会采用启发式的迭代方法进行求解
K-means聚类算法是一种基于质心(距离)的算法,每个聚类都与一个质心相关联,下面使用一个例子来展示K-means是如何迭代进行求解的,假如我们需要将下面8个点划分为簇

1.首先是选择簇的数目K,接着从数据中随机选出K个随机点作为质心,这里我们假设想要选出两个簇

2.选好质心后将所有的点分配给到某个质心最近的簇,计算点到质心的距离公式为

3.接着重新计算新形成的簇的质心,使用公式

重复第二步和第三步,直到遇见以下情况之一可以终止该迭代过程:
- 新形成的簇的质心没有任何变化;
- 多次迭代后所有的数据点仍然在同一簇中;
- 达到设置的最大迭代次数;
2.8.2 K-means++算法原理
使用K-means随机选择质心的时候可能会产生问题,K-means++算法可以优化初始化质心:
1.首先从数据点中随机选择一个质心;

2.接着计算每个数据点到其最近的簇的质心的距离;

3.从数据点中选择新的簇的质心 —— 下一个质心将是其平方距离离当前质心最远的点(为了确保不同的簇之间的距离足够大);

4.重复上述2、3步骤直到选择了K个簇;

使用K-means++初始化质心往往会改善聚类的结果,且会使得随后的K-means的收敛速度加快;
2.8.3 总结
优点:
简单快捷,容易理解,速度快,计算点和簇质心之间的距离:涉及的计算量非常小,具有线性复杂度 O(n);
对所有的数据样本都进行聚类;
对满足高斯分布、均匀分布的数据类型聚类效果表较好,适合常规数据集;
缺点:
需要事先确定聚类个数;
对初始聚类中心敏感,而K-means 也是从随机选择的聚类中心开始,所以可能在不同的算法中产生不同的聚类结果(结果可能不可重复并缺乏一致性);
对孤立点和噪声点相对敏感;
很难发现任意形状的簇;
2.9 深度神经网络
感知机模型是一个具有多个输入和多个输出的模型,可以用下图表示

然而该模型只能用于二元分类,且无法学习较复杂的非线性模型,因此演化出了人工神经网络(简称神经网络),在感知机的基础上做了如下拓展:
- 加入了隐藏层,增强了模型的表达能力(当然随之增强了模型的复杂度)

- 输出层的神经元可以不止一个,可以有多个输出

- 对激活函数做拓展,感知机的激活函数是sign(x)过于简单,我们可以选择sigmoid、tanx、softmax、Relu等激活函数(激活函数主要用于拟合非线性函数)
既然得到了神经网络,自然而然也就得到了深度神经网络(DNN),DNN可以看作是有很多层隐藏层的神经网络,DNN有时候也被称为多层感知机(MLP);
深度神经网络的层与层之间是全连接的,DNN可以简单的看作是和感知机一样的一个线性关系加上一个激活函数的组合;
2.9.1 DNN的前向传播算法
DNN的前向传播算法本质上就是利用若干权重系数矩阵W、偏倚向量b以及输入值向量x进行一系列的线性运算和激活运算,从输入层开始一直向后运算到输出层,得到输出结果;
2.9.2 DNN的反向传播算法
前面介绍了前向传播算法,好像并没有什么作用?而且我们需要的权重系数矩阵W以及偏向量b这些参数是怎么获得的也没有说明 – 这就涉及反向传播算法;
当我们需要寻找合适的所有隐藏层和输出层对应的线性系数W和偏倚向量b,我们可以参考使用一个合适的损失函数来度量训练样本的输出损失,并对这个损失函数进行优化求得最小值,此时对应的W和b就是最优的参数,得到一个良好的模型;DNN中常用的最优化损失函数的方法就是梯度下降法 – 对DNN的损失函数用梯度下降法进行迭代优化求极小值的过程称为反向传播算法;
BP算法在网上有很多讲解,感兴趣可以看视频讲解;
关于DNN的损失函数和激活函数,也有多种选择,详情可以参考深度神经网络(DNN)损失函数和激活函数的选择 - 刘建平Pinard - 博客园 (cnblogs.com);
Q_1:反向传播是什么?与梯度下降有什么关系?
A:DNN的反向传播算法是一种用于训练深度神经网络的方法,而梯度下降是一种用于最小化损失函数的优化算法。在神经网络中,反向传播算法的核心是计算梯度信息,而梯度下降算法则是使用这些梯度信息来更新模型参数,以逐步提高模型的性能。因此,反向传播和梯度下降密切合作,共同用于深度学习模型的训练和优化。
- DNN反向传播算法:
- 反向传播是一种监督学习的训练方法,用于调整神经网络中的权重和偏差,以最小化预测值与实际标签之间的损失函数。它通常用于深度神经网络,包括多层的隐藏层。
- 反向传播的核心思想是计算损失函数关于网络参数(权重和偏差)的梯度,然后使用梯度信息来更新参数以减小损失函数的值。
- 反向传播包括两个主要步骤:前向传播(计算网络输出)和反向传播(计算梯度并更新参数)。在前向传播过程中,输入数据通过网络进行前向传递,计算出预测值。在反向传播过程中,从输出层到输入层,逐层计算梯度,然后使用梯度信息来更新参数。
- 梯度下降:
- 梯度下降是一种用于最小化损失函数的优化算法。它通过沿着损失函数梯度的反方向更新参数,以减小损失函数的值。
- 在神经网络中,反向传播计算的梯度信息就是梯度下降所需要的梯度。具体来说,梯度下降使用反向传播计算的梯度来更新神经网络中的权重和偏差,从而不断优化模型,使其更好地拟合训练数据。
Q_2:能否使用通俗的语言解释反向传播的基本原理是什么?
A:一个完整的神经网络的学习过程如下
- 前向传播(Forward Propagation):
- 首先,你将输入数据(例如图像)传递给神经网络。
- 神经网络中的每个神经元都会对输入进行一些数学运算,并将结果传递给下一层神经元。
- 这个过程一直持续到输出层,最终得到模型的预测结果。
- 计算损失(Compute Loss):
- 一旦你的模型生成了预测,你需要计算一个损失值,它表示你的预测与实际标签有多大的差距。
- 损失值通常是一个数值,你的目标是尽量减小这个数值,因为它越小,表示模型的预测越接近真实情况。
- 反向传播(Backward Propagation):
- 反向传播是为了告诉网络如何调整自己的参数,以减小损失值。
- 首先,它从损失值开始,计算每个参数对损失值的影响,就像是查找问题的根本原因。
- 然后,通过使用梯度(即斜率)信息,它告诉每个参数应该朝哪个方向移动,以减小损失值。
- 更新参数(Update Parameters):
- 神经网络中的每个参数(例如权重和偏差)都根据反向传播计算的梯度信息进行微小的调整。
- 这个微小的调整会使模型更好地拟合训练数据,逐渐减小损失值。
- 迭代(Iteration):
- 以上步骤反复进行多次,每次传递一批训练数据,不断更新参数,直到损失值达到满意的程度或者达到了预定的迭代次数。
反向传播充当神经网络在学习过程中的关键过程,它通过计算损失和梯度,指导网络调整参数以提高预测准确性。这个过程就像是网络不断纠正自己的错误,逐渐变得更加智能和准确。通过多次迭代,神经网络能够不断学习并改进自己的能力。
Q_3:为什么会出现反向传播?前向传播不是也可以直接计算出梯度吗?
A:因为神经网络一般比较复杂,同时梯度的计算涉及链式法则等,直接前向计算梯度不现实:
- 链式法则(Chain Rule): 在深度神经网络中,通常有许多层和神经元相互连接,形成复杂的计算图。要计算整个网络的梯度,需要应用链式法则,将梯度从输出层传播回输入层。这个传播过程涉及到许多中间变量和复杂的计算链,难以手动计算和管理。
- 高效计算: 在深度神经网络中,通常有成千上万个参数需要进行梯度计算和更新。手动计算梯度对于如此大规模的网络来说是不切实际的,会耗费大量时间和资源。
- 通用性: 反向传播是一种通用的梯度计算方法,可以应用于各种不同类型的神经网络结构。这使得它成为了广泛使用的工具,无需每次重新推导梯度计算的公式。
2.9.3 DNN的正则化
DNN同样会遇到过拟合的问题,因此需要使用正则化解决;
(1)L2正则化
DNN的L2正则化通常只针对线性系数矩阵W而不针对偏倚系数b,假如每个样本的损失函数是均方差损失函数,则所有的m个样本的损失函数为

那么加上了L2正则化之后的损失函数是

在使用BP算法进行迭代的时候W的梯度下降更新公式变为

(2)集成学习正则化
这种方式是利用集成学习的思路进行正则化,集成学习主要有Boosting和Bagging两种思路,DNN可以用Bagging的思路来正则化,具体方法感兴趣自行了解;
(3)dropout正则化
该方法是指在训练DNN模型的时候,当一批数据进行迭代时,随机的从全连接的DNN网络中去掉一部分的隐藏层神经元,并使用去掉的隐藏层的神经元的网络来拟合下一批训练数据

dropout方法总结:每轮梯度下降迭代时,它需要将训练数据分成若干批,然后分批进行迭代,每批数据迭代时,需要将原始的DNN模型随机去掉部分隐藏层的神经元,用残缺的DNN模型来迭代更新W,b。每批数据迭代更新完毕后,要将残缺的DNN模型恢复成原始的DNN模型
2.9.4 卷积神经网络
参考资料卷积神经网络(CNN)模型结构 - 刘建平Pinard - 博客园 (cnblogs.com)
2.9.5 循环神经网络
参考资料循环神经网络(RNN)模型与前向反向传播算法 - 刘建平Pinard - 博客园 (cnblogs.com)
2.9.6 波尔茨曼机
参考资料循环神经网络(RNN)模型与前向反向传播算法 - 刘建平Pinard - 博客园 (cnblogs.com)
2.10 集成学习
机器学习的有监督学习算法中,我们期望的是学习习得到一个稳定并且在各个方面都表现较好的模型,但是实际上得到的模型都只能得到多个偏好的模型(我们称之为弱监督模型,只在某些方面表现较好),集成学习顾名思义就是将这些弱监督模型组合得到一个更加全面的强监督模型 – 集成学习的思想就是,即便某一个弱分类器得到了错误的预测,其他的弱分类器也可以将错误纠正:
- 弱学习器:常指泛化性能略优于随机猜测的学习器:例如在二分类问题上精度略高于50%的分类器;
- 强学习器:通过一定的方式集成一些弱学习器:例如达到了超过所有弱学习器的准确度的分类器;
集成学习并不只是一个单一的机器学习算法,它是将几种机器学习技术组合成为一个预测模型的元算法;集成学习是一种技术框架,按照不同的思路组合基础模型得到更好的模型以减小方差、偏差等,因此集成学习实际上需要解决的问题主要有两个:
Q:如何得到多个个体学习器;
- 所有的个体学习器都是同一个种类的,也可以说是同质的,如bagging和bossting系列:
- 个体学习器之间存在强依赖关系,一系列个体学习器基本都需要串行生成,代表算法是Boosting系列算法;
- 个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成,代表算法是Bagging系列算法;
- 所有的个体学习器不全是一个种类的,也可以说是异质的,如Stacking策略;
- 所有的个体学习器都是同一个种类的,也可以说是同质的,如bagging和bossting系列:
Q:选择一种什么样的学习策略,将这些弱学习器组合成为一个强学习器;
2.10.1 集成学习之Bagging
代表算法:随机森林
bagging的中文意义是训练多个分类器后取平均,较为严谨的解释是从训练集从进行子抽样组成每个基模型所需要的子训练集,对所有基模型预测的结果进行综合产生最终的预测结果

bagging的工作机制:
- 从原始样本集中抽取训练集,每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本,共进行k轮抽取,得到k个训练集;
- 每次使用一个训练集得到一个模型,k个训练集共得到k个模型;
- 对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果;
关于Bootstraping(自助采样法)
其思想非常简单,即对于m个样本的原始训练集,每次随机采取一个样本后将该样本放回原始训练集,也就是说该样本在下次取样的时候仍然有可能被采集,这样采集m次后得到的有m个样本的新的采样集和原始训练集以及其他采样集是不同的,相应的,这样训练得到的弱学习器也是不同的,
2.10.2 集成学习之Boosting
代表算法:AdaBoost, Xgboost,GBDT
boosting顾名思义就是提升算法,即从弱分类器开始加强,通过加权来进行训练,基模型的训练过程为阶梯状,基模型的训练集会随着训练结果的变化而变化(调整权重),最后对所有的基模型的预测结果进行线性综合产生最终的预测结果

boosting的工作机制:
- 首先从训练集用初始权重训练出一个弱学习器1;
- 根据弱学习的学习误差率表现来更新训练样本的权重,使之前弱学习器1学习误差率高的训练样本点的权重变高,即让误差率高的点在后面的弱学习器2中得到更多的重视;
- 然后基于调整权重后的训练集来训练弱学习器2;
- 如此重复进行,直到弱学习器数达到事先指定的数目T;
- 最终将这T个弱学习器通过集合策略进行整合,得到最终的强学习器;
2.10.3 集成学习之Stacking
stacking即堆叠各种各样的分类器,主要思想就是训练一个模型用于组合其他各个模型,方法是利用所有训练好的基模型分别在原始训练集和原始测试集上测试(第j个基模型对第i个训练样本的预测值将作为新的训练集中第i个样本的第j个特征值),得到新的训练集和新的测试集

stacking的工作机制:
- 首先训练多个不同的模型;
- 将上述训练得到的模型的输出作为输入来训练一个模型,得到最终的输出;
按照个体学习器之间的关系,集成学习一般分为三个大类:
Bagging是把各个基模型的结果组织起来,取一个折中的结果;
Boosting是根据旧模型中的错误来训练新模型,层层改进;
Stacking是把基模型组织起来,注意不是组织结果,而是组织基模型本身;
2.10.4 集成学习之Adaboost
Adaboost属于Boosting家族中较为典型的算法,因为Boosting算法的基本思想是将弱学习器提升为强学习器;
更多关于Adaboost算法参考集成学习之AdaBoost算法 - 大-道-至-简 - 博客园 (cnblogs.com)
2.10.5 集成学习之GBDT
GBDT即梯度提升树算法,Adaboost算法是利用前一轮的弱学习器的误差来更新样本权重值,然后一轮一轮的迭代,GBDT与之类似,但其弱分类器限定只能使用CART回归树模型(无论处理的是回归问题还是二分类问题或多分类问题),且在训练过程中要求模型预测的样本损失尽可能的小;
更多关于GBDT算法参考集成学习之梯度提升树(GBDT)算法 - 大-道-至-简 - 博客园 (cnblogs.com)
2.10.6 集成学习之随机森林
随机森林是基于bagging框架下的决策树模型(boosting流派特点是各个弱学习器之间存在依赖关系,bagging流派的各个 弱学习器之间不存在依赖关系可以并行拟合);
更多关于随机森林算法参考集成学习之随机森林 - 大-道-至-简 - 博客园 (cnblogs.com)
2.10.7 集成学习之Xgboost
Xgboost全称极端梯度提升,是大规模进行boosted tree的工具,Xgboost算法实际就是GBDT的改进,既可用于分类任务也可用于回归任务;
更多关于Xgboost算法参考集成学习之Xgboost - 大-道-至-简 - 博客园 (cnblogs.com)
二、强化学习
1.概述
参考自强化学习(一)模型基础 - 刘建平Pinard - 博客园 (cnblogs.com)强化学习系列;
强化学习是与监督学习、无监督学习并列的第三种机器学习算法,强化学习与时间顺序前后关系密切,而监督学习的训练数据之间一般都是相互独立的没有前后依赖关系;
强化学习的基本思路步骤如下:
- 在当前环境状态S
t下选择一个合适的动作At; - 选择好动作后,环境状态会发生改变,此时环境状态变为S
t+1,同时我们得到了动作At的延时奖励Rt+1; - 重复上述步骤;
从上面简单介绍的强化学习思路中我们可以看到,强化学习过程中出现了几个比较重要的因素:
- t时刻的
环境状态St是其环境状态集中的某一个状态; - t时刻的
个体动作At是其动作集中的某一个动作; - t时刻的个体在状态S
t采取的动作At对应的延时奖励Rt+1会在时刻t+1得到; 个体策略Π,代表个体采取动作的依据,简单来说就是个体依据策略Π选择个体动作,最常见的一种策略表达方式是条件概率分布Π(a|s),即在状态s时采取的动作a的概率,此时概率大的动作被个体选择的概率较高;- 个体在策略Π和环境状态为s时,采取行动后的
价值,常用vΠ(s)表示,是一个期望函数;该要素的意义在于针对奖励,只能代表此时的奖励较高但未知到了t+1、t+2…的奖励是否仍然高,因此需要综合考虑当前的延时奖励和后续的延时奖励,价值函数的表达式一般如下

γ是
奖励衰减因子,取值在[0,1]之间- 如果为0,则是贪婪法,即价值只由当前延时奖励决定;
- 如果是1,则所有的后续状态奖励和当前奖励一视同仁。大多数时候,我们会取一个0到1之间的数字,即当前延时奖励的权重比后续奖励的权重大;
环境状态转化模型,可以理解为一个概率状态机,表示一个概率模型,即在状态s下采取动作a转到下一个状态s’的概率,表示为Pss’^a^;探索率,该比率主要用于强化学习的迭代过程,意义在于假如我们直接选择使当前迭代价值最大的动作会导致其他较好的但是并未被我们执行的动作被错过,因此在选择最优动作的时候有一定概率不会选择使当前迭代价值最大的动作;
这里有一个关于强化学习的例子,涉及上述介绍的要素,强化学习(一)模型基础 - 刘建平Pinard - 博客园 (cnblogs.com)(3.强化学习的简单实例)
更多有关强化学习的介绍参考博客强化学习 - Tintoki_blog (gintoki-jpg.github.io);
三、深度学习
(这里主要就是整理的《动手学深度学习》这本书的知识点了;)
“机器学习(machine learning,ML)是一类强大的可以从经验中学习的技术。 通常采用观测数据或与环境交互的形式,机器学习算法会积累更多的经验,其性能也会逐步提高。在这本书中,我们将带你开启机器学习之旅,并特别关注深度学习(deep learning,DL)的基础知识”
整本书的结构如下

1.概述
首先是机器学习的概念,此处的定义比较新奇:
假设要编写一个程序来响应一个“唤醒词”(比如“Alexa”、“小爱同学”和“Hey Siri”)
我们可以收集一个包含音频样本的巨大的数据集(dataset),并对包含和不包含唤醒词的样本进行标记。 通过机器学习算法,我们不需要设计一个“明确地”识别唤醒词的系统。 相反,我们定义一个灵活的程序算法,其由许多参数(parameter)决定。 然后我们使用数据集来确定当下的“最佳参数集”,这些参数通过某种性能度量来获取完成任务的最佳性能。任一调整参数后的程序,我们称为模型(model)。 通过操作参数而生成的所有不同程序(输入-输出映射)的集合称为“模型族”。 使用数据集来选择参数的元程序被称为学习算法(learning algorithm)。
我们重新回顾一下算法和模型的关系:
- 运行算法输出模型;
- 算法与模型是一对多的关系,即一个算法运行在不同的训练数据上可以得到不同的模型;
下面将介绍一些机器学习中的核心组件(这些在前面多多少少也已经接触过了,这里只是作为回顾),这些组件的概念无论是面对什么类型的机器学习都将起到重要的作用:
- 用于学习的数据;
- 转换数据的模型(其实严格来说模型是训练之后得到的结果,但是很多时候我们把训练之前的“假设函数”也称为模型或“模型函数”);
- 用于量化模型有效性的目标函数(很多时候我们也称其为损失函数);
- 调整模型参数以优化目标函数的算法(梯度下降、随机梯度下降…);
当然上面这几个组件是最重要的,但不是仅有这几个组件,这些组件是构成一个完整的机器学习必不可少的部分;
1.1 组件:数据
每个数据集由一个个样本(example, sample)组成,大多时候,它们遵循独立同分布(independently and identically distributed, i.i.d.)。 样本有时也叫做数据点(data point)或者数据实(data instance),通常每个样本由一组称特征(features,或协变量(covariates))的属性组成。机器学习模型会针对这些属性进行预测(比如上面预测标签)。
当每个样本的特征类别数量都是相同的时候,其特征向量是固定长度的,这个长度被称为数据维数(dimensionality)。固定长度的特征向量是一个方便的属性,它有助于我们量化学习大量样本。
然而,并不是所有的数据都可以用“固定长度”的向量表示。 以图像数据为例,如果它们全部来自标准显微镜设备,那么“固定长度”是可取的; 但是如果图像数据来自互联网,它们很难具有相同的分辨率或形状。 这时,我们可以考虑将图像裁剪成标准尺寸,但这种办法很局限,有丢失信息的风险。
与传统机器学习方法相比,深度学习的一个主要优势是可以处理不同长度的数据。
当数据不具有充分代表性,甚至包含了一些社会偏见时,模型就很有可能有偏见。
我们通常将可用数据集分成两部分:训练数据集用于拟合模型参数,测试数据集用于评估拟合的模型。 然后我们观察模型在这两部分数据集的效能。
1.2 组件:模型
大多数机器学习会涉及到数据的转换,如辨别动物,虽然简单的机器学习模型能够解决如上简单的问题,但本书中关注的问题超出了经典方法的极限,因此需要使用到深度学习。
深度学习与经典方法的区别主要在于:前者关注的功能强大的模型,这些模型由神经网络错综复杂的交织在一起,包含层层数据转换,因此被称为深度学习(deep learning)。 在讨论深度模型的过程中,我们也将提及一些传统方法。
深度学习(Deep Learning)是机器学习研究中的一个新的领域,其动机在于建立、模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本。
1.3 组件:目标函数
在机器学习中,我们需要定义模型的优劣程度的度量,这个度量在大多数情况是“可优化”的,我们称之为目标函数(objective function)。 我们通常定义一个目标函数,并希望优化它到最低点。 因为越低越好,所以这些函数有时被称为损失函数(loss function,或cost function)。 但这只是一个惯例,你也可以取一个新的函数,优化到它的最高点。 这两个函数本质上是相同的,只是翻转一下符号。
当任务在试图预测数值时,最常见的损失函数是平方误差(squared error),即预测值与实际值之差的平方。 当试图解决分类问题时,最常见的目标函数是最小化错误率,即预测与实际情况不符的样本比例。 有些目标函数(如平方误差)很容易被优化,有些目标(如错误率)由于不可微性或其他复杂性难以直接优化。 在这些情况下,通常会优化替代目标。
通常,损失函数是根据模型参数定义的,并取决于数据集——在一个数据集上,我们通过最小化总损失来学习模型参数的最佳值。
1.4 组件:优化算法
一旦我们获得了一些数据源及其表示、一个模型和一个合适的损失函数(也就是具备上面所有的组件之后),我们接下来就需要一种算法,它能够搜索出最佳参数,以最小化损失函数。
更多有关深度学习的资料参考博客神经网络与深度学习 - Tintoki_blog (gintoki-jpg.github.io),这篇博客总结了常见的深度学习的一些模型;