理论+实例,带你入门Greenplum机器学习框架MADlib

2023-11-03 07:41

本文主要是介绍理论+实例,带你入门Greenplum机器学习框架MADlib,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

e45b2dd4-549c-4f09-82eb-5829b7a0ab56.jpg

本文由瀚高基础软件社区作者赫庆贺创作贡献


概述


本文介绍Greenplum和MADlib在机器学习方面的基本概念、架构和原理。并结合MNIST数据集完成对0-9阿拉伯数字的图形识别的应用实例。旨在为数据库开发者和DBA提供简单机器学习的了解和入门的方式。

一、知识与软件准备


1.1 Greenplum 


Greenplum是全球首个开源MPP数据库,内核基于PostgreSQL。作为PB级分布式数据库,支持大规模并行数据计算,被广泛应用于企业的OLAP业务场景。Greenplum集群的节点类型主要有master和segment。master提供数据库统一访问入口并协调各计算节点运行,segment作为物理存储和数据计算节点。通过增加segment节点可以实现系统性能的线性扩展。
Greenplum的并行计算能力和线性扩展能力赋能于MADlib,使其有更好的并发度,用更全量的数据和更少的数据移动来做模型训练。


1.2 MADlib


MADlib 是Apache 软件基金会顶级开源项目。作为一个机器学习函数库,MADlib能以扩展插件的形式嵌入到Greenplum和PostgreSQL数据库中,提供SQL层的接口。数据库用户可以直接通过SQL语言调用MADlib的接口完成机器学习的各个过程。
MADlib的架构如下:

6faa31c0-350c-4f23-a2f7-d07b60b77f90.png


为了保证执行效率,MADlib底层算法主要由C++编写,上层接口由python编写。目前已支持超过50种常用算法,并且为开发人员提供了扩展算法的方式。


所有算法都支持在Greenplum各个segment节点上并行运算,并将各个segment上的运算结果汇聚到master节点形成最终结果,计算时的数据仅在数据库内部移动。为了实现这一点,MADlib在数据库内创建一系列的汇聚函数(UDA)和计算函数(UDF)。在MADlib安装时这些函数会被创建在数据库内部。


MADlib支持深度学习算法,集成Keras、Tensorflow、Scipy库,并集成CUDA、CUDNN以支持GPU加速计算。


1.3 机器学习


机器学习是一门多领域交叉学科,涉及概率论、统计学、算法复杂度理论等多门学科。机器学习是人工智能(AI)的核心子领域,机器学习的理论基础是能够让计算机可以自动学习的算法。算法按照学习策略、应用领域、学习形式等方式划分为不同类别。常见机器学习算法有:朴素贝叶斯、线性回归、神经网络、决策树、支持向量机等等。幸运的是,作为一个软件开发者可以不用去了解算法的实现细节,直接调用函数库接口就能使用这些算法。机器学习已在生物特征检测、图像识别、数据挖掘、语义分析等多个领域有广泛应用。


传统方式下,计算机对某一个事物分类的判别方式通常需要一组事先定义好的阈值区间和一系列严格的判断逻辑组合来完成。例如让计算机判断一个物体是不是苹果,要事先告诉计算机苹果的定义是什么。


假设我们定义苹果的属性取值区间为:颜色为红色或青色,直径范围是2cm-10cm,重量范围20g-500g,口感香甜。


计算机判断物体是不是苹果的流程通常如下:


398caeb7-fbc9-43f0-b057-11ee5885cf80.png


机器学习则提供了另一种思路来解决这类问题。我们不需要给计算机预先定义苹果是什么。我们只需要告诉计算机这种东西是苹果、这种东西是苹果、这种东西也是苹果......


所有的苹果样例组成了数据集。通过机器学习算法对数据集的处理(训练)可以产生判断苹果的模型。随着数据集的变化,模型可以通过重复训练来优化调整。有了模型便可以判断一个新的物体是不是苹果了。


4af0ebcb-7974-4d11-a6e5-f5ccbf043a46.png


以上示例,对事务的分类判别方式称之为分类算法,分类算法仅仅是众多机器学习算法中的一种。除了分类算法还有用于预测连续性输出值的回归类算法,用来挖掘事务之间的关联关系的关联规则类算法等等。


1.4 数据集


机器学习中用来训练算法模型和测试算法正确性的数据。针对自身业务的机器学习模型训练最好使用自身应用场景的数据。也有许多不同应用场景下的公开数据集供学习研究使用。本文使用MNIST数据集作为训练和测试用数据。


MNIST来自美国国家标准与技术研究所(NIST),是被经常使用的典型数据集。MNIST由多人手写0-9的阿拉伯数字组成,可以把每个手写阿拉伯数字看做是一个28x28像素的图片,将图片转换成像素值的矩阵再以字节序的形式存储到文件中。


MNIST数据集的下载地址为:http://yann.lecun.com/exdb/mnist/


下载文件列表如图:


7a68586e-daf9-4a4d-8336-06aba762d9ac.png



下载后可以用gunzip工具将每个压缩文件解压。数据集包含60000个训练数据样本,10000个测试数据样本。文件分别以格式存储数据。

62296db0-6d88-4315-9e85-9bd3bf60b92e.png


1.5 数据处理代码


MNIST数据集需要将数据文件转换并导入Greenplum后才能被MADlib使用。为了方便数据集的处理,参照1.4节的数据文件格式,编写了代码文件mnist_transform.py:
import os  import struct  from PIL import Image  import numpy as np

def load_mnist(path, kind='train'): """Load MNIST data from files""" labels_path = os.path.join(path,'%s-labels-idx1-ubyte' % kind) images_path = os.path.join(path,'%s-images-idx3-ubyte' % kind) with open(labels_path, 'rb') as lbpath: magic, n = struct.unpack('>II', lbpath.read(8)) labels = np.fromfile(lbpath, dtype=np.uint8)
with open(images_path, 'rb') as imgpath: magic, num, rows, cols = struct.unpack('>IIII', imgpath.read(16)) images = np.fromfile(imgpath, dtype=np.uint8).reshape(len(labels), 784) return images, labels, num

def format_csv_line(seq, num, array): linestr="%d,%d,\"{" % (seq, num) for i in range(len(array)): linestr += "%d," % array[i] linestr = linestr[:-1] linestr += "}\"\n" return linestr

def array2csv(imgs, lbs, num, tofile): """covert np.array to CSV format file""" with open(tofile, "w") as f: for seq in range(num): f.write(format_csv_line(seq, lbs[seq], imgs[seq]))

def array2imgfile(idx, imgs, filename): """extract mnist data to png file by index""" imgarray=imgs[idx].reshape(28, 28) im = Image.fromarray(imgarray) im.save("/home/gpadmin/madlib/mnist/images/%s_idx_%d.png" % (filename, idx), format="png")

if __name__ == "__main__": imgs, lbs, count = load_mnist("/home/gpadmin/madlib/mnist", "train") array2csv(imgs, lbs, count, "/home/gpadmin/madlib/mnist/trans_data.csv") imgs, lbs, count = load_mnist("/home/gpadmin/madlib/mnist", "t10k") array2csv(imgs, lbs, count, "/home/gpadmin/madlib/mnist/test_data.csv") #array2imgfile(0,imgs,"test") print("transform completed.")

 load_mnist函数读取解压后的MNIST数据文件,并将数据放入numpy.array数组中。


array2csv函数将numpy.array数组中的数据装换成CSV格式文件,CSV文件可以通过copy命令导入数据库表,其格式与数据库表的格式要一致。请参考2.1节数据库表的创建语句。


array2imgfile 函数可以将数组中的一个样本转换成图片文件,以便通过图片查看器对数据样本进行可视查看。


二、应用实例


有了前面的各项准备工作,接下来我们要做的是以实现计算机对手写阿拉伯数字0-9的识别为例子,进一步探索Greenplum+MADlib机器学习方式。


具体过程是先将MNIST的数据集导入到Greenplum数据库中,使用MADlib提供接口,完成朴素贝叶斯算法模型的训练,并且使用训练的模型对测试数据进行识别。最后通过对比测试数据样本和识别结果来检验MADlib中朴素贝叶斯算法是否能对MNIST测试数据进行识别。


在进行第二章节的实例之前,需要先将Greenplum系统搭建好。Greenplum的安装方式可参考官方网站(https://cn.greenplum.org/)。


MADlib安装文档请参考:

https://cwiki.apache.org/confluence/display/MADLIB/Installation+Guide


安装时需要确保Greenplum已经启动,从源码编译安装到Greenplum时需要将编译好的函数库分发到各segment上。


本实例使用软件版本:

PostgreSQL 9.4.24 (Greenplum Database 6.0.0-beta.1 build dev)

MADlib version: 1.17.0


2.1 导入数据


以下步骤需要用客户端软件(如psql)连接到Greenplum数据库进行操作,使用PostgreSQL数据库时请酌情调整SQL。
创建训练数据表: CREATE TABLE mnist_example ( id int, label smallint, attributes smallint[]) DISTRIBUTED BY(id);   id 字段为样本编号。 label字段表示样本代表的阿拉伯数字。 attributes 字段是由784个元素构成的Array,用以保存样本图片的数据。
创建测试数据表: CREATE TABLE mnist_topredict ( id int, label smallint, attributes smallint[]) DISTRIBUTED BY(id);  
将MNIST的训练数据和测试数据转换成CSV格式: 运行mnist_transform.py文件的转换函数(python3):
imgs, lbs, count = load_mnist("/home/gpadmin/madlib/mnist", "train")  array2csv(imgs, lbs, count, "/home/gpadmin/madlib/mnist/trans_data.csv")  imgs, lbs, count = load_mnist("/home/gpadmin/madlib/mnist", "t10k")  array2csv(imgs, lbs, count, "/home/gpadmin/madlib/mnist/test_data.csv")

得到CSV文件:test_data.csv  trans_data.csv


导入训练数据到表mnist_example:

copy  mnist_example from '/home/gpadmin/madlib/mnist/trans_data.csv' CSV;   


导入测试数据到表mnist_topredict:

copy mnist_topredict from '/home/gpadmin/madlib/mnist/test_data.csv' CSV;  


2.2 训练模型
调用MADlib的API进行模型训练。 SELECT * FROM madlib.create_nb_prepared_data_tables('mnist_example','label','attributes',784,'mnist_feature_probs','mnist_priors');  
参数 'mnist_example' 为2.1步骤创建的训练数据表名。 参数 'label'  指定以mnist_example表中的lable字段作为分类字段。 参数 'attributes' 指定以mnist_example表的attributes字段作为特征字段。 参数 784  表示数据特征的个数,在本例中图片的每个像素都作为一个特征,图片是28*28=784像素的。 参数'mnist_feature_probs' 指定特征概率输出表的名称 参数'mnist_priors' 指定分类输出表的名称,此表统计训练数据中各个分类出现的次数。

2.3 样本识别结果


创建可用来查询识别结果的视图 mnist_classified。

SELECT madlib.create_nb_probs_view('mnist_feature_probs','mnist_priors','mnist_topredict','id','attributes',784,'mnist_classified'); 


参数'mnist_feature_probs'  'mnist_priors'同2.2节

参数'mnist_topredict' 为待识别数据表,'id' 'attributes' 784参数指定该表的键和属性字段以及特征数。

参数'mnist_classified'为创建的视图名称。


创建好的视图结构如下,


5202a944-f3c2-45c5-87e2-b87b6533731c.png


key 字段对应输入数据表(mnist_topredict)的id字段。 class 字段表示可能的阿拉伯数字 nb_prob 字段表示识别为对应class字段的概率,最大值为1。
对比查看对编号(key/id)为0的测试数据的识别结果以及待识别数据原型。
查看识别结果:

57832598-34d4-49e2-b0a1-0a47d654e311.png


可以看到识别为数字 7的概率有1(100%).识别为其他是数字的概率都远低于数字7. 查看对应编号为0(id)的数据样本:

fc83f8db-c777-454e-aff8-81c11ae82b64.png


编号为0的数据样本对应的阿拉伯数字为7。


通过mnist_transform.py文件里的array2imgfile函数将编号为0的测试数据转化为图片文件。


imgs, lbs, count = load_mnist("/home/gpadmin/madlib/mnist", "t10k")  array2imgfile(0,imgs,"test")

得到图片文件test_idx_0.png。 用图片查看器打开图片文件,验证为手写的数字 7。

d3046cc5-93c2-4218-9ae9-ae5ff376fd5f.png


对编号为0的测试数据样本识别达到期望目标。

再来看一个识别失败的例子。编号为1234的样本机器识别结果为:


dc26c226-b857-44bc-9991-6f3c57f1943e.png


机器识别为极大概率是数字5,其次为数字3,较小概率为数字8.为其他数字的概率远低于这三个。


对应的数据样本为:


f1c8e806-968d-4f7e-bc19-2e034e7a6c63.png


转换后的图片为:


1a5f849a-fe9e-41a1-86e4-af28077e8416.png


显然对这张图片的识别未达到预期结果。


2.3 识别的正确率    


我们将nb_prob值最大的一项对应的class值作为最终识别数字,然后统计一下对10000个测试数据的识别正确率。


在数据库中创建PL/pgSQL函数mnist_stat():

CREATE OR REPLACE FUNCTION mnist_stat() RETURNS integer AS $$    DECLARE      topredict   RECORD;      classified  RECORD;      total       integer := 0;      sucnum      integer := 0;      failnum     integer := 0;  BEGIN      RAISE NOTICE 'Begin statstics';      FOR topredict IN SELECT id,label FROM mnist_topredict  LOOP          EXECUTE  'SELECT key,class FROM mnist_classified WHERE key=$1 ORDER BY nb_prob DESC LIMIT 1 ' INTO STRICT classified USING topredict.id;          IF topredict.label = classified.class THEN              sucnum := sucnum + 1;          ELSE              failnum := failnum +1;              RAISE NOTICE 'id % failed: %  --- % ',topredict.id,topredict.label,classified.class;          END IF;          total := total + 1;
END LOOP; RAISE NOTICE 'total: % sucnum: % failnum:%',total,sucnum,failnum;
RETURN sucnum ; END; $$ LANGUAGE plpgsql;


执行统计过程:


testDB=# SELECT mnist_stat();


输出统计结果:

fa885b93-8121-454c-8277-9a16cdef339f.png


识别样本总数10000,识别正确数为8377,识别错误数为1623.正确率为83.77%。
在没有任何针对性优化的情况下,83.77%正确率可以说明Greenplum +MADlib进行图像识别的可行性,并不能说明这种方式的优劣。因为机器学习算法识别的正确率与很多因素相关,如训练数据数量、测试样本、使用的机器学习算法、算法使用的参数等等。对于如何优化和提升还需进一步深入学习研究。

参考资料:

http://docs.greenplum.org/6-4/analytics/madlib.html#topic9

http://madlib.apache.org/documentation.html

http://yann.lecun.com/exdb/mnist/




07d49c61-21bc-49a5-bb0f-d3d8a696b661.png

想学习机器学习算法?Greenplum原厂团队亲自操刀,和腾讯云大学合作打造了《基于 Greenplum 的机器学习算法与实践》系列课程。


十个章节,囊括了机器学习的前世今生、各大经典算法、深度学习、时间序列算法、图算法、数据分析扩展语言等丰富的内容,算法理论配合Greenplum应用实践。


十小时的精彩内容,免费贡献给社区,扫码或点击“阅读原文”即可开启你的学习之旅!


45770028-204b-4e79-a2e7-09feabdf97d0.jpg


bf9016b2-48c3-471e-8389-824d172bb4dd.png



c82d1672-8542-4df6-988f-36c89e334dfb.svg

近期活动

af4f73f6-d842-46ba-a433-bbc52f051d28.svg


06d27806-2bdb-4e3e-a966-6efbe8e6e1c7.jpg


点击文末“ 阅读原文 ”,获取课程链接

8fbd29e8-c45a-4842-aa10-b8b287c5a040.gif

82f83c8b-7ce6-4bea-b883-d97ff37e80b1.png来一波 “在看”、“分享”和 “赞” 吧!


本文分享自微信公众号 - Greenplum中文社区(GreenplumCommunity)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

这篇关于理论+实例,带你入门Greenplum机器学习框架MADlib的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/336650

相关文章

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

springboot security验证码的登录实例

《springbootsecurity验证码的登录实例》:本文主要介绍springbootsecurity验证码的登录实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录前言代码示例引入依赖定义验证码生成器定义获取验证码及认证接口测试获取验证码登录总结前言在spring

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

Python GUI框架中的PyQt详解

《PythonGUI框架中的PyQt详解》PyQt是Python语言中最强大且广泛应用的GUI框架之一,基于Qt库的Python绑定实现,本文将深入解析PyQt的核心模块,并通过代码示例展示其应用场... 目录一、PyQt核心模块概览二、核心模块详解与示例1. QtCore - 核心基础模块2. QtWid