主要机器学习算法的工程适用性分析
前段时间AlphaGo跟李世石的大战及相关的深度学习的新闻刷了一遍又一遍的朋友圈。不过这件事情,也只是在机器学习的深度上进一步拓展,而机器学习的广度(也即工程化实践)上,仍然没有什么突破性的理论或实践,用的领域继续用,不用的领域依然不用。
工程性分析的作用
工程上的琐事
机器学习的使命是使计算机强大的运算能力和存储能力转化为推演能力,能转化是一方面,转化的效率则是另一方面。科研性质的AlphaGo,拥有近乎无限的计算资源,不用太考虑这方面的问题,但在我们实际的工程应用中,时时刻刻要考虑到实现难度、内存、效率、能耗、稳定性等琐碎的问题。
下图列了机器学习在实际工程应用中会碰到的一系列问题,本篇呢,只讨论各类算法的时空复杂度及可并行性。
评估标准
机器学习算法的应用,一般是离线训练出模型后,放到线上预测。对于服务器集群而言,有可能训练和预测发生在同一种设备上。但更多的情况下,尤其是做客户端开发时,我们训练出来的模型是在放到一个计算资源比训练环境少得多的设备上去运行的。
离线训练在计算资源上没有太多限制,也不需要很实时,但如果确实数据量很大而且训练时间很长时,也希望能通过加机器解决问题(scale out)。
线上预测则会有实时性的要求,如果是移动设备,还有功耗的要求。
离线(训练)
离线训练过程,主要考虑以下因素
算法实现难度
工程上使用机器学习,虽然很多情况下是用现成的代码库,但算法的实现难度影响了可用的代码库的多少与好坏。并且,随着计算机硬件和软件架构的不断发展,始终是需要算法的实现代码与时俱进的(分布式、硬件加速等),这时候算法实现难度也决定了它更新的难易。
另外,对于“有理想、有追求”的公司来说,掌控一个工程的全部流程是必需的,真正做深做精,必须自己实现机器学习算法,参考文章http://www.infoq.com/cn/news/2015/12/manual-machine-algorithm-reason。这时,算法实现难度就是很现实的问题了。
算法使用难度
这里的算法使用难度也包括算法本身的健壮性,是工程上最需要好好考虑的地方。一方面是对脏数据是否敏感,需不需要做复杂的数据清洗;另一方面是需要设定多少参数,参数本身对算法结果影响是否显著。
算法使用难度高,需要专业人士去使用,工程的人力成本会显著提升。
使用难度高的另一后果则是结果不可预估,需要反复尝试,造成额外的时间和人力耗费。
训练所需资源与并行性
对大公司而言,机器比人便宜,动辄几百台的服务器,计算资源不愁,但对小公司来说,则很可能是人比机器便宜,训练算法的时间复杂度和空间复杂度太高,则不一定承受得起。
算法的并行性一方面决定算法能不能scale up(加机器),另一方面决定它能不能使用GPU加速(使用GPU加速后所需要资源和能耗可大大降低)。
在线(预测)
模型文件大小
监督学习算法训练数据之后,将得到一个模型文件,以供做后续预测,这个模型文件的大小决定它是否可迁移到其他设备上运行。
模型文件的大小也是评估学习算法是否过拟合的一个指标。
预测速度
预测速度不仅仅是实时性的问题,也是功耗的问题。速度快的一般是因为运算量少,功耗也会低。
在移动设备上,这是很重要的考量因素。
算法评价
支持向量机SVM
训练时的时间复杂度为内积计算+核函数映射+梯度下降/SMO,核函数计算相对于内积计算可以忽略,因此线性SVM和非线性SVM的训练时间复杂度是差不多的。但如果要考虑到非线性SVM的参数调优,其复杂度就需要乘寻优迭代数(网格寻优RBF核函数,粒度为100时就是10000倍。
内积计算是可以做数据并行的,在海量数据下,二次规划的解法用SMO或梯度下降,虽然SMO的算法复杂度低,但是不容易并行实现,因此在大数据量下,还是用梯度下降。SVM的数据并行原理上不难,实施起来由于SVM本身算法就复杂,还是比较麻烦的。
预测时线性SVM和非线性SVM有很大差别:
SVM完成训练之后,最终权值不为0的样本留下,作为支持向量。
非线性SVM必须保留所有支持向量,在预测时让所有支持向量与目标向量作一次内积计算,因此,支持向量数决定了模型的大小和预测的时间复杂度。(在海量数据之下,这个支持向量数很可能也是海量的)。
线性SVM可以对所有支持向量作合并,成为一个超平面方程,这样仅仅就是维度量级的一组参数。
另外,支持向量机由于天然只支持二分类,在处理多分类问题时必须用一套组合逻辑把二分类器扩展为多分类器。
参考:
http://blog.sina.com.cn/s/blog_5eef0840010147pa.html
这也会将降低预测的速度。
除了那些有名的机器学习工具包之外,svm有一个专门的工具libsvm去实现,可以适用于数据量不太大的情形。这个工具包基本上可以无脑训练模型,只是做预测时要集成一下代码。
逻辑回归(Logistic回归)
逻辑回归是改变了损失函数计算方式的线性回归。使用梯度下降算法去求解系数。系数个数就是特征个数。
鉴于使用梯度下降算法去求解系数,不断计算导数和偏移会有一些运算量,但运算量明显地比SVM少。且十分容易拓展到大数量的应用。
逻辑回归训练出来的结果大部分情况下都是欠拟合,少数情况下,特征实在取得太多,也会有过拟合出现。
朴素贝叶斯
朴素贝叶斯的训练过程就是一个统计数据频率的过程,非常迅速,得出的是一系列概率值,在预测时计算全部类别的概率取最高者就可。
作为一个简单暴力的算法,工程上应用很广。
决策树
C4,5决策树
决策树的训练是一个不断寻找最优分划点的过程,选取分划点时,每个可能选择都要过一次,但不断分划过程中,数据量也不断减少,总体训练速度还是很快的。
决策树出来的模型是比较简单的,也可以配参数控制,这使得它非常容易集成。
由于它在训练过程中会做特征的选择,因此有少量无效特征对它影响不大。但当树深比较大时,会过拟合。
一般情况它的训练速度快于逻辑回归,也比较准确,但在大数据量下,由于决策树的分划点计算过程需要遍历全部数据,效率不一定比使用了随机梯度下降的逻辑回归高。
随机森林
随机森林对数据进行若干次随机采样,生成若干个决策树,使用
训练时,尽量每次数据是采样一部分,但由于要生成多个子树,其复杂度总体而言比决策树高。
预测时,则由于原先的一个决策树变成了多个(一般是几十个),预测的复杂度明显变高。
最近邻算法KNN
KNN属于惰性学习,训练过程不做任何处理,只是在预测时查询最近的n个数据作判断。
它由于保存了全部训练数据,其模型文件无疑是非常巨大的,因此这种算法仅限于服务器上使用。
用一张表概括一下:
训练用的矩阵输入为 n X m ,n为数据量,m为维度(特征数),一般来说m 远小n。
此外记几个估计系数:
t:10量级
p:100量级
k:1000量级
q:10000量级
f:0~1之间的实数
预测准确率是根据以前做数据的经验估计的,随便看看就好。
算法 | 训练时间 | 训练内存占用 | 模型文件大小 | 预测时间 | 算法实现难度 | 算法使用难度 | 预测准确率 |
---|---|---|---|---|---|---|---|
非线性SVM | 长O(p*m*n*n)+O(p*k*n*n) | 多 O(n*n) | O(m*n^f) | 较慢 | 高 | 中等 | 高 |
线性SVM | 较长O(m*n*n)+O(k*n*n) | 同非线性SVM | O(m) | 快 | 高 | 一般 | 一般 |
逻辑回归 | 一般O(k*n*m) | 少 O(m) | O(m) | 快 | 低 | 一般 | 低 |
朴素贝叶斯 | 少O(n*m) | 少 O(m) | O(m*t) | 快 | 低 | 低 | 低 |
C4,5决策树 | 较少O(t*n*m) | 少 O(m) | O(m*m) | 快 | 低 | 一般 | 一般 |
随机森林 | 一般 O(t*t*n*m) | 少 O(m) | O(m*m*t) | 较快 | 低 | 较低 | 高 |
BP神经网络 | 一般 O(p*q*n*m) | 一般 O(m*p) | O(m*p) | 中等 | 一般 | 中等 | 一般 |
KNN | 无 | 无 | O(m*n) | 慢 | 低 | 低 | 一般 |
深度学习
上一篇已经说明,深度学习是由一系列无监督+监督学习算法组合而成的。因此也不能简单地判定其时空复杂度。
深度学习的模型参数一般而言是与数据量级无关的,但一方面由于它相对于浅层学习而言对输入没那么挑,输入向量的维度较大,另一方面可以尽情叠加模型,因此其参数量级非常大。
由于深度学习的几个基本算法(卷积神经网络CNN、深信度网络DBN等)都是天然数据并行的算法,作硬件加速也比较容易,加以可以横行于海量数据之上的随机梯度下降算法SGD,使其能够在海量数据之下进行不是太慢的训练。
神经网络类算法的模型参数较多,预测时所需要的内存和时间都比较长,因此在非服务器环境下还是很难使用。