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