自動(dòng)部署開(kāi)源AI模型到生產(chǎn)環(huán)境:Scikit-learn、XGBoost、LightGBM、和PySpark

目錄

背景介紹

AI的廣泛應(yīng)用是由AI在開(kāi)源技術(shù)的進(jìn)步推動(dòng)的,利用功能強(qiáng)大的開(kāi)源模型庫(kù),數(shù)據(jù)科學(xué)家們可以很容易的訓(xùn)練一個(gè)性能不錯(cuò)的模型。但是因?yàn)槟P蜕a(chǎn)環(huán)境和開(kāi)發(fā)環(huán)境的不同,涉及到不同角色人員:模型訓(xùn)練是數(shù)據(jù)科學(xué)家和數(shù)據(jù)分析師的工作,但是模型部署是開(kāi)發(fā)和運(yùn)維工程師的事情,導(dǎo)致模型上線部署卻不是那么容易。

DaaS(Deployment-as-a-Service)是AutoDeployAI公司推出的基于Kubernetes的AI模型自動(dòng)部署系統(tǒng),提供一鍵式自動(dòng)部署開(kāi)源AI模型生成REST API,以方便在生產(chǎn)環(huán)境中調(diào)用。下面,我們主要演示在DaaS中如何部署經(jīng)典機(jī)器學(xué)習(xí)模型,包括Scikit-learn、XGBoost、LightGBM、和PySpark ML Pipelines。關(guān)于深度學(xué)習(xí)模型的部署,會(huì)在下一章中介紹。

部署準(zhǔn)備

我們使用DaaS提供的Python客戶端(DaaS-Client)來(lái)部署模型,對(duì)于XGBoost和LightGBM,我們同樣使用它們的Python API來(lái)作模型訓(xùn)練。在訓(xùn)練和部署模型之前,我們需要完成以下操作。

  1. 安裝Python DaaS-Client。

    pip install --upgrade git+https://github.com/autodeployai/daas-client.git
    
  2. 初始化DaasClient。使用DaaS系統(tǒng)的URL、賬戶、密碼登陸系統(tǒng),文本使用的DaaS演示系統(tǒng)安裝在本地的Minikube上。完整Jupyter Notebook,請(qǐng)參考:deploy-sklearn-xgboost-lightgbm-pyspark.ipynb

    from daas_client import DaasClient
    
    client = DaasClient('https://192.168.64.3:30931', 'username', 'password')
    
  3. 創(chuàng)建項(xiàng)目。DaaS使用項(xiàng)目管理用戶不同的分析任務(wù),一個(gè)項(xiàng)目中可以包含用戶的各種分析資產(chǎn):模型、部署、程序腳本、數(shù)據(jù)、數(shù)據(jù)源等。項(xiàng)目創(chuàng)建成功后,設(shè)置為當(dāng)前活動(dòng)項(xiàng)目,發(fā)布的模型和創(chuàng)建的部署都會(huì)存儲(chǔ)在該項(xiàng)目下。create_project函數(shù)接受三個(gè)參數(shù):

    1. 項(xiàng)目名稱:可以是任意有效的Linux文件目錄名。
    2. 項(xiàng)目路由:使用在部署的REST URL中來(lái)唯一表示當(dāng)前項(xiàng)目,只能是小寫(xiě)英文字符(a-z),數(shù)字(0-9)和中橫線-,并且-不能在開(kāi)頭和結(jié)尾處。
    3. 項(xiàng)目說(shuō)明(可選):可以是任意字符。
    project = '部署測(cè)試'
    if not client.project_exists(project):
        client.create_project(project, 'deployment-test', '部署測(cè)試項(xiàng)目')
    client.set_project(project)
    
  4. 初始化數(shù)據(jù)。我們使用流行的分類數(shù)據(jù)集iris來(lái)訓(xùn)練不同的模型,并且把數(shù)據(jù)分割為訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集以方便后續(xù)使用。

    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    import pandas as pd
    
    seed = 123456
    
    iris = datasets.load_iris()
    iris_target_name = 'Species'
    iris_feature_names = iris.feature_names
    iris_df = pd.DataFrame(iris.data, columns=iris_feature_names)
    iris_df[iris_target_name] = iris.target
    
    X, y = iris_df[iris_feature_names], iris_df[iris_target_name]
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=seed)    
    
  5. 模型部署流程。主要包含以下幾步:

    1. 訓(xùn)練模型。使用模型庫(kù)提供的API,在iris數(shù)據(jù)集上訓(xùn)練模型。
    2. 發(fā)布模型。調(diào)用publish函數(shù)發(fā)布模型到DaaS系統(tǒng)。
    3. 測(cè)試模型(可選)。調(diào)用test函數(shù)獲取測(cè)試API信息,可以使用任意的REST客戶端程序測(cè)試模型在DaaS中是否工作正常,使用的是DaaS系統(tǒng)模型測(cè)試API。第一次執(zhí)行test會(huì)比較慢,因?yàn)镈aaS系統(tǒng)需要啟動(dòng)測(cè)試運(yùn)行時(shí)環(huán)境。
    4. 部署模型。發(fā)布成功后,調(diào)用deploy函數(shù)部署部署模型。可以使用任意的REST客戶端程序測(cè)試模型部署,使用的是DaaS系統(tǒng)正式部署API。

部署Scikit-learn模型

  1. 訓(xùn)練一個(gè)Scikit-learn分類模型:SVC。

    from sklearn.svm import SVC
    
    model = SVC(probability=True, random_state=seed)
    model.fit(X_train, y_train)
    
  2. 發(fā)布Scikit-learn模型。

    publish_resp = client.publish(model,
                                name='iris',
                                mining_function='classification',
                                X_test=X_test,
                                y_test=y_test,
                                description='A SVC model')
    pprint(publish_resp)
    

    test函數(shù)必須要指定前兩個(gè)參數(shù),第一個(gè)model是訓(xùn)練的模型對(duì)象,第二個(gè)是模型名稱,其余是可選參數(shù):

    • mining_function:指定挖掘功能,可以指定為regression(回歸)、classification(分類)、和clustering(聚類)。
    • X_test和y_test:指定測(cè)試訓(xùn)練集,發(fā)布時(shí)計(jì)算模型評(píng)估指標(biāo),比如針對(duì)分類模型,計(jì)算正確率(Accuracy),對(duì)于回歸模型,計(jì)算可釋方差(explained Variance)。
    • data_test: 同樣是指定測(cè)試訓(xùn)練集,但是該參數(shù)用在Spark模型上,非Spark模型通過(guò)X_testy_test指定。
    • description:模型描述。
    • params:記錄模型參數(shù)設(shè)置。

    publish_resp是一個(gè)字典類型的結(jié)果,記錄了模型名稱,和發(fā)布的模型版本。該模型是iris模型的第一個(gè)版本。

    {'model_name': 'iris', 'model_version': '1'}
    
  3. 測(cè)試Scikit-learn模型。

    test_resp = client.test(publish_resp['model_name'], model_version=publish_resp['model_version'])
    pprint(test_resp)
    

    test_resp是一個(gè)字典類型的結(jié)果,記錄了測(cè)試REST API信息。如下,其中access_token是訪問(wèn)令牌,一個(gè)長(zhǎng)字符串,這里沒(méi)有顯示出來(lái)。endpoint_url指定測(cè)試REST API地址,payload提供了測(cè)試當(dāng)前模型需要輸入的請(qǐng)求正文格式。

    {'access_token': 'A-LONG-STRING-OF-BEARER-TOKEN-USED-IN-HTTP-HEADER-AUTHORIZATION',
    'endpoint_url': 'https://192.168.64.3:30931/api/v1/test/deployment-test/daas-python37-faas/test',
    'payload': {'args': {'X': [{'petal length (cm)': 1.5,
                                'petal width (cm)': 0.4,
                                'sepal length (cm)': 5.7,
                                'sepal width (cm)': 4.4}],
                        'model_name': 'iris',
                        'model_version': '1'}}}
    

    使用requests調(diào)用測(cè)試API,這里我們直接使用test_resp返回的測(cè)試payload,您也可以使用自定義的數(shù)據(jù)X,但是參數(shù)model_namemodel_version必須使用上面輸出的值。

    response = requests.post(test_resp['endpoint_url'],
                            headers={'Authorization': 'Bearer {token}'.format(token=test_resp['access_token'])},
                            json=test_resp['payload'],
                            verify=False)
    pprint(response.json())
    

    返回結(jié)果,不同于正式部署API,除了預(yù)測(cè)結(jié)果,測(cè)試API會(huì)同時(shí)返回標(biāo)準(zhǔn)控制臺(tái)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出內(nèi)容,以方便用戶碰到錯(cuò)誤時(shí),查看相關(guān)信息。

    {'result': [{'PredictedValue': 0,
                'Probabilities': [0.8977133931668801,
                                0.05476023239878367,
                                0.047526374434336216]}],
    'stderr': [],
    'stdout': []}
    
  4. 部署模型。

    deploy_resp = client.deploy(model_name='iris', 
                                deployment_name='iris-svc',
                                model_version=publish_resp['model_version'],
                                replicas=1)
    pprint(deploy_resp)
    

    deploy函數(shù)必須要指定模型名稱,和部署名稱。模型版本默認(rèn)為當(dāng)前最新版本(latest),副本數(shù)默認(rèn)是1。為了確保部署服務(wù)的穩(wěn)定性,還可以輸入部署運(yùn)行時(shí)環(huán)境分配指定CPU核數(shù)和使用內(nèi)存量,默認(rèn)為None,讓系統(tǒng)自動(dòng)分配。

    deploy_resp是一個(gè)字典類型的結(jié)果,記錄了正式部署REST API信息。如下,可以看到和測(cè)試結(jié)果類似,在payload中,我們不需要在輸入模型名稱和版本,因?yàn)檎讲渴鸱?wù)在創(chuàng)建是已經(jīng)記錄了這些信息,并且是一個(gè)獨(dú)占式服務(wù)。

    {'access_token': 'A-LONG-STRING-OF-BEARER-TOKEN-USED-IN-HTTP-HEADER-AUTHORIZATION',
    'endpoint_url': 'https://192.168.64.3:30931/api/v1/svc/deployment-test/iris-svc/predict',
    'payload': {'args': {'X': [{'petal length (cm)': 1.5,
                                'petal width (cm)': 0.4,
                                'sepal length (cm)': 5.7,
                                'sepal width (cm)': 4.4}]}}}
    

    使用requests調(diào)用測(cè)試API,這里我們直接使用test_resp返回的測(cè)試payload,您也可以使用自定義的數(shù)據(jù)。

    response = requests.post(deploy_resp['endpoint_url'],
                         headers={'Authorization': 'Bearer {token}'.format(token=deploy_resp['access_token'])},
                         json=deploy_resp['payload'],
                         verify=False)
    pprint(response.json())
    

    返回結(jié)果:

    {'result': [{'PredictedValue': 0,
                'Probabilities': [0.8977133931668801,
                                0.05476023239878367,
                                0.047526374434336216]}]}
    

部署XGBoost模型

XGBoost提供了兩套Python API,一套是原生Python API,另一套是基于Scikit-learn包裝API。您可以使用任何一種,下面的例子中我們使用基于Scikit-learn的Python API。

  1. 訓(xùn)練一個(gè)分類XGBoost模型:

    from xgboost import XGBClassifier
    
    model = XGBClassifier(max_depth=3, objective='multi:softprob', random_state=seed)
    model = model.fit(X_train, y_train)
    
  2. 發(fā)布XGBoost模型。

    publish_resp = client.publish(model,
                                name='iris',
                                mining_function='classification',
                                X_test=X_test,
                                y_test=y_test,
                                description='A XGBClassifier model')
    pprint(publish_resp)
    

    因?yàn)槿匀皇褂昧?code>iris這個(gè)模型名稱,所以該模型是iris的第二個(gè)版本。

    {'model_name': 'iris', 'model_version': '2'}
    
  3. 測(cè)試XGBoost模型。和Scikit-learn流程相同。

  4. 部署模型。和Scikit-learn流程相同,這里我們暫時(shí)先不創(chuàng)建獨(dú)立部署,后面我們會(huì)介紹如何在DaaS系統(tǒng)中管理部署,如何切換部署模型版本。

部署LightGBM模型

同XGBoost類似,LightGBM同樣提供了兩套Python API,一套是原生Python API,另一套是基于Scikit-learn包裝API。您可以使用任何一種,下面的例子中我們使用基于Scikit-learn的Python API。

  1. 訓(xùn)練一個(gè)分類LightGBM模型:

    from lightgbm import LGBMClassifier
    
    model = LGBMClassifier()
    model = model.fit(X_train, y_train, eval_set=[(X_test, y_test)])
    
  2. 發(fā)布LightGBM模型。

    publish_resp = client.publish(model,
                                name='iris',
                                mining_function='classification',
                                X_test=X_test,
                                y_test=y_test,
                                description='A LGBMClassifier model')
    pprint(publish_resp)
    

    LightGBM模型是iris的第三個(gè)版本。

    {'model_name': 'iris', 'model_version': '3'}
    
  3. 測(cè)試LightGBM模型。和Scikit-learn流程相同。

  4. 部署模型。和Scikit-learn流程相同,這里我們暫時(shí)先不創(chuàng)建獨(dú)立部署。

部署PySpark模型

  1. 訓(xùn)練一個(gè)PySpark分類模型:RandomForestClassifier。PySpark模型必須是一個(gè)PipelineModel,也就是說(shuō)必須使用Pipeline來(lái)建立模型,哪怕只有一個(gè)Pipeline節(jié)點(diǎn)。

    from pyspark.sql import SparkSession
    from pyspark.ml.classification import RandomForestClassifier
    from pyspark.ml.feature import VectorAssembler
    from pyspark.ml import Pipeline
    
    spark = SparkSession.builder.getOrCreate()
    df = spark.createDataFrame(iris_df)
    
    df_train, df_test = df.randomSplit([0.7, 0.3], seed=seed)
    assembler = VectorAssembler(inputCols=iris_feature_names,
                                outputCol='features')
    
    rf = RandomForestClassifier(seed=seed).setLabelCol(iris_target_name)
    pipe = Pipeline(stages=[assembler, rf])
    model = pipe.fit(df_train)
    
  2. 發(fā)布PySpark模型。

    publish_resp = client.publish(model,
                                name='iris',
                                mining_function='classification',
                                data_test=df_test,
                                description='A RandomForestClassifier of Spark model')
    pprint(publish_resp)
    

    PySpark模型是iris的第四個(gè)版本。

    {'model_name': 'iris', 'model_version': '4'}
    
  3. 測(cè)試PySpark模型。和Scikit-learn流程相同。

  4. 部署模型。和Scikit-learn流程相同,這里我們暫時(shí)先不創(chuàng)建獨(dú)立部署。

模型部署管理

打開(kāi)瀏覽器,登陸DaaS管理系統(tǒng)。進(jìn)入項(xiàng)目部署測(cè)試,切換到模型標(biāo)簽頁(yè),有一個(gè)iris模型,最新版本是v4,類型是Spark即我們最后發(fā)布的模型。

DaaS-models

點(diǎn)擊模型,進(jìn)入模型主頁(yè)(概述)。當(dāng)前v4是一個(gè)Spark Pipeline模型,正確率是94.23%,并且顯示了iris不同版本正確率歷史圖。下面羅列了模型的輸入和輸出變量,以及評(píng)估結(jié)果,當(dāng)前為空,因?yàn)檫€沒(méi)有在DaaS中執(zhí)行任何的模型評(píng)估任務(wù)。

DaaS-model-overview-v4

點(diǎn)擊v4,可以自由切換到其他版本。比如,切換到v1

DaaS-model-versions

v1版本是一個(gè)Scikit-learn SVM分類模型,正確率是98.00%。其他信息與v4類似。

DaaS-model-overview-v1

切換到模型部署標(biāo)簽頁(yè),有一個(gè)我們剛才創(chuàng)建的部署iris-svc,鼠標(biāo)移動(dòng)到操作菜單,選擇修改設(shè)置。可以看到,當(dāng)前部署服務(wù)關(guān)聯(lián)的是模型v1,就是我們剛才通過(guò)deploy函數(shù)部署的iris第一個(gè)版本Scikit-learn模型。選擇最新的v4,點(diǎn)擊命令保存并且重新部署,該部署就會(huì)切換到v4版本。

DaaS-edit-service

總結(jié)

通過(guò)Python DaaS-Client我們可以很容易的部署訓(xùn)練好的模型,并且在DaaS網(wǎng)絡(luò)客戶端管理這些模型和部署,可以支持自由切換部署中的模型版本。除了支持部署網(wǎng)絡(luò)(Web)服務(wù),DaaS還支持部署任務(wù)(Job)服務(wù),通過(guò)任務(wù)我們可以運(yùn)行離線批量預(yù)測(cè)和模型評(píng)估等,具體可以參考文章《自動(dòng)部署PMML模型生成REST API》

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,241評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,939評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,697評(píng)論 6 409
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,182評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,406評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,772評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,973評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,638評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,866評(píng)論 1 285
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,644評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,953評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容