是時候搞一個面向大數據和AI的新編程語言了

數據和AI正在成爲很多公司的重要資產。其中,數據代表了公司在特定領域的積累,也是公司的護城河,AI能力輸出則代表了公司對數據資產的利用深度。二者不可分,光有數據沒有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平臺依然困難

即使到今天,對很多公司來說,構建數據和AI平臺依然很困難:需要了解無數的組件,需要有大量經驗且分別懂SQL、Java、Scala、Python的開發、分析師、算法,或者需要了解各種雲產品並做組合以達到自己想要的效果。所有這些困難堆疊起來就會導致極其高昂的開發成本。同時,由於IT特有的屬性,即使做了這些投入,可能依然滿地是坑。面對底層無數存儲,如何做一個有效的權限控制就已經讓很多開發撓頭了。

而且,數據和AI應該是普惠的。在筆者看來,數據和AI不應該僅僅侷限在數據科學家手裏(包括分析師和算法),任何一個產品、運營,甚至任何一個有權訪問數據的人,都應該可以對這些數據進行價值開發。這種開發小到只是查看,或者導出成一個Excel,或者對外提供一個查詢接口,大到提供一個精準的推薦系統,都應該能比較容易地完成。

我們需要一個面向大數據和AI的新語言

前面說了這麼多,無非是想告訴大家:

  1. 大數據和AI需要融合成一個平臺;
  2. 構建這個平臺的成本應該要降下來;
  3. 數據和AI的使用門檻要降下來,人人都應該能夠利用數據給公司創造價值。

那怎麼才能實現上面這三個訴求呢?單單從平臺層面很難解決這個問題,這個時候我們就需要從語言層面着手了。我們需要一個能夠更好地融合大數據和AI的編程語言,它必須具備以下特點:

  1. 語言要足夠簡單,產品和運營也能很容易學會;
  2. 能夠同時完美滿足大數據和算法的需求,打通兩者互通的數據管道;
  3. 語言的執行引擎要是分佈式的,並具備強大的硬件資源管理能力,能夠滿足海量數據計算需求;
  4. 必須保護現有的投資,包括能夠複用現有的大數據生態和AI生態。

Python對大多數人還是有一定難度,而且無法很好地整合大數據生態。SQL簡單,但是無法滿足算法的複雜需求且難以利用AI領域大量生態。

我們希望用一個語言完成大數據批流處理以及AI的訓練和預測。我們希望在語言層面內建數據安全機制,解決無數底層存儲的訪問控制問題,讓開發不再撓頭。我們還希望這個語言內置的功能易於擴展,且能夠充分利用大數據和AI的構建語言Java/Scala/C++做擴展,因此這個語言的執行引擎應該具有強大的插件化能力。

目前正在朝着這個目標努力的編程語言有SQLFlow和MLSQL。

SQLFlow

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

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有點三不像:

  1. 有命令行的東西
  2. 有類SQL的東西
  3. 有Python

我們相信部分任務僅僅用類似命令行就能解決,大部分僅僅用SQL就能解決,只有非常少的一部分才需要動手寫Python。因此MLSQL將SQL作爲一等公民,命令行是SQL的一個語法糖,Python作爲內嵌語言,也是爲了儘可能讓語言的使用更簡單。

MLSQL底層腳本執行引擎採用的是Spark,這意味着MLSQL可以充分利用現有的大數據生態,目前已經支持市面上大部分存儲,包括數倉、關係型數據庫、數據湖、分佈式文件系統等,並且可以利用Spark自身強大的算力完成混算。而基於MLSQL另外一個子項目PyJava開發的Python執行引擎,則使得用戶可以充分利用Python的生態體系。另外,MLSQL也對分佈式機器學習框架Ray做了深度的集成,並且支持插拔使用。

MLSQL底層架構如下圖所示,使用者可以用MLSQL同時完成批處理、AdHoc計算、流式計算、機器學習等諸多任務。

不要被架構圖的複雜度嚇到,MLSQL執行引擎的部署和一個普通的Spark應用沒有任何區別。

除此之外,MLSQL還有諸多特性,譬如:

  1. 在語言層面內置了到列級別的權限訪問控制;
  2. 插件化內核,核心功能均採用內置插件完成,現在也有不少官方插件;
  3. 支持在腳本中使用Java/Scala語言書寫UDF/UDAF;
  4. 支持include語法,強化了SQL工程和複用能力。

以上兩個項目的開源地址如下:

結語

當下編程語言越來越趨向領域化,最終都是要讓合適的語言爲合適的領域助力。我們相信,大數據和AI的蓬勃發展,必然需要一個更加爲之量身定製的語言。以SQLFlow、MLSQL爲代表的這類語言的誕生正是順應了這個趨勢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章