引言
提起笔来写这篇博客,突然有点愧疚和尴尬。愧疚的是,工作杂事多,加之懒癌严重,导致这个系列一直没有更新,向关注该系列的同学们道个歉。尴尬的是,按理说,机器学习介绍与算法一览应该放在最前面写,详细的应用建议应该在讲完机器学习常用算法之后写,突然莫名奇妙在中间插播这么一篇,好像有点打乱主线。
老话说『亡羊补牢,为时未晚』,前面开头忘讲的东西,咱在这块儿补上。我们先带着大家过一遍传统机器学习算法,基本思想和用途。把问题解决思路和方法应用建议提前到这里的想法也很简单,希望能提前给大家一些小建议,对于某些容易出错的地方也先给大家打个预防针,这样在理解后续相应机器学习算法之后,使用起来也有一定的章法。
2.机器学习算法简述
按照不同的分类标准,可以把机器学习的算法做不同的分类。
2.1 从机器学习问题角度分类
我们先从机器学习问题本身分类的角度来看,我们可以分成下列类型的算法:
监督学习算法
机器学习中有一大部分的问题属于『监督学习』的范畴,简单口语化地说明,这类问题中,给定的训练样本中,每个样本的输入x都对应一个确定的结果y,我们需要训练出一个模型(数学上看是一个x→y的映射关系f),在未知的样本x′给定后,我们能对结果y′做出预测。
这里的预测结果如果是离散值(很多时候是类别类型,比如邮件分类问题中的垃圾邮件/普通邮件,比如用户会/不会购买某商品),那么我们把它叫做分类问题(classification problem);如果预测结果是连续值(比如房价,股票价格等等),那么我们把它叫做回归问题(regression problem)。
有一系列的机器学习算法是用以解决监督学习问题的,比如最经典的用于分类问题的朴素贝叶斯、逻辑回归、支持向量机等等;比如说用于回归问题的线性回归等等。
无监督学习
有另外一类问题,给我们的样本并没有给出『标签/标准答案』,就是一系列的样本。而我们需要做的事情是,在一些样本中抽取出通用的规则。这叫做『无监督学习』。包括关联规则和聚类算法在内的一系列机器学习算法都属于这个范畴。
半监督学习
这类问题给出的训练数据,有一部分有标签,有一部分没有标签。我们想学习出数据组织结构的同时,也能做相应的预测。此类问题相对应的机器学习算法有自训练(Self-Training)、直推学习(Transductive Learning)、生成式模型(Generative Model)等。
总体说来,最常见是前两类问题,而对应前两类问题的一些机器学习算法如下:
2.2 从算法的功能角度分类
我们也可以从算法的共性(比如功能,运作方式)角度对机器学习算法分类。下面我们根据算法的共性去对它们归个类。不过需要注意的是,我们下面的归类方法可能对分类和回归有比较强的倾向性,而这两类问题也是最常遇到的。
2.2.1 回归算法(Regression Algorithms)
Ordinary Least Squares Regression (OLSR)
Linear Regression
Logistic Regression
Stepwise Regression
Locally Estimated Scatterplot Smoothing (LOESS)
Multivariate Adaptive Regression Splines (MARS)
2.2.2 基于实例的算法(Instance-based Algorithms)
k-Nearest Neighbour (kNN)
Learning Vector Quantization (LVQ)
Self-Organizing Map (SOM)
Locally Weighted Learning (LWL)
2.2.3 决策树类算法(Decision Tree Algorithms)
Classification and Regression Tree (CART)
Iterative Dichotomiser 3 (ID3)
C4.5 and C5.0 (different versions of a powerful approach)
Chi-squared Automatic Interaction Detection (CHAID)
M5
Conditional Decision Trees
2.2.4 贝叶斯类算法(Bayesian Algorithms)
Naive Bayes
Gaussian Naive Bayes
Multinomial Naive Bayes
Averaged One-Dependence Estimators (AODE)
Bayesian Belief Network (BBN)
Bayesian Network (BN)
2.2.5 聚类算法(Clustering Algorithms)
k-Means
Hierarchical Clustering
Expectation Maximisation (EM)
2.2.6 关联规则算法(Association Rule Learning Algorithms)
Apriori algorithm
Eclat algorithm
2.2.7 人工神经网络类算法(Artificial Neural Network Algorithms)
Perceptron
Back-Propagation
Radial Basis Function Network (RBFN)
2.2.8 深度学习(Deep Learning Algorithms)
Deep Boltzmann Machine (DBM)
Deep Belief Networks (DBN)
Convolutional Neural Network (CNN)
Stacked Auto-Encoders
2.2.9 降维算法(Dimensionality Reduction Algorithms)
有意思的是,降维算法一般在数据的可视化,或者是降低数据计算空间有很大的作用。它作为一种机器学习的算法,很多时候用它先处理数据,再灌入别的机器学习算法学习。主要的降维算法包括:
Principal Component Analysis (PCA)
Principal Component Regression (PCR)
Partial Least Squares Regression (PLSR)
Sammon Mapping
Multidimensional Scaling (MDS)
Linear Discriminant Analysis (LDA)
Mixture Discriminant Analysis (MDA)
Quadratic Discriminant Analysis (QDA)
Flexible Discriminant Analysis (FDA)
2.2.10 模型融合算法(Ensemble Algorithms)
Random Forest
Boosting
Bootstrapped Aggregation (Bagging)
AdaBoost
Stacked Generalization (blending)
Gradient Boosting Machines (GBM)
Gradient Boosted Regression Trees (GBRT)
2.3 机器学习算法使用图谱
scikit-learn作为一个丰富的python机器学习库,实现了绝大多数机器学习的算法,有相当多的人在使用,于是我这里很无耻地把machine learning cheat sheet for sklearn搬过来了,原文可以看这里。哈哈,既然讲机器学习,我们就用机器学习的语言来解释一下,这是针对实际应用场景的各种条件限制,对scikit-learn里完成的算法构建的一颗决策树,每一组条件都是对应一条路径,能找到相对较为合适的一些解决方法,具体如下:
3. 机器学习问题解决思路
上面带着代价走马观花过了一遍机器学习的若干算法,下面我们试着总结总结在拿到一个实际问题的时候,如果着手使用机器学习算法去解决问题,其中的一些注意点以及核心思路。主要包括以下内容:
拿到数据后怎么了解数据(可视化)
选择最贴切的机器学习算法
定位模型状态(过/欠拟合)以及解决方法
大量极的数据的特征分析与可视化
各种损失函数(loss function)的优缺点及如何选择
多说一句,这里写的这个小教程,主要是作为一个通用的建议和指导方案,你不一定要严格按照这个流程解决机器学习问题。
3.1 数据与可视化
我们先使用scikit-learn的make_classification函数来生产一份分类数据,然后模拟一下拿到实际数据后我们需要做的事情。
我们在处理任何数据相关的问题时,了解数据都是很有必要的,而可视化可以帮助我们更好地直观理解数据的分布和特性
数据的可视化有很多工具包可以用,比如下面我们用来做数据可视化的工具包Seaborn。最简单的可视化就是数据散列分布图和柱状图,这个可以用Seanborn的pairplot来完成。以下图中2种颜色表示2种不同的类,因为20维的可视化没有办法在平面表示,我们取出了一部分维度,两两组成pair看数据在这2个维度平面上的分布状况,代码和结果如下:
插一句,这里的维度只有20,所以这个相关度计算并不费太大力气,然而实际情形中,你完全有可能有远高于这个数字的特征维度,同时样本量也可能多很多,那种情形下我们可能要先做一些处理,再来实现可视化了。别着急,一会儿我们会讲到。
3.2 机器学习算法选择
数据的情况我们大致看了一眼,确定一些特征维度之后,我们可以考虑先选用机器学习算法做一个baseline的系统出来了。这里我们继续参照上面提到过的机器学习算法使用图谱。
我们只有1000个数据样本,是分类问题,同时是一个有监督学习,因此我们根据图谱里教的方法,使用LinearSVC(support vector classification with linear kernel)试试。注意,LinearSVC需要选择正则化方法以缓解过拟合问题;我们这里选择使用最多的L2正则化,并把惩罚系数C设为10。我们改写一下sklearn中的学习曲线绘制函数,画出训练集和交叉验证集上的得分:
3.2.1 过拟合的定位与解决
问题来了,过拟合咋办?
针对过拟合,有几种办法可以处理:
增大样本量
这个比较好理解吧,过拟合的主要原因是模型太努力地去记住训练样本的分布状况,而加大样本量,可以使得训练集的分布更加具备普适性,噪声对整体的影响下降。恩,我们提高点样本量试试:
减少特征的量(只用我们觉得有效的特征)
比如在这个例子中,我们之前的数据可视化和分析的结果表明,第11和14维特征包含的信息对识别类别非常有用,我们可以只用它们。
从另外一个角度看,我们之所以做特征选择,是想降低模型的复杂度,而更不容易刻画到噪声数据的分布。从这个角度出发,我们还可以有(1)多项式你和模型中降低多项式次数
(2)神经网络中减少神经网络的层数和每层的结点数 (c)SVM中增加RBF-kernel的bandwidth等方式来降低模型的复杂度。
话说回来,即使以上提到的办法降低模型复杂度后,好像能在一定程度上缓解过拟合,但是我们一般还是不建议一遇到过拟合,就用这些方法处理,优先用下面的方法:
增强正则化作用(比如说这里是减小LinearSVC中的C参数)
正则化是我认为在不损失信息的情况下,最有效的缓解过拟合现象的方法。
使用新的C参数,我们再看看学习曲线:
我们知道:
l2正则化,它对于最后的特征权重的影响是,尽量打散权重到每个特征维度上,不让权重集中在某些维度上,出现权重特别高的特征。
而l1正则化,它对于最后的特征权重的影响是,让特征获得的权重稀疏化,也就是对结果影响不那么大的特征,干脆就拿不着权重。
那基于这个理论,我们可以把SVC中的正则化替换成l1正则化,让其自动甄别哪些特征应该留下权重。
好了,我们一起来看看最后特征获得的权重:
3.2.2 欠拟合定位与解决
我们再随机生成一份数据[1000*20]的数据(但是分布和之前有变化),重新使用LinearSVC来做分类。
不要盲目动手收集更多资料,或者调整正则化参数。我们从学习曲线上其实可以看出来,训练集上的准确度和交叉验证集上的准确度都很低,这其实就对应了我们说的『欠拟合』状态。别急,我们回到我们的数据,还是可视化看看:
那我们又怎么解决欠拟合问题呢?通常有下面一些方法:
调整你的特征(找更有效的特征!!)
比如说我们观察完现在的数据分布,然后我们先对数据做个映射:
使用更复杂一点的模型(比如说用非线性的核函数)
我们对模型稍微调整了一下,用了一个复杂一些的非线性rbf kernel:
3.3 关于大数据样本集和高维特征空间
我们在小样本的toy dataset上,怎么捣鼓都有好的方法。但是当数据量和特征样本空间膨胀非常厉害时,很多东西就没有那么好使了,至少是一个很耗时的过程。举个例子说,我们现在重新生成一份数据集,但是这次,我们生成更多的数据,更高的特征维度,而分类的类别也提高到5。
3.3.1 大数据情形下的模型选择与学习曲线
在上面提到的那样一份数据上,我们用LinearSVC可能就会有点慢了,我们注意到机器学习算法使用图谱推荐我们使用SGDClassifier。其实本质上说,这个模型也是一个线性核函数的模型,不同的地方是,它使用了随机梯度下降做训练,所以每次并没有使用全部的样本,收敛速度会快很多。再多提一点,SGDClassifier对于特征的幅度非常敏感,也就是说,我们在把数据灌给它之前,应该先对特征做幅度调整,当然,用sklearn的StandardScaler可以很方便地完成这一点。
StandardScaler每次只使用一部分(mini-batch)做训练,在这种情况下,我们使用交叉验证(cross-validation)并不是很合适,我们会使用相对应的progressive validation:简单解释一下,estimator每次只会拿下一个待训练batch在本次做评估,然后训练完之后,再在这个batch上做一次评估,看看是否有优化。
3.3.2 大数据量下的可视化
大样本数据的可视化是一个相对比较麻烦的事情,一般情况下我们都要用到降维的方法先处理特征。我们找一个例子来看看,可以怎么做,比如我们数据集取经典的『手写数字集』,首先找个方法看一眼这个图片数据集。
随机投射
我们先看看,把数据随机投射到两个维度上的结果:
在维度约减/降维领域有一个非常强大的算法叫做PCA(Principal Component Analysis,主成分分析),它能将原始的绝大多数信息用维度远低于原始维度的几个主成分表示出来。PCA在我们现在的数据集上效果还不错,我们来看看用PCA对原始特征降维至2维后,原始样本在空间的分布状况:
如果我们用一些非线性的变换来做降维操作,从原始的64维降到2维空间,效果更好,比如这里我们用到一个技术叫做t-SNE,sklearn的manifold对其进行了实现:
3.4 损失函数的选择
损失函数的选择对于问题的解决和优化,非常重要。我们先来看一眼各种不同的损失函数:
0-1损失函数(zero-one loss)非常好理解,直接对应分类问题中判断错的个数。但是比较尴尬的是它是一个非凸函数,这意味着其实不是那么实用。
hinge loss(SVM中使用到的)的健壮性相对较高(对于异常点/噪声不敏感)。但是它没有那么好的概率解释。
log损失函数(log-loss)的结果能非常好地表征概率分布。因此在很多场景,尤其是多分类场景下,如果我们需要知道结果属于每个类别的置信度,那这个损失函数很适合。缺点是它的健壮性没有那么强,相对hinge loss会对噪声敏感一些。
多项式损失函数(exponential loss)(AdaBoost中用到的)对离群点/噪声非常非常敏感。但是它的形式对于boosting算法简单而有效。
感知损失(perceptron loss)可以看做是hinge loss的一个变种。hinge loss对于判定边界附近的点(正确端)惩罚力度很高。而perceptron loss,只要样本的判定类别结果是正确的,它就是满意的,而不管其离判定边界的距离。优点是比hinge loss简单,缺点是因为不是max-margin boundary,所以得到模型的泛化能力没有hinge loss强。
4. 总结
全文到此就结束了。先走马观花看了一遍机器学习的算法,然后给出了对应scikit-learn的『秘密武器』机器学习算法使用图谱,紧接着从了解数据(可视化)、选择机器学习算法、定位过/欠拟合及解决方法、大量极的数据可视化和损失函数优缺点与选择等方面介绍了实际机器学习问题中的一些思路和方法。本文和文章机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾都提及了一些处理实际机器学习问题的思路和方法,有相似和互补之处,欢迎大家参照着看。
End.