| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> 以??简单易懂??的语言带你搞懂有监督学习算法【附Python代码详解】机器学习系列之KNN篇 -> 正文阅读 |
|
[人工智能]以??简单易懂??的语言带你搞懂有监督学习算法【附Python代码详解】机器学习系列之KNN篇 |
必须要看的前言本文风格:以??简单易懂??的语言带你彻底搞懂KNN,了解什么是有监督学习算法。 认真看完这篇文章,彻底了解KNN、了解监督学习算法绝对是一样很简单的事情。
目录监督学习算法本文主要介绍的有监督学习算法是KNN,后续会接着介绍决策树、线性回归等算法。 KNN/K近邻算法1 算法原理首先,第一个也是最主要的问题——KNN是如何对样本进行分类的呢? 它的本质是通过距离判断两个样本是否相似,如果距离够近就认为他们足够相似属于同一类别。 当然只对比一个样本是不够的,误差会很大,我们需要找到离其最近的 k 个样本,并将这些样本称之为「近邻」(nearest neighbor)。对这 k 个近邻,查看它们的都属于何种类别(这些类别我们称作「标签」 (labels))。 然后根据“少数服从多数,一点算一票”原则进行判断,数量最多的的标签类别就是新样本的标签类别。其中涉及到的原理是“越相近越相似”,这也是KNN的基本假设。 1.1 实现过程假设 X_test 待标记的数据样本,X_train 为已标记的数据集。
1.2 距离的确定该算法的「距离」在二维坐标轴就表示两点之间的距离,计算距离的公式有很多。 我们常用欧拉公式,即“欧氏距离”。回忆一下,一个平面直角坐标系上,如何计算两点之间的距离? 应该不难会想起来吧,公式应该大致如下: d i s t a n c e ( A , B ) = ( x A ? x B ) 2 + ( y A ? y B ) 2 distance(A, B)=\sqrt[]{(x_A-x_B)^2+(y_A-y_B)^2} distance(A,B)=(xA??xB?)2+(yA??yB?)2?那如果不是在一个平面直角坐标系,而是在立体直角坐标系上,怎么计算呢? d i s t a n c e ( A , B ) = ( x A ? x B ) 2 + ( y A ? y B ) 2 + ( z A ? z B ) 2 distance(A, B)=\sqrt[]{(x_A-x_B)^2+(y_A-y_B)^2+(z_A-z_B)^2} distance(A,B)=(xA??xB?)2+(yA??yB?)2+(zA??zB?)2?那如果是n维空间呢? d i s t a n c e ( A , B ) = ( x 1 A ? x 1 B ) 2 + ( x 2 A ? x 2 B ) 2 + ( x 3 A ? x 3 B ) 2 + . . . . . . + ( x n A ? x n B ) 2 = ∑ i = 1 n ( x i A ? x i B ) 2 distance(A, B)=\sqrt[]{(x_{1A}-x_{1B})^2+(x_{2A}-x_{2B})^2+(x_{3A}-x_{3B})^2+......+(x_{nA}-x_{nB})^2}=\sqrt[]{\sum_{i=1}^{n} {(x_{iA}-x_{iB})^2}} distance(A,B)=(x1A??x1B?)2+(x2A??x2B?)2+(x3A??x3B?)2+......+(xnA??xnB?)2?=i=1∑n?(xiA??xiB?)2?而在我们的机器学习中,坐标轴上的值 x 1 x_1 x1?, x 2 x_2 x2? , x 3 x_3 x3? ,…… x n x_n xn?正是我们样本数据上的 n 个特征。 2 算法的优缺点算法参数是 k,k 可以理解为标记数据周围几个数作为参考对象,参数选择需要根据数据来决定。
3 算法的变种3.1 变种一默认情况下,在计算距离时,权重都是相同的,但实际上我们可以针对不同的邻居指定不同的距。离权重,比如距离越近权重越高。
3.2 变种二使用一定半径内的点取代距离最近的 k 个点。
4 Python代码实现这里我还是先以上篇文章讲到的红酒分类为例子,待会还会有其他实例。 4.1 导入模块
4.2 构建已经分类好的原始数据集首先随机设置十个样本点表示十杯酒,这里取了部分样本点。 为了方便验证,这里使用 Python 的字典 dict 构建数据集,然后再将其转化成 DataFrame 格式。
我们先来画一下图。
4.3 计算已知类别数据集中的点与当前点之间的距离。我们使用欧式距离公式,计算新数据点 new_data 与现存的 X 数据集每一个点的距离:
4.4 将距离升序排列,然后选取距离最小的k个点。
array([6, 7, 1, 4, 5, 9, 2, 8, 3, 0], dtype=int64) 6、7、4为最近的3个“数据点”的索引值,那么这些索引值对应的原数据的标签是什么?
[1,1,0] 这个时候我们就得到了离黄点最近的三个点对应的类别啦。 4.5 确定前k个点所在类别的计数。
1 所以当我们的k取3时,分类结果为1,也就是赤霞珠。大家看一下是不是跟我们人脑分辨的结果是一样的呢? 4.6 封装成函数那为了后续更好的操作,我们可以将上述过程封装成一个函数。
[1] 5 SCIKIT-LEARN算法库实现上述过程是我们自己一个个实现的,而在如今呢,人们更习惯用scikit-learn这一Python的第三方模块。 scikit-learn 自 2007 年发布以来,scikit-learn已经成为 Python 中重要的机器学习库了。scikit-learn,简称 sklearn, 支持了包括分类、回归、降维和聚类四大机器学习算法,以及特征提取、数据预处理和模型评估三大模块。 在工程应用中,用 Python 手写代码来从头实现一个算法的可能性非常低,这样不仅耗时耗力,还不一 定能够写出构架清晰,稳定性强的模型。更多情况下,是分析采集到的数据,根据数据特征选择适合的算法, 在工具包中调用算法,调整算法的参数,获取需要的信息,从而实现算法效率和效果之间的平衡。而 sklearn, 正是这样一个可以帮助我们高效实现算法应用的工具包。 http://scikit-learn.org/stable/index.html 上述链接是sklearn的官方网站,里面详细地介绍了sklearn的使用,感兴趣的朋友可以看一看这个,或者看我下面的简要介绍。
1)一致性
2)监控 3)防止类扩散 4)合成 5)合理默认值 5.1 案例一:红酒
array([0])
1.0
array([[0.66666667, 0.33333333]]) 这里解释一下,0.66666667是标签为0的概率,0.33333333是标签为1的概率。 5.2 案例二:乳腺癌
0.9210526315789473 如何用上面分类器拟合结果找出离 Xtest 中第 20 行和第 30 行最近的 4 个“点”?
(array([[35.70015941, 42.02374599, 81.82147557, 83.06271326], 6 选择最优K值相信大家看到这可能会有疑惑说,这个k值到底怎么取比较好,那么接下来,就正式讲一讲怎么选择k值吧。 KNN 中的 k 是一个超参数,所谓“超参数”,就是需要人为输入,算法不能通过直接计算得出的参数。 KNN 中的 k 代表的是距离需要分类的测试点 x 最近的 k 个样本点,如果不输入这个值,那么算法中重要部分 “选出 k 个最近邻” 就无法实现。 从 KNN 的原理中可见,是否能够确认合适的 k 值对算法有极大的影响。 如果选择的 k 值较小,就相当于较小的邻域中的训练实例进行预测,这时候只有与输入实例较近的(相似的)训练实例才会对预测结果起作用,但缺点是预测结果会对近邻的实例点非常敏感。如果邻近的实例点恰好是噪声,预测就会出错。 相反地,如果选择的 k 值较大,就相当于较大的邻域中的训练实例进行预测。这时与输入实例较远的 (不相似的)训练实例也会对预测起作用,使预测发生错误。因此,超参数 k 的选定是 KNN 的头号问题。
6.1 学习曲线那我们怎样选择一个最佳的 k 呢?在这里我们要使用机器学习中的神器:参数学习曲线。参数学习曲线是一条以不同的参数取值为横坐标,不同参数取值下的模型结果为纵坐标的曲线,我们往往选择模型表现最佳点的参数取值作为这个参数的取值。
0.9385964912280702 绘制学习曲线:
究竟上图中k为多少的时候分数越高?
8 但是这个时候会有个问题,如果随机划分的数据集变化的的话,得分最高的k值也会发生变化:
3 这样就无法确定最佳的k值了,就无法进行下面的建模工作,怎么办? 我们接着往下看。 7 交叉验证确定了 k 之后,我们还能够发现一件事:每次运行的时候学习曲线都在变化,模型的效果时好时坏, 这是为什么呢? 实际上,这是由于「训练集」和「测试集」的划分不同造成的。模型每次都使用不同的训练集进行训练, 不同的测试集进行测试,自然也就会有不同的模型结果。 在业务当中,我们的训练数据往往是已有的历史数据,但我们的测试数据却是新进入系统的一系列还没有标签的未知数据。我们的确追求模型的效果,但我们追求的是模型在未知数据集上的效果,在陌生数据集上表现优秀的能力被称为泛化能力,即我们追求的是模型的泛化能力。 7.1 泛化能力我们在进行学习算法前, 通常会将一个样本集分成训练集(training set)和测试集(testing set),其中训练集用于模型的学习或训练,而后测试集通常用于评估训练好的模型对于数据的预测性能评估。 **训练误差(training error)**代表模型在训练集上的错分样本比率。 **测试误差(empirical error)**是模型在测试集上的错分样本比率。 训练误差的大小,用来判断给定问题是不是一个容易学习的问题。 测试误差则反映了模型对未知数据的预测能力,测试误差小的学习方法具有很好的预测能力,如果得到的训练集和测试集的数据没有交集,通常将此预测能力称为泛化能力(generalization ability)。 我们认为,如果模型在一套训练集和数据集上表现优秀,那说明不了问题,只有在众多不同的训练集和 测试集上都表现优秀,模型才是一个稳定的模型,模型才具有真正意义上的泛化能力。为此,机器学习领域有发挥神作用的技能:「交叉验证」,来帮助我们认识模型。 7.2 K折交叉验证最常用的交叉验证是 k 折交叉验证。我们知道训练集和测试集的划分会干扰模型的结果,因此用交叉验证 n 次的结果求出的均值,是对模型效果的一个更好的度量。
7.3 带交叉验证的学习曲线对于带交叉验证的学习曲线,我们需要观察的就不仅仅是最高的准确率了,而是准确率高且方差还相对较小的点,这样的点泛化能力才是最强的。在交叉验证+学习曲线的作用下,我们选出的超参数能够保证更好的泛化能力。
array([0.92207792, 0.90789474, 0.97368421, 0.94736842, 0.93333333, 0.92 ])
0.934059770638718 0.0004622658270548926
7.4 是否需要验证集最标准,最严谨的交叉验证应该有三组数据:训练集、验证集和测试集。 当我们获取一组数据后:
通常来说,我们认为经过验证集找出最终参数后的模型的泛化能力是增强了的,因此模型在未知数据(测试集)上的效果会更好,但尴尬的是,模型经过交叉验证在验证集上的调参之后,在测试集上的结果没有变好的情况时有发生。 原因其实是:
如果我们相信交叉验证的调整结果是增强了模型的泛化能力的,那即便测试集上的测试结果并没有变 好(甚至变坏了),我们也认为模型是成功的。 如果我们不相信交叉验证的调整结果能够增强模型的泛化能力,而一定要依赖测试集来进行判断,我们完全没有进行交叉验证的必要,直接用测试集上的结果来跑学习曲线就好了。 所以,究竟是否需要验证集,其实是存在争议的,在严谨的情况下,大家还是使用有验证集的方式。 7.5 其他交叉验证交叉验证的方法不止“k 折” 一种,分割训练集和测试集的方法也不止一种,分门别类的交叉验证占据了sklearn 中非常长的一章。 所有的交叉验证都是在分割训练集和测试集,只不过侧重的方向不同。
各类交叉验证的原理繁琐,大家在机器学习道路上一定会逐渐遇到更难的交叉验证,但是万变不离其宗:本质上交叉验证是为了解决训练集和测试集的划分对模型带来的影响,同时检测模型的泛化能力的。
另外,交叉验证的折数不可太大,因为折数越大抽出来的数据集越小,训练数据所带的信息量会越小,模型会越来越不稳定。 7.6 避免折数太大如果你发现不使用交叉验证的时候模型表现很好,一使用交叉验证模型的效果就骤降。
如果将上面例题的代码中将 cv 将 5 改成 100:
8 归一化8.1 距离类模型归一化的要求什么是归一化?我们把 X 放到数据框中来看一眼,你是否观察到,每个特征的均值差异很大?有的特征数值很大,有的特征数值很小,这种现象在机器学习中被称为"量纲不统一"。KNN 是距离类模型,欧氏距离的计算公式中存在着特征上的平方和: d i s t a n c e ( A , B ) = ( x 1 A ? x 1 B ) 2 + ( x 2 A ? x 2 B ) 2 + ( x 3 A ? x 3 B ) 2 + . . . . . . + ( x n A ? x n B ) 2 = ∑ i = 1 n ( x i A ? x i B ) 2 distance(A, B)=\sqrt[]{(x_{1A}-x_{1B})^2+(x_{2A}-x_{2B})^2+(x_{3A}-x_{3B})^2+......+(x_{nA}-x_{nB})^2}=\sqrt[]{\sum_{i=1}^{n} {(x_{iA}-x_{iB})^2}} distance(A,B)=(x1A??x1B?)2+(x2A??x2B?)2+(x3A??x3B?)2+......+(xnA??xnB?)2?=i=1∑n?(xiA??xiB?)2?如果某个特征 的取值非常大,其他特征的取值和它比起来就不算什么,那么距离的大小很大程度都会由这个 来决定,其他的特征之间的距离可能就无法对d(A,B)的大小产生什么影响,这种现象会让KNN这样的距离类模型的效果大打折扣。 然而在实际分析情景当中,绝大多数数据集都会存在各特征值量纲不同的情况,此时若要使用 KNN 分类器,则需要先对数据集进行归一化处理,即是将所有的数据压缩都同一个范围内。 当数据(x)按照最小值中心化后,再按极差(最大值-最小值)缩放,数据移动了最小值个单位,并且会被收敛到[0,1]之间,而这个过程,就称作数据归一化(Normalization,又称 Min-Max Scaling)。 x ? = x ? m i n ( x ) m a x ( x ) ? m i n ( x ) x^*=\frac {x-min(x)} {max(x)-min(x)} x?=max(x)?min(x)x?min(x)? 8.2 先分数据集,再做归一化直接在全数据集 X 上进行了归一化,然后放入交叉验证绘制学习曲线,这种做法是错误的。 真正正确的方式是,先分训练集和测试集,再归一化! 为什么?想想看归一化的处理手段,我们是使用数据中的最小值和极差在对数据进行压缩处理,如果我们在全数据集上进行归一化,那最小值和极差的选取是会参考测试集中的数据的状况的。因此,当我们归一化后,无论我们如何分割数据,都会由一部分测试集的信息被“泄露”给训练集,这会使得我们的模型效果被高估。 在现实业务中,我们只知道训练集的数据,不了解测试集究竟会长什么样,所以我们要利用训练集上的最小值和极差来归一化测试集。 8.3 通过 python 实现
8.4 通过 sklearn 实现同样的,slearn也封装了Min-Max Scaling方法,具体操作如下:
8 最终的到 k 最优值为 8,无论 random_state 取什么值,最优 k 值不会相差太多。 把经过交叉验证、归一化处理之后,我们得到最优 k 为 8,放在归一化后的训练集重新建模,然后在归一化后的测试集中查看结果分数:
0.956140350877193 大家可以尝试着更改random_state,然后再根据学习曲线图更换k值,最终查看分数是否同95.6%有较大出入。 9 距离的惩罚最近邻点距离远近修正在对未知分类过程中, “一点一票” 的规则是 KNN 模型优化的一个重要步骤。 也就是说,对于原始分类模型而言,在选取最近的 k 个元素之后,将参考这些点的所属类别,并对其进行简单计数,而在计数的过程中这些点 “一点一票” ,这些点每个点对分类目标点的分类过程中影响效力相同。 但这实际上是不公平的,就算是最近邻的 k 个点,每个点的分类目标点的距离仍然有远近之别,而近的点往往和目标分类点有更大的可能性属于同一类别( 该假设也是 KNN 分类模型的基本假设) 。 关于惩罚因子的选取有很多种方法, 最常用的就是根据每个最近邻 𝑥= 距离的不同对其作加权, 加权方法为设置 权重,该权重计算公式为 w i = 1 d ( x ′ , x i ) w_i=\frac{1}{d(x^{'},x_i)} wi?=d(x′,xi?)1?这里需要注意的是,关于模型的优化方法只是在理论上而言进行优化会提升模型判别效力,但实际应用过程中最终能否发挥作用,本质上还是取决于优化方法和实际数据情况的契合程度,如果数据本身存在大量异常值点,则采用距离远近作为惩罚因子则会有较好的效果,反之则不然。 因此在实际我们进行模型优化的过程当中,是否起到优化效果还是要以最终模型运行结果为准。在sklearn中,我们可以通过参数 weights 来控制是否适用距离作为惩罚因子。
6
0.9473684210526315 结束语感谢你能看到这里,我会在后续继续更新机器学习系列的文章,内容风格依旧会是易懂但有用,希望能得到你的点赞支持,感谢! 机器学习系列往期回顾 ?? 开始学习机器学习之前你必须要了解的知识有哪些?机器学习系列入门篇 🖤 我和关注我的前1000个粉丝“合影”啦!收集前1000个粉丝进行了一系列数据分析,收获满满 推荐关注的专栏 👨?👩?👦?👦 数据分析:分享数据分析实战项目和常用技能整理 CSDN@报告,今天也有好好学习 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 15:51:56- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |