`
weitao1026
  • 浏览: 1053577 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Madlib库

阅读更多

随着应用数据的增长,在大规模数据集上进行统计分析和机器学习越来越成为一个巨大的挑战。目前,适用于统计分析/机器学习的语言/库有很多,如专为数据分析用途而设计的R语言,Python语言的机器学习库Scikits,支持分布式环境扩展的有基于Map-Reduce实现的Mahout,以及分布式内存计算框架Spark上的机器学习库MLlib等等。目前Spark框架也推出了R语言的接口SprakR。但是,本文要讨论的,则是另外一种设计思路,在database中实现统计分析和机器学习算法,即In-Database Analysis,Madlib库就是这种设计思路的代表。

把机器学习库内置到database中(通过database的UDF)有许多优点,执行机器学习算法时只需要编写相应的SQL语句就可以了,同时database本身作为分析的数据源,使用非常方便,大大降低了机器学习的应用门槛。当然缺点也是明显的,由于受限于database提供的UDF编程接口,实现算法时会受到很多限制,很多优化难以实现,而大规模数据集上的机器学习,尤其是需要迭代计算的,通常对算法性能和结果收敛速度要求较高,否则很难做到实用。本文的重点就是讨论如何在In-database Analysis的框架下,高效的实现机器学习中的SGD(随机梯度下降)算法。由于很多机器学习算法如linear SVM分类器、K-mean、Logistic Regression都可以采用SGD算法来实现,只需要针对不同算法设计不同的目标函数即可。因此在database上实现高性能的SGD算法框架,便可用来执行一大类机器学习算法。

以Madlib为例,如果要Madlib用SVM算法对数据集做训练,可以执行如下SQL语句:

 
SELECT madlib.lsvm_classification( 'my_schema.my_train_data', 
                                   'myexpc', 
                                   false
                                );

madlib.lsvm_classification是Madlib中实现的SVM计算函数,上述方式的调用则是采用SGD算法进行linear SVM分类,其中my_schema.my_train_data是训练数据表,必须满足如下结构定义:

TABLE/VIEW my_schema.my_train_table 
(       
        id    INT,       -- point ID
        ind   FLOAT8[],  -- data point
        label  FLOAT8   -- label of data point,即分类结果
);

执行之后生成的Model将会被存到第二个参数’myexpec’指定的表中。第三个参数(true/false)指定算法是否需要并行执行。

生成Model表myexpec后,执行以下SQL语句就可以进行预测:

SELECT madlib.lsvm_predict( 'myexpc', 
                            '{10,-2,4,20,10}'
                          );

madlib.lsvm_classification函数还有更多的参数可以设置。如可以设置kernel-function,那么这时候计算实现的方式就不是SGD了,还可以设置迭代精度阈值等,具体参见Madlib文档。

从这个例子可以看出,Madlib库的使用是非常方便的,只要我们按照库函数要求建好相应的数据表并导入数据,就可以通过调用Madlib库中的SQL函数来进行模型训练和模型预测了。目前Madlib支持PostgreSQL、Greenplum、Pivotal HAWQ。

但是,在很多情形下,Madlib的执行性能是很差的,以基于SGD算法实现的机器学习训练模型为例,在数据量大的情况下经常需要几十小时甚至几百小时来完成,为了提高计算速度和模型收敛速度,有两个非常值得优化的地方:一是改为并发更新模型,二是优化数据读取顺序。

首先看基本的SGD算法框架在database的UDFA(自定义聚合函数)上的实现。以linear SVM为例,可以定义如下目标函数f(x):

其中<xi, yi>就是训练数据,w是训练模型。如下的梯度下降算法通过迭代找出使这个目标函数值尽可能小的w:

其中是步长值。

但是直接按照上式计算,每迭代一次,就需要遍历所有的数据,难以在实际场景中应用,因此就有了SGD(随机梯度下降)算法,对每一步迭代中的f(x),近似的用随机的一个数据点来代替原有f(x)中对所有数据点的求和:

在原始数据顺序随机的情况下,每次迭代只需要顺次取出一条记录并按上式进行迭代即可。这种迭代更新的计算方式,和database中提供的UDFA扩展接口是非常吻合的。可以把这个计算过程抽象为三个函数:

initialize(state)
transition(state, row_data)
terminate(state)

state用于存储这个UDFA计算上下文,对应SDG算法,state存的就是不停被迭代更新的model。row_data是每次读入的一行记录,即一个数据点。terminate函数返回最终的计算结果。具体这三个函数调用的次序如下图所示:

在PostgreSQL数据库中,这三个函数分别被命名为initcond、sfunc和finalfunc。

在训练数据表上执行一次这样的UDFA,相当于顺次用表中所有的数据按照上述的迭代式计算了一遍。通常要对总体数据迭代多遍才能得到想要精度的结果,因此Madlib库中那些训练函数实际上是用SQL脚本语言编写的函数,其中包含了对整个表数据的多轮迭代,直到获得所需精度的结果。如果数据表的数据顺序是有序的,那么顺次迭代将大大降低算法的收敛速度,这时可以先将数据表的数据顺序打乱再执行上述算法,如在PostgreSQL中,可以先用order by random()打乱数据顺序,然后再进行迭代计算。

上述的UDFA执行过程存在着两大缺陷:1.没有并行化。2.在数据量大的情况下,将数据次序打乱可能是一个非常大的开销。下面先讨论并行化的改进方案:

一个简单的并行化计算方法是,将表数据分为多个部分,每个部分有自己的model state,每个部分的model各自进行各自的迭代计算,当各个model都计算完毕时再进行合并。简单的合并方案就是将所有的model做平均值得到最终的model。为什么SDG算法可以用这种方法拆分计算然后取model平均值,可以参见这篇论文[1]。当然,这要求database对UDFA提供一个merge(state, state)的函数接口让用户来自定义合并方式。这种简单的并行化方式不仅可以应用在单机database上,也可以用在数据分布到多个结点上的分布式database/datawarehouse上,如Cloudera Impala。但是这种简单的share nothing的并行计算方案通常会极大的影响model的收敛速度,因此还需要寻找更好的并行执行方案。

实现不影响收敛速度的并行执行,就需要所有在不同区段数据上并发执行的UDFA去更新同一个model,这就要database提供Share-Memory的接口以便于UDFA访问共享内存。像PostgreSQL就提供了相应的接口[3]。

但是这种并发更新model的方式又带来了另外一个矛盾,在用迭代式更新model时必须对model加锁,假设多个UDFA计算线程同时工作,在同一时刻显然只有一个线程能获得锁进行计算并更新模型,本质上还是等同于单线程的计算效率。要解决这个矛盾,可以采用论文[2]中提出的lock-free parallelizing SGD算法。这个算法避免了更新model时对model加锁,核心思想是通过稀疏化model,使得每次迭代只需要更新model中的很少一部分分量,然后证明在lock-free方式下并发更新,收敛速度有一个不错的下限。

第二个问题是如何避免大数据量情况下打乱数据次序的开销,因为如果原始数据是有序的话,可能对model收敛速度有很大影响,但是打乱大量数据通常又要耗费大量开销。一个简单的方法是,对所有表数据做reservior sampling,这是一个经典的算法,通过一遍扫描原始数据集进行等概率抽样。然后对抽样数据打乱次序后在抽样数据上进行迭代。当然这种算法缺点也很明显,大量有效的数据点被舍弃了,对训练结果的准确性影响很大。为了避免这个缺陷,可以把数据抽样和按数据顺序迭代相结合,即如下的multiplexed reservior sampling:

如上图所示,设立两个工作线程并发更新Model,一个是I/O线程,分配好buffer A;另一个是Memory线程,分配好buffer B。

第一轮迭代,只有I/O线程工作,假设buffer A的容量为M,总记录数为N,遍历每一条记录,前M条记录直接填入buffer A。从M+1条记录开始,假设当前为第i条记录,第i条记录有M/i的概率被选中,如果被选中那么替换掉buffer A中的随机一条记录,替换出的记录被丢弃,否则直接丢弃第i条记录。这时候用被丢弃的记录更新模型,直到所有记录遍历完成。

第一轮迭代后交换buffer A和buffer B。第二轮以后的迭代都是I/O线程和Memory线程同时工作。Memory线程负责循环读取出buffer B中的数据并用来更新model,I/O线程的工作和第一轮的工作方式相同。每一轮迭代过后交换buffer使得memory线程可以用到上一轮I/O线程采样出的数据。

基于Hadoop的分布式SQL查询引擎Cloudera Impala也集成了Madlib库,当然现在还很不成熟,感兴趣的读者可以点击:

http://blog.cloudera.com/blog/2013/10/how-to-use-madlib-pre-built-analytic-functions-with-impala/

这个项目的Github地址在:

https://github.com/cloudera/madlibport

这个项目把Madlib库和Bismark计算框架移植到了Impala上,当然好处是可以利用Impala的分布式处理能力,至于性能和成熟度,目前还无法期待太多,毕竟Imapla也才刚刚在1.2的版本中加入了UDFA的编程接口,还有太多局限的地方。

分享到:
评论

相关推荐

    基于postgresql+机器学习库MadLib的上海地区二手房价格预测及推荐

    一旦数据被导入到数据库中,我们就可以使用MadLib库来训练机器学习模型。MadLib是一个开源的机器学习库,可以在PostgreSQL和Greenplum等数据库中使用SQL语句直接训练模型。它支持多种机器学习算法,包括线性回归、...

    Linux音视频播放器.zip

    它由Madsonic项目开发,基于Madlib库,能够高效地解码和播放MP3文件。madplay的特点在于其简洁的命令行界面,使得用户可以通过终端进行控制。尽管它没有图形用户界面,但通过脚本或与其他工具集成,madplay可以实现...

    STM32软解MP3

    - 解码引擎:执行解码算法,如FFmpeg或MadLib库对于MP3,或者直接处理WAV的PCM数据。 - 数模转换(DAC)驱动:将解码后的数字信号转换为模拟音频信号输出。 - 控制逻辑:管理解码过程,包括播放/暂停/停止控制,...

    mp3 1_基于stm32F103单片机;_MP3播放器源代码_

    2. **库文件**:可能包含用于MP3解码的库,例如使用开源的MadLib库或者LAME库进行MP3解码。这些库通常由专业开发者编译,可以处理音频数据的压缩和解压缩。 3. **配置文件**:可能包括针对STM32F103的HAL库配置文件...

    EVC下闹钟程序,很简单,只播放简单MP3音乐 Alarm

    1. 媒体播放库:在资源有限的嵌入式设备上,需要轻量级的MP3解码库,如MPEG Layer-3 Decoder或开源的madlib库。这些库能将MP3音频数据解码为PCM格式,然后通过设备的音频硬件或软件播放。 2. WAV格式转换:由于某些...

    【基于STM32设计的音乐播放器】包括:PCB源文件+源码+论文

    例如,可以使用开源的MadLib库进行MP3解码。 解码后的音频数据随后会被送入数字模拟转换器(DAC),通过PWM或I2S接口,将数字信号转化为模拟音频信号,然后通过扬声器或耳机输出。这个过程中,STM32还需要处理音量...

    MP3 源程序

    开发者可能使用了优化过的库,如开源的MadLib库或LAME库,来实现MP3解码。 在KEIL uVision 4中,开发者会创建工程,将MP3源文件添加到项目中,并配置必要的编译器选项和链接器设置,确保代码能正确地编译和链接到...

    基于嵌入式的智能MP3开发方案

    C语言可以实现一个高效的解码算法,如FFmpeg或Madlib库,它们提供了MP3解码的API。 3. **音频输出**:将解码后的数字音频信号转换为模拟信号,通过耳机或扬声器输出。这可能涉及到对硬件音频接口的操作,如DMA...

    kmeans-digit-on-madlib

    标题 "kmeans-digit-on-madlib" 暗示了我们正在讨论一个使用 Madlib 库进行 K-Means 聚类分析的项目,特别是针对数字数据。Madlib 是一个开源的、用于数据库系统的机器学习和统计库,它允许在数据库内部执行各种数据...

    MADlib-基于SQL的数据挖掘解决方案-关联规则之Apriori算法.docx

    【MADlib与Apriori算法】MADlib是一款开源的、嵌入到数据库管理系统中的数据挖掘库,它提供了一种高效的方式来进行复杂的数据分析,尤其是对于SQL支持的数据库系统。MADlib专注于向企业提供实用的技术方案,解决大...

    MADlib-基于SQL的数据挖掘解决方案-图算法之单源最短路径.docx

    **MADlib** 是一个开源库,提供了一系列高级分析功能,支持 SQL 查询接口。在 MADlib 中,单源最短路径算法可以通过特定的 SQL 函数来调用。这些函数接受图的表示形式(通常是邻接表)以及起始顶点作为输入参数,并...

    基于postgresql+机器学习库MadLib的上海地区二手房价格预测及推荐).zip

    本文将详细探讨如何利用PostgreSQL数据库与机器学习库MadLib,进行上海地区二手房价格预测及推荐系统的设计与实现。 PostgreSQL是一种功能强大的开源关系型数据库管理系统,因其稳定性和可扩展性而被广泛应用。...

    MADlib-基于SQL的数据挖掘解决方案-分类之朴素贝叶斯.docx

    MADlib是一款开源的数据挖掘库,支持多种数据库系统。它提供了基于SQL的接口来执行复杂的数据挖掘任务,包括分类、回归等。在MADlib中实现朴素贝叶斯分类主要包括以下几个方面: 1. **数据准备**:使用SQL语句加载...

    madlib:Apache MADlib的镜像

    马德利布:registered:是可扩展的数据库内分析的开源库。 它为结构化和非结构化数据提供了数学,统计和机器学习方法的数据并行实现。 安装和贡献 请访问项目网站,以获取最新二进制文件和源程序包的链接。 我们感谢...

    基于Java的MADlib自动化测试框架.pdf

    "基于Java的MADlib自动化测试框架" 摘要:本文介绍了基于Java的MADlib自动化测试框架的设计和实现,该框架可以在Linux操作系统下自动实现数据的处理和导入、测试用例的生成和执行,以及测试结果的分析,从而可以...

    MADlib2.1.0 安装包

    MADlib是一款强大的开源库,专门用于在关系数据库管理系统(如Greenplum)中执行大规模的数据分析和机器学习任务。这个“MADlib2.1.0安装包”是为Greenplum数据库系统设计的,提供了高效且可扩展的统计、机器学习和...

    基于postgresql+机器学习库MadLib实现的的上海地区二手房价格预测和推荐Python源码+文档说明

    基于postgresql+机器学习库MadLib实现的的上海地区二手房价格预测和推荐Python源码+文档说明 - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,...

Global site tag (gtag.js) - Google Analytics