数据和AI正在成为很多公司的重要资产。其中,数据代表了公司在特定领域的积累,也是公司的护城河,AI能力输出则代表了公司对数据资产的利用深度。二者不可分,光有数据没有AI,就好比你只有原材料,却无法加工产生价值;光有AI没有数据,就好比你光有屠龙术,但是却没有龙给你屠。只有将二者作为一个整体,才能给一个公司带来最大的价值。
数据和AI本身存在上下游关系,以及由于历史发展而存在先后顺序,这导致它们最终成为了两个相对独立的体系,带来了两个很大的问题:
大数据在语言层面以Java/Scala/SQL为主导,其中SQL是交互语言,Java/Scala则是大数据体系的构建语言。 AI则是以Python/C++ 为主导,其中Python为交互语言,C++为算法体系的构建语言。在面向的人群上,Java/Scala面向数据研发,SQL面向分析师、运营、产品。但是随着SQL进一步发展,现在越来越多数据研发也开始直接使用SQL去解决自己的问题。Python则更多面向算法。当然,分析师通常也会一些Python,而会Python的自然也会一些SQL。
从交互的复杂度而言:
C++ > Java/Scala > Python > SQL
自然而然的,越是简单的编程语言,就越容易变得流行,毕竟流行的本质就是使用人群扩大。只有门槛低的语言,才能提高使用人群的比例。所以SQL和Python慢慢分别发展成了大数据和算法的标准交互语言。实际上这些语言存在已久,只是因为各自的特点以及简单性使得它们在新的时代得到了新的应用。
在很多公司,数据平台和AI平台通常是两个平台,而且有时候连维护也是由两个不同的团队负责。这种平台之间的隔离造成了很大的互通问题,其中最大的问题就是数据互通。
完成一次对数据价值的开发,首先要对数据进行处理,处理后进一步交给AI去学习。而技术栈以及平台的不同,导致AI获取数据的成本被提高了。用户可能需要先去数据平台写个数据处理脚本(譬如基于Spark等)提取数据,然后转存到AI平台或者一个能被AI和数据平台共享的存储上,然后再去AI平台写Python或者调库完成对数据的训练。当然,随着分工越来越细,其实用户自己无法完成所有这些事情,他往往需要把这些步骤拆解然后下发到各个小的支持团队里去,然后各个小团队进行排期,最终完成一整个链条的工作。无论对大公司还是小公司,这都会极大地消耗成本。
即使到今天,对很多公司来说,构建数据和AI平台依然很困难:需要了解无数的组件,需要有大量经验且分别懂SQL、Java、Scala、Python的开发、分析师、算法,或者需要了解各种云产品并做组合以达到自己想要的效果。所有这些困难堆叠起来就会导致极其高昂的开发成本。同时,由于IT特有的属性,即使做了这些投入,可能依然满地是坑。面对底层无数存储,如何做一个有效的权限控制就已经让很多开发挠头了。
而且,数据和AI应该是普惠的。在笔者看来,数据和AI不应该仅仅局限在数据科学家手里(包括分析师和算法),任何一个产品、运营,甚至任何一个有权访问数据的人,都应该可以对这些数据进行价值开发。这种开发小到只是查看,或者导出成一个Excel,或者对外提供一个查询接口,大到提供一个精准的推荐系统,都应该能比较容易地完成。
前面说了这么多,无非是想告诉大家:
那怎么才能实现上面这三个诉求呢?单单从平台层面很难解决这个问题,这个时候我们就需要从语言层面着手了。我们需要一个能够更好地融合大数据和AI的编程语言,它必须具备以下特点:
Python对大多数人还是有一定难度,而且无法很好地整合大数据生态。SQL简单,但是无法满足算法的复杂需求且难以利用AI领域大量生态。
我们希望用一个语言完成大数据批流处理以及AI的训练和预测。我们希望在语言层面内建数据安全机制,解决无数底层存储的访问控制问题,让开发不再挠头。我们还希望这个语言内置的功能易于扩展,且能够充分利用大数据和AI的构建语言Java/Scala/C++做扩展,因此这个语言的执行引擎应该具有强大的插件化能力。
目前正在朝着这个目标努力的编程语言有SQLFlow和MLSQL。
SQLFlow的初衷是为了解决成千上万分析师既要操作数据又要使用AI,往往需要在两个系统甚至更多系统之间切换导致工作效率低的窘境。
SQLFlow对SQL做了部分语法扩展,用户可以在SQL中加入算法的描述。
一个典型的语法如下:
-- SQL 部分
SELECT * FROM 20newsgroups.train
-- 算法描述部分
TO TRAIN DNNClassifer
WITH hidden_units = [10, 10], n_classes = 3, EPOCHS = 10
COLUMN sepal_length, sepal_width, petal_length, petal_width
LABEL class
INTO sqlflow_models.my_dnn_model;
其基本逻辑是提供了一个基于Go开发的Service,用于接收发往后端存储的SQL,然后对SQL进行解析并提取出数据描述部分和算法描述部分。
SQLFlow会将数据描述部分(SQL)发送给后端存储引擎,并把后端返回的数据喂给算法部分做训练;同时根据算法描述自动生成Python代码,然后提交给特定的算法引擎来完成训练,最后将结果保存回存储引擎。目前后端支持MySQL、Hive、MaxCompute等,算法引擎支持 TensorFlow、PyTorch。
不过笔者个人认为,SQLFlow需要研发去适配众多存储后端,同时还要针对各个算法引擎做支持,并且语法扩展部分目前还不够灵活,只能使用SQLFlow已经实现好的一些算法,缩小了SQLFlow的覆盖人群,譬如专业的算法工程师应该不大会去使用它。
MLSQL一开始的出发点也是为了解决算法的普惠性,希望不仅仅是AI人才能用上算法,工程师、分析师和产品运营都应该能用起来。
和SQLFlow只是简单扩展SQL不同的是,MLSQL是基于SQL语法设计的全新的编程语言。
对于工程师或分析师来说,可以完全使用类SQL语法来实现训练和预测,这一点上MLSQL和SQLFlow是相同的:
select * from 20newsgroups as 20newsgroups;
train 20newsgroups
as RandomForest.`/ai_model/rf`
where keepVersion="true"
and evaluateTable="tfTable_test"
and `fitParam.0.featuresCol`="value"
and `fitParam.0.labelCol`="label_num"
and `fitParam.0.maxDepth`=“2";
系统会自动生成Spark/Python代码完成训练。
而对于专业的算法工程师,MLSQL支持使用内嵌Python进行训练(这一点目前在SQLFlow官方文档中没有体现):
!python env "PYTHON_ENV=source activate dev";
!python conf "schema=st(field(count_vect,binary),field(tfidf_transformer,binary),field(nb,binary))";
load delta.`ai_data.20newsgroups` as 20newsgroups;
-- 提取数据中的分类,因为隐含在url里。
select *, split(file,"/")[4] as label from 20newsgroups as 20newsgroups;
--我们可视化下数据分布
select label,value from 20newsgroups as 20newsgroups;
!ray on 20newsgroups '''
import pandas as pd
import plotly.express as px
from plotly.io import to_html
from vega_datasets import data
from pyjava.api.mlsql import PythonContext,RayContext
ray_context = RayContext.connect(globals(),None)
data = list(ray_context.collect())
df = pd.DataFrame(data, columns=data[0].keys())
from sklearn.feature_extraction.text import CountVectorizer
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(df.value)
from sklearn.feature_extraction.text import TfidfTransformer
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
from sklearn.naive_bayes import MultinomialNB
print("这是进行训练的过程")
clf = MultinomialNB().fit(X_train_tfidf, df.label)
docs_new = ['God is love', 'OpenGL on the GPU is fast']
X_new_counts = count_vect.transform(docs_new)
X_new_tfidf = tfidf_transformer.transform(X_new_counts)
print("这是进行预测的过程。")
predicted = clf.predict(X_new_tfidf)
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, category))
# 最好是能讲数据序列化后上传到模型仓库
# 不过我们这里就先保存成表
import pickle
context.build_result([{"count_vect":pickle.dumps(count_vect),"tfidf_transformer":pickle.dumps(tfidf_transformer),"nb":pickle.dumps(clf)}])
''' named model_data;
-- 把三个模型保存到数据湖
save overwrite model_data as delta.`ai_model.20newsgroups` where overwriteSchema="true";
上述代码从数据湖中提取数据,使用SQL进行简单处理,然后使用Python做了一个文本分类训练,最后把模型保存回数据湖中。
从语言层面来讲,MLSQL有点三不像:
我们相信部分任务仅仅用类似命令行就能解决,大部分仅仅用SQL就能解决,只有非常少的一部分才需要动手写Python。因此MLSQL将SQL作为一等公民,命令行是SQL的一个语法糖,Python作为内嵌语言,也是为了尽可能让语言的使用更简单。
MLSQL底层脚本执行引擎采用的是Spark,这意味着MLSQL可以充分利用现有的大数据生态,目前已经支持市面上大部分存储,包括数仓、关系型数据库、数据湖、分布式文件系统等,并且可以利用Spark自身强大的算力完成混算。而基于MLSQL另外一个子项目PyJava开发的Python执行引擎,则使得用户可以充分利用Python的生态体系。另外,MLSQL也对分布式机器学习框架Ray做了深度的集成,并且支持插拔使用。
MLSQL底层架构如下图所示,使用者可以用MLSQL同时完成批处理、AdHoc计算、流式计算、机器学习等诸多任务。
不要被架构图的复杂度吓到,MLSQL执行引擎的部署和一个普通的Spark应用没有任何区别。
除此之外,MLSQL还有诸多特性,譬如:
以上两个项目的开源地址如下:
当下编程语言越来越趋向领域化,最终都是要让合适的语言为合适的领域助力。我们相信,大数据和AI的蓬勃发展,必然需要一个更加为之量身定制的语言。以SQLFlow、MLSQL为代表的这类语言的诞生正是顺应了这个趋势。
领取专属 10元无门槛券
私享最新 技术干货