‘壹’ 机器学习几个重要概念
机器学习几个重要概念
统计学习的算法可以分为以下几个类别:监督学习、非监督学习、半监督学习以及强化学习。
监督学习的输入数据都有对应的类标签或是一个输出值,其任务是学习一个模型,使模型能够对任意给定的输入,对其相应的输出做出一个好的预测。
非监督学习就是没有对应的类标签或是输出值。学习中并没有任何标准来告诉你,某个概念是否正确,需要学习器自身形成和评价概念。就是自动地从数据中挖掘出结构信息或是抽取出一些规则。近年来,非监督学习被认为是解决一些重要问题的突破口所在。因为科学的产生就是人类中无监督学习的最佳案例。
半监督学习就是介于监督学习和非监督学习之间。这在最近的研究领域也是被大家所热烈探讨的,因为对于现实数据来说,有标签的数据总是少量的,往往都需要人工来进行标注。而无标签数据是能够大量获得的。
增强学习强调如何基于环境而行动,以取得最大化的预期利益。其灵感来源于心理学中的行为主义理论,即有机体如何在环境给予的奖励或惩罚的刺激下,逐步形成对刺激的预期,产生能获得最大利益的习惯性行为。强化学习和标准的监督式学习之间的区别在于,它并不需要出现正确的输入/输出对,也不需要精确校正次优化的行为。(以上内容摘自维基网络)这在机器人、无人机领域中应用的还是非常广泛的。
在线学习与离线学习
对于机器学习算法的分类,站在不同的角度就能有不同的分类方法。在具体的应用中还有一种常用的分类方法是:在线学习与离线学习。
在线学习,是在获取到新的数据后就能够输入到模型中进行学习。这需要学习算法能够在处于任何状态时都能进行参数的更新。而且需要算法对噪声数据有很好的鲁棒性。
离线学习就正好与在线学习相反,当数据有更新时,需要将其与原来的数据一起对模型的参数进行重新地训练。这时,整个训练的过程能够被很好的控制,因为所有的数据都是已知的,能够对数据进行细致的预处理过程。
生成模型与判别模型
这种分类方式是针对于监督学习来进行分类的。这个在我腾讯面试的时候还被问到过这个问题。
生成模型
生成方法由数据学习联合概率分布P(X,Y)
,然后求出条件概率分布P(Y|X)
作为预测的模型,即生成模型:
模型表示了给定输入X产生输出Y的生成关系。典型的生成模型有:朴素贝叶斯方法和隐马尔可夫模型。
生成模型能够还原出联合概率分布P(X,Y)
;生成模型的收敛速度快,当样本容量增加的时候,学到的模型可以更快地收敛于真实模型;当存在隐变量时,仍可以使用生成学习方法,此时判别方法就不能用。
判别模型
判别方法由数据直接学习决策函数f(x)
或者条件概率分友卜中布P(Y|X)
作为预测的模型,即判别模型。典型的判别模型包括:k近邻法、感知机、决策树、logistic回归模型、最大熵模型、支持向量机、提升方法和条件随机场。
判别模型直接面对预测,往往学习的准确率越高。可以对数据进行各种程度上的抽好山象、定义特征并使用特征,因此可以简化学习问题。
算法的归纳偏好
机器学习算法在学习过程中对某种类型假设的偏好称为‘归纳偏好’。这个‘假设’包含了一个算法方方面面的内容。
任何一个有效的机器学习算法必有其归纳的偏好,否则它将被假设空间中看似在训练集上‘等效’的假设所迷惑,而无法产生确定的学习结果。例如在分类问题中,如果随机抽选训练集上等效的假设(可以认为所有的正反例并没有区别),那么它的分类结果其实是不确定的,这要根据它所选取的样本来决定,这样的学习显然是没有意义的。
归纳偏好对应了学习算法本身所做出的关于‘什么样的模型更好’的假设。在具弊睁体的问题中,这个假设是否成立,即算法的归纳偏好是否与问题本身匹配,大多数时候直接决定了算法能否取得好的性能。
‘奥卡姆剃刀’就是一个常用的原则,‘若有多个假设与观察一致,则选择最简单的那个’。对于一些以简洁为美的人来说是再正确不过了。在一些工程技术中有一些问题也确实是这样,一个较为简单的方法所取得的效果虽然不是最好,但是它的代价与其效果之比已然是最优。
对于一个线性回归问题,如下图所示:
根据‘奥卡姆剃刀’原则,你肯定会选择中间那条经过回归处理之后的直线作为之后预测的标准。在一些场景下,这样选择自然是正确的。如果再给你更多的数据点,你发现这些点正好是在穿过所有红色点的曲线之上,你还会选择那条回归的直线吗?这就牵扯出一个非常有意思的定理,‘没有免费的午餐’。
这个定理所描述的是,对于任意两个学习算法A和B,它们在任意分布数据上的误差其实是相等的。仔细想想的话确实是那么回事。这个定理有一个重要的前提:所有问题出现的机会相同或是所有问题都是同等重要的。
这时候你肯定会有疑问,既然所有的学习算法的期望性能都和随机猜测差不多,那学习的过程岂不是并没有什么用。注意到一点,上面所说的相等是在所有数据的分布之下,但是我们所处理的问题的数据往往是某一特定分布的。
欠拟合与过拟合
当目标函数给定时,基于目标函数的模型训练误差和模型测试误差就自然成为学习方法的评估标准。注意,学习方法具体采用的目标函数未必是评估时所使用的标准。关于评估标准这一问题会在之后的博客中提到。
假设学习到的模型是Y=f^(x)
,训练误差是模型关于训练数据数据集的平均损失:
其中N是训练样本容量。
测试误差是模型关于测试数据集的平均损失:
其中N’是测试样本容量。
通常将学习方法对未知数据的预测能力称为泛化能力。显然,我们希望得到泛化误差小的学习器。然而,事先我们并不知道新样本是什么样的,实际能做的是努力使在训练集上的误差最小化。
如果一味追求提高对训练数据的预测能力,所选模型的复杂度往往会比真模型要高。这种现象称为过拟合。过拟合是指学习时选择的模型包含参数过多,以致于出现这一模型对已知数据预测的很好,但对未知数据预测得很差的现象。与过拟合相对的是欠拟合,这是指对训练样本的一般性质尚未学好。
欠拟合比较容易克服,一般只需要增加训练的次数。而过拟合是机器学习面临的关键障碍,各类学习算法都必然带有一些针对过拟合的措施;然而必须认识到,过拟合是无法彻底避免的,我们所能做的只是缓解。这是因为,机器学习面临的问题一般是NP难甚至是更难的,而有效的学习算法必然是在多项式时间内完成的。若可以彻底避免过拟合,这就意味着我们构造性地证明了‘NP = P’,那么你就可以获得图灵奖了。只要相信‘P != NP’,过拟合就无法避免。
关于过拟合与欠拟合图形化的解释,下面那张图中有具体说明。
方差与偏差
偏差方差-分解试图对学习算法的期望泛化误差进行分解。推导的过程这里就不写了,直接给出公式。
这个式子表示的是泛化误差可以分解为偏差、方差与噪声之和。偏差度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力。为什么一个算法会有偏差呢,下面这句话给出了答案:
Biases are introced by the generalizations made in the model including the configuration of the model and the selection of the algorithm to generate the model.
我个人的理解是,因为对于算法的选择乃至于调整参数方法的选择导致了算法是有偏差的。因为算法的选择中就蕴含着偏好。
方差度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响;噪声则表达了在当前任务上任何学习算法所能到达的期望泛化误差的下界,即刻画了问题本身的难度。
泛化能力是由学习算法的能力、数据的充分性以及学习任务本身的难度所共同决定的。给定学习任务,为了取得好的泛化性能,则需使偏差较小,即能充分拟合数据,并且使方差较小,即使得数据扰动产生的影响小。
但偏差与方差是不能同时达到最优的,这称为偏差方差窘境。
这个图所表达的含义相信不用过多地解释了吧。
‘贰’ 机器人是如何学习处理矢量图输入输出的
引言:人工智能受到人们的关注,一直以来人工智能都伴随着机器人学习从而来进行发展,而机器人的学习,是可以通过人们的编程和一次又一次的反复训练来进行的。机器人是如何学习处理矢量图输入输出的?
‘叁’ 机器学习framework怎么画
1 画机器学习framework,需要掌握数据分析或者机器学习的基础知识,同时也需要了解具体的framework的特点和使用方法。
2 机器学习framework通常包含数据的输入输出、数据清洗、模型训练和模型预测等环节,因此需要考虑猛模清楚每个环节的组成和交互关系。
3 可早肆以通过流程图或者框图的方式来展示机器学习framework,其中每个环节需要给出具体的算法或者工具的名称,以及对应的参数和输出结果。
延伸陆知轿:在实际的机器学习过程中,framework的选择和使用对模型的性能和效果有着重要的影响,因此需要根据具体的问题和数据特点来选择最合适的framework。
同时,不同的framework还具有各自的优缺点和适用范围,需要根据实际情况进行权衡和选择。
‘肆’ 机器学习系列 - 3. 数据预处理
KNN的主要优点有:
理论成熟,思想简单,既可以用来做分类也可以用来做回归
天然解决多分类问题,也可用于回归问题
和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感
由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合
KNN的主要缺点有:
计算量大,效率低。即使优凳罩化算法,效率也不高。
高度数据相关,样本不平衡的时候,对稀有类别的预测准确率低
相比决策树模型,KNN模型可解释性不强
维度灾难:随着维度的增加,“看似相近”的两个点之间的距离越来越大,而knn非常依赖距离
KNN优化算法之一。
原理:kd树是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构,且kd树是一种二叉树,表示对k维空间的一个划分。
k-d tree是每个节点均为k维样本点的二叉树,其上的每个样本点代表一个超平面,该超平面垂直于当前划分维度的坐标轴,并在该维度上将空间划分为两部分,一部分在其左子树,另一部分在其右子树。即若当前节点的划分维度为d,其左子树上所有点在d维的坐标值均小于当前值,右子树上所有点在d维的坐标值均大于等于当前值,本定义对其任意子节点均成立。
KD树的构建:
循环依序取数据点的各维度来作为切分维度,
取数据点在该维度的中值作为切分超平面,
将中值左侧的数据点挂在其左子树,将中值右侧的数据点挂在其右子树,
递归处理其子树,直至所有数据点挂载完毕。
对于构建过程,有两个优化点:选择切分维度:根据数据点在各维度上的分布情况,方差越大,分布越分散,从方差大的维度开始切分,有较好的切分效果和平衡性。
确定中值点:预先对原始数据点在所有维度进行一次排序,存储下来,然后在后续的中值选择中,无须每次都对其子集进行排序,提升了性能。也可以从原始数据点中随机选择固定数目的点,晌粗迹然后对其进行排序,每次从这些样本点中取中值,来作为分割超平面。该方式在实践中被证明可以取得很好性能及很好的平衡性。
1.数据标准化:
标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。
数据标准化优缺点:
优点:
Z-Score最大的优点就是简单,容易计算,Z-Score能够应用于数值型的数据,并且不受数据量级的影响,因为它本身的作用就是消除量级给分析带来的不便。
缺点:
估算Z-Score需要总体的平均值与方差,但是这一值在真实的分析与挖掘中很难得到,大多数情况下是用样本的均值与标准差替代;
Z-Score对于数据的分布有一定的要求,正态分布是最有利于Z-Score计算的;
Z-Score消除了数据具有的实际意义,A的Z-Score与B的Z-Score与他们各自的分数不再有关系,因此Z-Score的结果只能用于比较数据间的结果,数据的真实意义还需要还原原值;
在存在异常值时无法保证平衡的特征尺度。
2.归一化:
1)MinMax归一化:区间缩放法,利用于边界值信息。将属性缩放到[0,1]
缺点:
这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义;
MinMaxScaler对异常值的存在非常敏感。
2)MaxAbs 归一化:
单独地缩放和转换每个特征,使得训练集中的每个特征的最大绝对值将为1.0,将属性缩放到[-1,1]。它不会移动/居中数据,因此不会破坏任何稀疏性。
缺点:
这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义;
MaxAbsScaler与先前的缩放器不同,绝对值映射在[0,1]范围内。在仅有正数据时,该缩放器的行为MinMaxScaler与此类似,因此也存在大的异常值。
3)正态分布化:
定义:正则化的过程是将每个样本缩放到单位范数(每个样本的范数为1),如果要使用如二次型(点积)或者其它核方法计算两个样本之间的相似性这个方法会很有用。
该方法是文本分类和聚类分析中经常使宴并用的向量空间模型(Vector Space Model)的基础。
Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(l1-norm,l2-norm)等于1。
4.标准化与归一化对比
1)标准化与归一化的异同
相同点:
它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。
不同点:
目的不同,归一化是为了消除纲量压缩到[0,1]区间;
标准化只是调整特征整体的分布;
归一化与最大,最小值有关;
标准化与均值,标准差有关;
归一化输出在[0,1]之间;
标准化无限制。
2)什么时候用归一化?什么时候用标准化?
如果对输出结果范围有要求,用归一化;
如果数据较为稳定,不存在极端的最大最小值,用归一化;
如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。
3)归一化与标准化的应用场景
在分类、聚类算法中,需要使用距离来度量相似性的时候(如SVM、KNN)、或者使用PCA技术进行降维的时候,标准化(Z-score standardization)表现更好;
在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。
比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0 255]的范围;
基于树的方法不需要进行特征的归一化。
例如随机森林,bagging与boosting等方法。
如果是基于参数的模型或者基于距离的模型,因为需要对参数或者距离进行计算,都需要进行归一化。
一般来说,建议优先使用标准化。对于输出有要求时再尝试别的方法,如归一化或者更加复杂的方法。很多方法都可以将输出范围调整到[0, 1],如果我们对于数据的分布有假设的话,更加有效的方法是使用相对应的概率密度函数来转换。
1.无监督分箱法
1)自定义分箱
2)等距分箱 - pd.cut
3)等频分箱 - pd.qcut
4)聚类分箱:基于k均值聚类的分箱:k均值聚类法将观测值聚为k类,但在聚类过程中需要保证分箱的有序性:第一个分箱中所有观测值都要小于第二个分箱中的观测值,第二个分箱中所有观测值都要小于第三个分箱中的观测值,等等。
5)二值化:二值化可以将数值型(numerical)的feature进行阀值化得到boolean型数据。
2.无监督分箱法
1)卡方分箱法:自底向上的(即基于合并的)数据离散化方法。它依赖于卡方检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。
基本思想:
对于精确的离散化,相对类频率在一个区间内应当完全一致。因此,如果两个相邻的区间具有非常类似的类分布,则这两个区间可以合并;否则,它们应当保持分开。而低卡方值表明它们具有相似的类分布。
2)最小熵法分箱:需要使总熵值达到最小,也就是使分箱能够最大限度地区分因变量的各类别。
熵是信息论中数据无序程度的度量标准,提出信息熵的基本目的是找出某种符号系统的信息量和冗余度之间的关系,以便能用最小的成本和消耗来实现最高效率的数据存储、管理和传递。
数据集的熵越低,说明数据之间的差异越小,最小熵划分就是为了使每箱中的数据具有最好的相似性。给定箱的个数,如果考虑所有可能的分箱情况,最小熵方法得到的箱应该是具有最小熵的分箱。
‘伍’ 机器学习入门报告之 解决问题一般工作流程
机器学习入门报告之 解决问题一般工作流程
对于给定的数据集和问题,用机器学习的方法解决问题的工作一般分为4个步骤:
一. 数据预处理
首先,必须确保数据的格式符合要求。使用标准数据格式可以融合算法和数据源,方便匹配操作。此外还需要为机器学习算法准备特定的数据格式。
然后,直接得到的数据集很少可以直接使用,可能有以下原因:
1. 样本某些属性缺失
2. 某些样本未标记
3. 样本属性过多
4. 没有分出训练集和测试集
5. 不同类别训练样例比例相差太大
对于1,2这样的情况,在该类样本数较少的情况下一般通过删除该类无效样本来清洗数据。
对于3
·过多的特征可能误导学习器
·更多的特征意味着更多的参数需要调整,过拟合的风险加大
·数据的可视化要求维度不高于3
·维度越少训练越快,可尝试的东西越多,能得到更好地效果
·数据的维度可能虚高。
解决方法就是降维,降维分为特征选择法和特征抽取法。
特征选择法:
所谓特征选择,就是选择样本中有用、跟问题相关的特征。事实上并不一定样本的所有属性对具体问题都是有用的,通过一定的方法选择合适的特征可以保证模型更优。常用的方法大致分三类:过滤式、包裹式和嵌入式。
特征抽取法:
特征抽取试图将原始特征空间转换成一个低维特征空间而不丢失主要信息。无法使用选择方法来删除特征,而特征又太罩尺多的时候,这种方法很有效。我们可以通过主成分分析PCA和线性判别式分析和多维标度法来验证。
对于4,为了方便训练和验证模型好坏,数据集一般会以9:1或者其他合适比例(比例选择主要基于实际问题)分为测试集和验证集。如果给定的数据集只是已经标记好的样本,那么划分时必须保证数据集和测试集的分布大致均匀。
对于5,即类别不均衡问题,处理的一个基本策略是—再缩放。
二. 选定算法
一种方式是根据有没有标记样本考虑。
如果是有标记样本,可以考虑有监督学习,反之则是无监督学习。
无监督学习方法主要是聚类。随机选定几个样本,通过一定的算法不停迭代直至收敛或者达到停止条件,然后便将所有样本分成了几类。
对有监督学习而言,根据最终所需要的输出结果
如果是分类问题,可以参考的模型有线性回归及其非线性扩展、决策树、神经网络、支持向量机SVM、规则学习蠢扮等
如果是回归问题,可以认为是分类的连续形式,方法便是以上模型的变种或扩展
如果涉及到概率,可带闷灶以参考的有神经网络、贝叶斯、最大似然、EM、概率图、隐马尔科夫模型、强化学习等
三. 训练算法
将格式化数据输入到算法,从中抽取知识或信息。这里的得到的知识需要存储为计算机可以处理的格式,方便后续使用。
四. 性能评估和优化
如果要评估训练集和测试集的划分效果,常用的有留出法、交叉验证法、自助法、模型调参等
如果模型计算时间太长,可以考虑剪枝
如果是过拟合,则可通过引入正则化项来抑制(补偿原理)
如果单个模型效果不佳,可以集成多个学习器通过一定策略结合,取长补短(集成学习)
‘陆’ python处理图片数据
生成一张纯色的图片
先设置图片的颜色,接着悄腊利用Image模块的new方法新生成一张图片,png格式的图片需要设置成rgba,类似的还有rgb,L(灰度图等),尺寸设定为640,480,这个可以根据自己的情况设定,颜色同样如此。
‘柒’ 机器学习中的数据预处理有哪些常见/重要的工具
不太清携滑楚你说的是搭建pipeline的工具还是说pipeline里面处理数据的工具,就顺道都说一下。
pipeline工具本身一般是控制这些工具的流程,最简单的crontab就定时执行就好,但是有时候会有数据依赖的问题,比如第7步依赖第三步的两个文件以及平行的第6步的文件,这个依赖并不是线性的,而是一个图的形式。当中加上有些辩行腊技术延迟比如有些数据生成失败了需要重启某些特定的步骤重新生成,这个问题就稍微复杂了。crontab一般在这时候就搞不定,需要一些专门的pipeline管理,比如 spotify/luigi · GitHub 或者 Azkaban
2. 预处理文本数据本身一般用一些Linux的工具比如cut啊awk啊等等做数据筛选和清理,自己写一写python小工具做数据的简单组合比如复杂的regex规则组合,比较大的数据归类和抽象一般用Hive之类的hadoop工具都可以,里带棚面也可以插入linux小工具和自己写的工具。
工业界的数据项目多数时间要设计如何清理数据,这和学术界的玩具数据玩起来很不一样,欢迎来到真实的世界。-ITjob
‘捌’ 机器学习的常用方法有哪些
梯度下降是非常常用的优化算法。作为机器学习的基础知识,这是一个必须要掌握的算法。借助本文,让我们来一起详细了解一下这个算法。
前言
本文的代码可以到我的Github上获取:
https://github.com/paulQuei/gradient_descent
本文的算法示例通过Python语言实现,在实现中使用到了numpy和matplotlib。如果你不熟悉这两个工具,请自行在网上搜索教程。
关于优化
大多数学习算法都涉及某种形式的优化。优化指的是改变x以最小化或者最大化某个函数的任务。
我们通常以最小化指代大多数最优化问题。最大化可经由最小化来实现。
我们把要最小化或最大化的函数成为目标函数(objective function)或准则(criterion)。
我们通常使用一个上标*表示最小化或最大化函数的x值,记做这样:
[x^* = arg; min; f(x)]
优化本身是一个非常大的话题。如果有兴趣,可以通过《数值优化》和《运筹学》的书籍进行学习。
模型与假设函数
所有的模型都是错误的,但其中有些是有用的。– George Edward Pelham Box
模型是我们对要分析的数据的一种假设,它是为解决某个具体问题从老洞数据中学习到的,因此它是机器学习最核心的概念。
针对一个问题,通常有大量的模型可以选择。
本文不会深入讨论这方面的内容,关于各种模型请参阅机器学习的相关书籍。本文仅以最简单的线性模型为基础来讨论梯度下降算法。
这里我们先介绍一下在监督学习(supervised learning)中常见的三个符号:
m,描述训练样本的数量
x,描述输入变量或特征
y,描述输出变量或者叫目标值
训练集会包含很多的样本,我们用 表示其中第i个样本。
x是数据样本的特征,y是其目标值。例如,在预测房价的模型中,x是房子的各种信息,例如:面积,楼层,位置等等,y是房子的价格。在图像识别的任务中,x是图形的所有像素点数据,y是图像中包含的目标对象。
我们是希望寻找一个函数,将x映射到y,这个函数要足够的好,以至于能够预测对应的y。由于历史原因,这个函数叫做假设函数(hypothesis function)。
学习的过程如下图所示。即:首先根据已有的数据(称之为训练集)训练我们的算法模型,然后根据模型的假设函数来进行新数据的预测。
线性模型(linear model)正如其名称那样:是希望通过一个直线的形式来描述模式。线性模型的假设函数如下所示:
[h_{ heta}(x) = heta_{0} + heta_{1} * x]
这个公式对于大家来说应该都是非常简单的。如果把它绘制出来,其实就是一条直线。
下图是一个具体的例子,即: 的图形:
在实际的机器学习工程中碰含伍,你会拥有大量的数据。这些数据会来自于某个数据源。它们存储在csv文件中,或者以其他的形式打包。
但是本文作为演示使用,我们通过一些简单的代码自动生成了需要的数据。为了便于计算,演示的数据量也很小。
import numpy as np
max_x = 10
data_size = 10
theta_0 = 5
theta_1 = 2
def get_data:
x = np.linspace(1, max_x, data_size)
noise = np.random.normal(0, 0.2, len(x))
y = theta_0 + theta_1 * x + noise
return x, y
这段代码很简单,我们生成了x范围是 [1, 10] 整数的10条数据。对应的y是以线性模型的形式计算得到,其函数是:。现实中的数据常常受到各种因素的干扰,所以对于y我们故意加上了一些高斯噪声。因此最终的y值为比原先会有轻微的偏离。
最后我们的数据如下所示:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [6.66, 9.11, 11.08, 12.67, 15.12, 16.76, 18.75, 21.35, 22.77, 24.56]
我们可以把这10条数据绘制出来这样就有一个直观的了解了,如下图所示:
虽然演示用的数据是我们通过公式计算得到的。但在实际的工程中,模型的参数是需要我们通过数据学习到的。所以下文我们假设我们不知道这里线性模式的两个参数是什么,而是通过算法的形式求得。
最后再跟已知的参数进行对比以验证我们的算法是否正确。
有了上面的数据,我们可以尝试画一条直线来描述我们的模型。
例如,像下面这样画一条水平的直线:
很显然,这条水平线离数据太远了,非常的不匹配。
那我们可以再画一条斜线。
我们初次画的斜线可能也不贴切,它可能像下面这样:
最后我们通过不断尝试,找到了最终最合适的那条,如下所示:
梯度下降算法的计算过程,就和这种本能式的试探是类似的,它就是不停的迭代,一步步的接近最终的结果。
代价函数
上面我们尝试了几次通过一条直线来拟合(fitting)已有的数据。
二维平面上的一条直线可以通过两个参数唯一的确定,两个参数的确定也即模型的确定。那如何描述模型与数据的拟合程度呢?答案就是代价函数。
代价函数(cost function)描述了学习到的模型与实际结果的偏差程度。以上面的三幅图为例,最后一幅图中的红线相比第一条水平的绿线,其偏离程度(代价)应该是更小的。
很显然,我们希望我们的假设函数与数据尽可能的贴近,也就是说:希望代价函数的结果尽可能的小。这就涉及到结果的优化,而梯度下降就是寻找最小值的方法之一。
对于每一个样本,假设函数会依据计算出一个估算值,我们常常用来表示。即 。
很自然的,我们会想到,通过下面这个公式来描述我们的模型与实际值的偏差程度:
[(h_ heta(x^i) - y^i)^2 = (widehat{y}^{i} - y^i)^2 = ( heta_{0} + heta_{1} * x^{i} - y^{i})^2]
请注意, 是实际数据的值, 是我们的模型的估算值。前者对应了上图中的离散点的y坐标,后者对应了离散点在直线上投影点的y坐标。
每一条数据都会存在一个偏差值,而代价函数就是对所有样本的偏差求平均值,其计算公式如下所示:
[L( heta) = frac {1}{m} sum_{i=1}^{m}(h_ heta(x^i) - y^i)^2 = frac {1}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i})^2]
当损失函数的结果越小,则意味着通过我们的假设函数估算出的结果与真实值越接近。这也就是为什么我们要最小化损失函数的原因。
借助上面这个公式,我们可以写一个函数来实现代价函数:
def cost_function(x, y, t0, t1):
cost_sum = 0
for i in range(len(x)):
cost_item = np.power(t0 + t1 * x[i] - y[i], 2)
cost_sum += cost_item
return cost_sum / len(x)
这个函数的代码应该不用多做解释,它就是根据上面的完成计算。
我们可以尝试选取不同的 和 组合来计算代价函数的值,然后将结果绘制出来:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
theta_0 = 5
theta_1 = 2
def draw_cost(x, y):
fig = plt.figure(figsize=(10, 8))
ax = fig.gca(projection='3d')
scatter_count = 100
radius = 1
t0_range = np.linspace(theta_0 - radius, theta_0 + radius, scatter_count)
t1_range = np.linspace(theta_1 - radius, theta_1 + radius, scatter_count)
cost = np.zeros((len(t0_range), len(t1_range)))
for a in range(len(t0_range)):
for b in range(len(t1_range)):
cost[a][b] = cost_function(x, y, t0_range[a], t1_range[b])
t0, t1 = np.meshgrid(t0_range, t1_range)
ax.set_xlabel('theta_0')
ax.set_ylabel('theta_1')
ax.plot_surface(t0, t1, cost, cmap=cm.hsv)
在这段代码中,我们对 和 各自指定了一个范围进行100次的采样,然后以不同的 组合对来计算代价函数的值。
如果我们将所有点的代价函数值绘制出来,其结果如下图所示:
从这个图形中我们可以看出,当 越接近 [5, 2]时其结果(偏差)越小。相反,离得越远,结果越大。
直观解释
从上面这幅图中我们可以看出,代价函数在不同的位置结果大小不同。
从三维的角度来看,这就和地面的高低起伏一样。最高的地方就好像是山顶。
而我们的目标就是:从任意一点作为起点,能够快速寻找到一条路径并以此到达图形最低点(代价值最小)的位置。
而梯度下降的算法过程就和我们从山顶想要快速下山的做法是一样的。
在生活中,我们很自然会想到沿着最陡峭的路往下行是下山速度最快的。如下面这幅图所示:
针对这幅图,细心的读者可能很快就会有很多的疑问,例如:
对于一个函数,怎么确定下行的方向?
每一步该往前走多远?
有没有可能停留在半山腰的平台上?
这些问题也就是本文接下来要讨论的内容。
算法描述
梯度下降算法最开始的一点就是需要确定下降的方向,即:梯度。
我们常常用 来表示梯度。
对于一个二维空间的曲线来说,梯度就是其切线的方向。如下图所示:
而对于更高维空间的函数来说,梯度由所有变量的偏导数决定。
其表达式如下所示:
[ abla f({ heta}) = ( frac{partial f({ heta})}{partial heta_1} , frac{partial f({ heta})}{partial heta_2} , ... , frac{partial f({ heta})}{partial heta_n} )]
在机器学习中,我们主要是用梯度下降算法来最小化代价函数,记做:
[ heta ^* = arg min L( heta)]
其中,L是代价函数,是参数。
梯度下降算法的主体逻辑很简单,就是沿着梯度的方向一直下降,直到参数收敛为止。
记做:
[ heta ^{k + 1}_i = heta^{k}_i - lambda abla f( heta^{k})]
这里有几点需要说明:
收敛是指函数的变化率很小。具体选择多少合适需要根据具体的项目来确定。在演示项目中我们可以选择0.01或者0.001这样的值。不同的值将影响算法的迭代次数,因为在梯度下降的最后,我们会越来越接近平坦的地方,这个时候函数的变化率也越来越小。如果选择一个很小的值,将可能导致算法迭代次数暴增。
公式中的 称作步长,也称作学习率(learning rate)。它决定了每一步往前走多远,关于这个值我们会在下文中详细讲解。你可以暂时人为它是一个类似0.01或0.001的固定值。
在具体的项目,我们不会让算法无休止的运行下去,所以通常会设置一个迭代次数的最大上限。
线性回归的梯度下降
有了上面的知识,我们可以回到线性模型代价函数的梯度下降算法实现了。
首先,根据代价函数我们可以得到梯度向量如下:
[ abla f({ heta}) = (frac{partial L( heta)}{ partial heta_{0}}, frac{ partial L( heta)}{ partial heta_{1}}) = (frac {2}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) , frac {2}{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) x^{i})]
接着,将每个偏导数带入迭代的公式中,得到:
[ heta_{0} := heta_{0} - lambda frac{partial L( heta_{0})}{ partial heta_{0}} = heta_{0} - frac {2 lambda }{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) heta_{1} := heta_{1} - lambda frac{partial L( heta_{1})}{ partial heta_{1}} = heta_{1} - frac {2 lambda }{m} sum_{i=1}^{m}( heta_{0} + heta_{1} * x^{i} - y^{i}) x^{i}]
由此就可以通过代码实现我们的梯度下降算法了,算法逻辑并不复杂:
learning_rate = 0.01
def gradient_descent(x, y):
t0 = 10
t1 = 10
delta = 0.001
for times in range(1000):
sum1 = 0
sum2 = 0
for i in range(len(x)):
sum1 += (t0 + t1 * x[i] - y[i])
sum2 += (t0 + t1 * x[i] - y[i]) * x[i]
t0_ = t0 - 2 * learning_rate * sum1 / len(x)
t1_ = t1 - 2 * learning_rate * sum2 / len(x)
print('Times: {}, gradient: [{}, {}]'.format(times, t0_, t1_))
if (abs(t0 - t0_) < delta and abs(t1 - t1_) < delta):
print('Gradient descent finish')
return t0_, t1_
t0 = t0_
t1 = t1_
print('Gradient descent too many times')
return t0, t1
这段代码说明如下:
我们随机选择了 都为10作为起点
设置最多迭代1000次
收敛的范围设为0.001
学习步长设为0.01
如果我们将算法迭代过程中求得的线性模式绘制出来,可以得到下面这幅动态图:
最后算法得到的结果如下:
Times: 657, gradient: [5.196562662718697, 1.952931052920264]
Times: 658, gradient: [5.195558390180733, 1.9530753071808193]
Times: 659, gradient: [5.194558335124868, 1.9532189556399233]
Times: 660, gradient: [5.193562479839619, 1.9533620008416623]
Gradient descent finish
从输出中可以看出,算法迭代了660次就收敛了。这时的结果[5.193562479839619, 1.9533620008416623],这已经比较接近目标值 [5, 2]了。如果需要更高的精度,可以将delta的值调的更小,当然,此时会需要更多的迭代次数。
高维扩展
虽然我们举的例子是二维的,但是对于更高维的情况也是类似的。同样是根据迭代的公式进行运算即可:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - frac{2lambda}{m} sum_{i=1}^{m}(h_ heta(x^{k})-y^k)x_i^k]
这里的下标i表示第i个参数,上标k表示第k个数据。
梯度下降家族BGD
在上面的内容中我们看到,算法的每一次迭代都需要把所有样本进行遍历处理。这种做法称为之Batch Gradient Descent,简称BGD。作为演示示例只有10条数据,这是没有问题的。
但在实际的项目中,数据集的数量可能是几百万几千万条,这时候每一步迭代的计算量就会非常的大了。
于是就有了下面两个变种。
SGD
Stochastic Gradient Descent,简称SGD,这种算法是每次从样本集中仅仅选择一个样本来进行计算。很显然,这样做算法在每一步的计算量一下就少了很多。
其算法公式如下:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - lambda(h_ heta(x^k)-y^k)x_i^k]
当然,减少算法计算量也是有代价的,那就是:算法结果会强依赖于随机取到的数据情况,这可能会导致算法的最终结果不太令人满意。
MBGD
以上两种做法其实是两个极端,一个是每次用到了所有数据,另一个是每次只用一个数据。
我们自然就会想到两者取其中的方法:每次选择一小部分数据进行迭代。这样既避免了数据集过大导致每次迭代计算量过大的问题,也避免了单个数据对算法的影响。
这种算法称之为Mini-batch Gradient Descent,简称MBGD。
其算法公式如下:
[ heta_{i} = heta_{i} - lambda frac {partial L( heta)}{partial heta_i} = heta_{i} - frac{2lambda}{m} sum_{i=a}^{a + b}(h_ heta(x^k)-y^k)x_i^k]
当然,我们可以认为SGD是Mini-batch为1的特例。
针对上面提到的算法变种,该如何选择呢?
下面是Andrew Ng给出的建议:
如果样本数量较小(例如小于等于2000),选择BGD即可。
如果样本数量很大,选择 来进行MBGD,例如:64,128,256,512。
下表是 Optimization for Deep Learning 中对三种算法的对比
方法准确性更新速度内存占用在线学习BGD好慢高否SGD好(with annealing)快低是MBGD好中等中等是
算法优化
式7是算法的基本形式,在这个基础上有很多人进行了更多的研究。接下来我们介绍几种梯度下降算法的优化方法。
Momentum
Momentum是动量的意思。这个算法的思想就是借助了动力学的模型:每次算法的迭代会使用到上一次的速度作为依据。
算法的公式如下:
[v^t = gamma v^{t - 1} + lambda abla f( heta) heta = heta - v_t]
对比式7可以看出,这个算法的主要区别就是引入了,并且,每个时刻的受前一个时刻的影响。
从形式上看,动量算法引入了变量 v 充当速度角色——它代表参数在参数空间移动的方向和速率。速度被设为负梯度的指数衰减平均。名称动量来自物理类比,根据牛顿运动定律,负梯度是移动参数空间中粒子的力。动量在物理学上定义为质量乘以速度。在动量学习算法中,我们假设是单位质量,因此速度向量 v 也可以看作是粒子的动量。
对于可以取值0,而是一个常量,设为0.9是一个比较好的选择。
下图是momentum算法的效果对比:
对原来的算法稍加修改就可以增加动量效果:
def gradient_descent_with_momentum(x, y):
t0 = 10
t1 = 10
delta = 0.001
v0 = 0
v1 = 0
gamma = 0.9
for times in range(1000):
sum1 = 0
sum2 = 0
for i in range(len(x)):
sum1 += (t0 + t1 * x[i] - y[i])
sum2 += (t0 + t1 * x[i] - y[i]) * x[i]
v0 = gamma * v0 + 2 * learning_rate * sum1 / len(x)
v1 = gamma * v1 + 2 * learning_rate * sum2 / len(x)
t0_ = t0 - v0
t1_ = t1 - v1
print('Times: {}, gradient: [{}, {}]'.format(times, t0_, t1_))
if (abs(t0 - t0_) < delta and abs(t1 - t1_) < delta):
print('Gradient descent finish')
return t0_, t1_
t0 = t0_
t1 = t1_
print('Gradient descent too many times')
return t0, t1
以下是该算法的输出:
Times: 125, gradient: [4.955453758569991, 2.000005017897775]
Times: 126, gradient: [4.955309381126545, 1.9956928964532015]
Times: 127, gradient: [4.9542964317327005, 1.9855674828684156]
Times: 128, gradient: [4.9536358220657, 1.9781180992510465]
Times: 129, gradient: [4.95412496254411, 1.9788858350530971]
Gradient descent finish
从结果可以看出,改进的算法只用了129次迭代就收敛了。速度比原来660次快了很多。
同样的,我们可以把算法计算的过程做成动态图:
对比原始的算法过程可以看出,改进算法最大的区别是:在寻找目标值时会在最终结果上下跳动,但是越往后跳动的幅度越小,这也就是动量所产生的效果。
Learning Rate 优化
至此,你可能还是好奇该如何设定学习率的值。
事实上,这个值的选取需要一定的经验或者反复尝试才能确定。
关键在于,这个值的选取不能过大也不能过小。
如果这个值过小,会导致每一次迭代的步长很小,其结果就是算法需要迭代非常多的次数。
那么,如果这个值过大会怎么样呢?其结果就是:算法可能在结果的周围来回震荡,却落不到目标的点上。下面这幅图描述了这个现象:
事实上,学习率的取值未必一定要是一个常数,关于这个值的设定有很多的研究。
下面是比较常见的一些改进算法。
AdaGrad
AdaGrad是Adaptive Gradient的简写,该算法会为每个参数设定不同的学习率。它使用历史梯度的平方和作为基础来进行计算。
其算法公式如下:
[ heta_i = heta_i - frac{lambda}{sqrt{G_t + epsilon}} abla f( heta)]
对比式7,这里的改动就在于分号下面的根号。
根号中有两个符号,第二个符号比较好理解,它就是为了避免除0而人为引入的一个很小的常数,例如可以设为:0.001。
第一个符号的表达式展开如下:
[G_t = sum_{i = 1}^{t} abla f( heta){i} abla f( heta){i}^{T}]
这个值其实是历史中每次梯度的平方的累加和。
AdaGrad算法能够在训练中自动的对learning rate进行调整,对于出现频率较低参数采用较大的学习率;相反,对于出现频率较高的参数采用较小的学习率。因此,Adagrad非常适合处理稀疏数据。
但该算法的缺点是它可能导致学习率非常小以至于算法收敛非常的慢。
关于这个算法的直观解释可以看李宏毅教授的视频课程:ML Lecture 3-1: Gradient Descent。
RMSProp
RMS是Root Mean Square的简写。RMSProp是AI教父Geoff Hinton提出的一种自适应学习率方法。AdaGrad会累加之前所有的梯度平方,而RMSProp仅仅是计算对应的平均值,因此可缓解Adagrad算法学习率下降较快的问题。
该算法的公式如下:
[E[ abla f( heta_{i})^2]^{t} = gamma E[ abla f( heta_{i})^2]^{t - 1} + (1-gamma)( abla f( heta_{i})^{t})^{2} heta_i = heta_i - frac{lambda}{sqrt{E[g^2]^{t+1} + epsilon}} abla f( heta_{i})]
类似的,是为了避免除0而引入。 是衰退参数,通常设为0.9。
这里的 是t时刻梯度平方的平均值。
Adam
Adam是Adaptive Moment Estimation的简写。它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。
Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
该算法公式如下:
[m^{t} = eta_{1} m^{t-1} + (1-eta_{1}) abla f( heta) v^{t} = eta_{2} v^{t-1} + (1-eta_{2}) abla f( heta)^2 widehat{m}^{t} = frac{m^{t}}{1 - eta^{t}_1} widehat{v}^{t} = frac{v^{t}}{1 - eta^{t}_2} heta = heta - frac{lambda}{sqrt{widehat{v}^{t}} + epsilon}widehat{m}^{t}]
,分别是对梯度的一阶矩估计和二阶矩估计。, 是对,的校正,这样可以近似为对期望的无偏估计。
Adam算法的提出者建议 默认值为0.9,默认值为0.999,默认值为 。
在实际应用中 ,Adam较为常用,它可以比较快地得到一个预估结果。
优化小结
这里我们列举了几种优化算法。它们很难说哪种最好,不同的算法适合于不同的场景。在实际的工程中,可能需要逐个尝试一下才能确定选择哪一个,这个过程也是目前现阶段AI项目要经历的工序之一。
实际上,该方面的研究远不止于此,如果有兴趣,可以继续阅读 《Sebastian Ruder: An overview of gradient descent optimization algorithms》 这篇论文或者 Optimization for Deep Learning 这个Slides进行更多的研究。
由于篇幅所限,这里不再继续展开了。
算法限制
梯度下降算法存在一定的限制。首先,它要求函数必须是可微分的,对于不可微的函数,无法使用这种方法。
除此之外,在某些情况下,使用梯度下降算法在接近极值点的时候可能收敛速度很慢,或者产生Z字形的震荡。这一点需要通过调整学习率来回避。
另外,梯度下降还会遇到下面两类问题。
局部最小值
局部最小值(Local Minima)指的是,我们找到的最小值仅仅是一个区域内的最小值,而并非全局的。由于算法的起点是随意取的,以下面这个图形为例,我们很容易落到局部最小值的点里面。
这就是好像你从上顶往下走,你第一次走到的平台未必是山脚,它有可能只是半山腰的一个平台的而已。
算法的起点决定了算法收敛的速度以及是否会落到局部最小值上。
坏消息是,目前似乎没有特别好的方法来确定选取那个点作为起点是比较好的,这就有一点看运气的成分了。多次尝试不同的随机点或许是一个比较好的方法,这也就是为什么做算法的优化这项工作是特别消耗时间的了。
但好消息是:
对于凸函数或者凹函数来说,不存在局部极值的问题。其局部极值一定是全局极值。
最近的一些研究表明,某些局部极值并没有想象中的那么糟糕,它们已经非常的接近全局极值所带来的结果了。
鞍点
除了Local Minima,在梯度下降的过程中,还有可能遇到另外一种情况,即:鞍点(Saddle Point)。鞍点指的是我们找到点某个点确实是梯度为0,但它却不是函数的极值,它的周围既有比它小的值,也有比它大的值。这就好像马鞍一样。
如下图所示:
多类随机函数表现出以下性质:在低维空间中,局部极值很普遍。但在高维空间中,局部极值比较少见,而鞍点则很常见。
不过对于鞍点,可以通过数学方法Hessian矩阵来确定。关于这点,这里就不再展开了,有兴趣的读者可以以这里提供的几个链接继续探索。
参考资料与推荐读物
Wikipeida: Gradient descent
Sebastian Ruder: An overview of gradient descent optimization algorithms
吴恩达:机器学习
吴恩达:深度学习
Peter Flach:机器学习
李宏毅 - ML Lecture 3-1: Gradient Descent
PDF: 李宏毅 - Gradient Descent
Intro to optimization in deep learning: Gradient Descent
Intro to optimization in deep learning: Momentum, RMSProp and Adam
Stochastic Gradient Descent – Mini-batch and more
刘建平Pinard - 梯度下降(Gradient Descent)小结
多元函数的偏导数、方向导数、梯度以及微分之间的关系思考
[Machine Learning] 梯度下降法的三种形式BGD、SGD以及MBGD
‘玖’ 机器学习是什么
提起机器学习,我们不得不给机器学习下一个准确的定义。在直观的层面,如果说计算机科学是研究关于算法的科学,那么机器学习就是研究关于“学习算法”的科学,或者说,不同于一般的显式编程,机器学习就是研究如何使得计算机在无法被显式编程的情况下进行学习的领域,需要注意的是,显式与否都是对于人类而言的——人类能否明确的搞清楚每个决策步骤,对于计算机而言,构成不同算法的代码与指令没有任何区别。
更加精确的说,机器学习的定义如下:
A computer program is said to learn from experience E with respect to some task T and some performance measure P, if its performance on T, as measured by P, improves with experience E.
一个(机器学习)的程序就是可以从经验数据E中对任务T进行学习的算法,它在任务T上的性能度量P会随着对于经验数据E的学习而变得更好
由于机器学习必然利用了某些经验,它们常常数据的形式存在,我们称之为数据集,其中的每个数据称为记录。例如我们通过一个人的性别、年龄和身高预测他是否患某种常见疾病,有以下数据:
(性别:男;年龄:18;身高:174;是否得病:否)
(性别:女;年龄:17;身高:164;是否得病:是)
(性别:男;年龄:20;身高:181;是否得病:是)
(性别:女;年龄:16;身高:161;是否得病:是) ……
这可以被称为一个数据集,其中每个人的数据称为记录。在记录中,关于该对象的描述型数据称为属性,由于属性往往有很多个——如上文的年龄,身高等,可以构成属性向量,这些向量张成的空间称为属性空间。而我们的算法需要预测那个量被称为标记(label)——在上文中便是“得病与否”。在有的数据集中存在标记,有的不存在。标记构成的空间称为标记空间,也称为输出空间。
显然,由于我们只能得到整个总体数据的一部分——即训练样本,我们程序得到的模型却不能只适应于这个训练样本,它宽孙必须对整个总体数据都有比较好的预测效果。这就是说我们的模型必须具有泛化的能力。
我们训练得到棚梁的模型称为一个假设,所有的模型一起构成了假设空间。显然,可能有多种假设空间和训练数据一致——就好像对于一个知识点很少的课堂学习,有不少人能得到很高的分数,但是对于整个总体数据,学习的不同模型显然效果差别很大——真正考验很多难的知识点的考试,考验把上述表面上的学霸分开。
每个假设——也就是训练的模型,必然有其归纳偏好,也就是说,在训练集中没有见过的情况,或者两者皆可的情况,模型会选择哪种。归纳偏好是模型进行泛化链巧运的能力基础。
‘拾’ 关于机器学习应用不得不思考哪些问题
机器学习是一种能够赋予机器学习的能力以此让它完成直接编程无法完成的功能的方法。但从实践的意义上来说,机器学习是一种通过利用数据,训练出模型,然后使用模型预测的一种方法。
让我们具体看一个例子。
图4房价的例子
拿国民话题的房子来说。现在我手里有一栋房子需要售卖,我应该给它标上多大的价格?房子的面积是100平方米,价格是100万,120万,还是140万?
很显然,我希望获得房价与面积的某种规律。那么我该如何获得这个规律?用报纸上的房价平均数据么?还是参考别人面积相似的?无论哪种,似乎都并不是太靠谱。
我现在希望获得一个合理的,并且能够最大程度的反映面积与房价关系的规律。于是我调查了周边与我房型类似的一些房子,获得一组数据。这组数据中包含了大大小小房子的面积与价格,如果我能从这组数据中找出面积与价格的规律,那么我就可以得出房子的价格。
对规律的寻找很简单,拟合出一条直线,让它“穿过”所有的点,并且与各个点的距离尽可能的小。
通过这条直线,我获得了一个能够最佳反映房价与面积规律的规律。这条直线同时也是一个下式所表明的函数:房价=面积*a+b
上述中的a、b都是直线的参数。获得这些参数以后,我就可以计算出房子的价格。
假设a=0.75,b=50,则房价=100*0.75+50=125万。这个结果与我前面所列的100万,120万,140万都不一样。由于这条直线综合考虑了大部分的情况,因此从“统计”意义上来说,这是一个最合理的预测。
在求解过程中透露出了两个信息:
1.房价模型是根据拟合的函数类型决定的。如果是直线,那么拟合出的就是直线方程。如果是其他类型的线,例如抛物线,那么拟合出的就是抛物线方程。机器学习有众多算法,一些强力算法可以拟合出复杂的非线性模型,用来反映一些不是直线所能表达的情况。
2.如果我的数据越多,我的模型就越能够考虑到越多的情况,由此对于新情况的预测效果可能就越好。这是机器学习界“数据为王”思想的一个体现。一般来说(不是绝对),数据越多,最后机器学习生成的模型预测的效果越好。
通过我拟合直线的过程,我们可以对机器学习过程做一个完整的回顾。首先,我们需要在计算机中存储历史的数据。接着,我们将这些数据通过机器学习算法进行处理,这个过程在机器学习中叫做“训练”,处理的结果可以被我们用来对新的数据进行预测,这个结果一般称之为“模型”。对新数据的预测过程在机器学习中叫做“预测”。“训练”与“预测”是机器学习的两个过程,“模型”则是过程的中间输出结果,“训练”产生“模型”,“模型”指导“预测”。