使用ML.NET + Azure DevOps + Azure Container Instances打造機器學習生產化
介紹
Azure DevOps,以前稱為Visual Studio Team Services(VSTS),可幫助個人和組織更快地規劃,協作和釋出產品。其中一項值得注意的服務是Azure Pipelines,它可以幫助開發人員構建持續整合(CI)和持續交付(CD)管道,從而自動化和標準化軟體開發過程的構建,測試和部署階段。此外,Azure Pipelines還提供本機容器支援,可與任何語言,平臺和雲配合使用。像軟體開發這樣的機器學習也是一個包括構建,測試和部署階段的過程,這使其成為自動化和標準化的良好候選者。在Build 2018,微軟宣佈推出ML.NET,.NET的開源,跨平臺機器學習框架。
先決條件
應用程式
因為這篇文章的目的是演示Azure Devops的功能而不是ML.NET的功能,所以我將從一個預構建的應用程式開始。
- 使用ML.NET和Azure Function進行機器學習 - 第1部分
- 使用ML.NET和Azure Function進行機器學習 - 第2部分
- 使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET機器學習模型
本文中使用的應用程式包含三個.NET Core專案。一個是類庫,我們將使用它來為訓練模型包裝ML.NET功能,以及載入預先訓練的模型,然後將其用於進行預測。另一個是.NET Core控制檯應用程式,它引用類庫來訓練和持久化ML.NET模型。
Class Library
可以在MLModel
目錄中找到類庫。類庫定義觀察和預測資料類,它們分別可以在IrisData.cs
和IrisPrediction.cs
檔案中找到。此外,Model
該類包含輔助方法,用於訓練和儲存機器學習模型,載入預先訓練的模型並使用這些模型進行預測。
控制檯應用
在解決方案目錄中,我們在目錄中也有一個控制檯應用程式ModelTrainer
。此應用程式引用MLModel
目錄中的類庫來訓練和持久化機器學習模型。
API
該ModelApi
目錄包含一個ASP.NET Core Web API應用程式,該應用程式引用MLModel
類庫專案以載入由ModelTrainer
控制檯應用程式訓練並通過HTTP進行預測的預訓練模型。可以在ModelApi應用程式Controllers目錄中的PredictController.cs
類中找到進行預測的邏輯。
CI / CD管道流程
從概念上講,當手動構建和部署應用程式時,機器學習模型在MLModel
類庫中定義和開發。一旦對模型滿意,就會構建類庫。MLModel
構建引用類庫的控制檯應用程式以及執行以在稱為的檔案中訓練和持久化分類模型model.zip
。該MLModel
類庫也被引用的ModelApi
ASP.NET核心專案。因為ModelApi
我們要部署的應用程式是為了公開我們預先訓練好的機器學習模型,所以我們需要找到一種方法來打包它以進行部署。我們將使用Azure Container Instances部署ModelApi
意味著我們需要建立專案的Docker映象,然後將其推送到Docker登錄檔,以供公眾使用。可以使用Azure DevOps標準化和自動化構建多個專案以及將Docker映象構建,釋出和部署到Azure Container Instances。本文的其餘部分將重點介紹如何使用Azure管道通過Azure DevOps中的CI / CD管道逐步操作此機器學習應用程式。
獲取程式碼
在開始之前,您要做的第一件事就是將mlnetazdevopssample GitHub儲存庫分成您自己的GitHub帳戶。
建立專案
導航到https://devops.azure.com,單擊Start Free
並按照提示建立新帳戶或登入現有帳戶。
登入後,單擊Create Project
。
輸入專案名稱以及簡短說明。然後,單擊Create
。
持續整合(CI)管道
使用Azure管道,我們將為應用程式的構建和打包步驟配置CI管道。以下是我們的CI管道中涉及的所有步驟的說明:
- 構建類庫應用程式
- 構建控制檯應用程式
- 通過執行控制檯應用程式來訓練和持久化ML.NET模型。
- 將控制檯應用程式建立的ML.NET模型檔案複製到ASP.NET Core Web API應用程式目錄中
- 構建ASP.NET Core Web API應用程式
- 構建Docker映象
- 將Docker映象推送到Docker Hub
CI管道設定
建立專案後,在主專案頁面中,將滑鼠懸停在上Pipelines
,然後單擊Builds
。
在Builds
管道頁面中,單擊New pipeline
。
選擇GitHub作為源,並將您的GitHub帳戶與Azure DevOps連線。
一旦您授權Azure DevOps使用您的GitHub帳戶,請選擇將用於此構建管道的儲存庫和分支。在我們的例子中,我們將使用mlnetazdevopssample
儲存庫的主分支。完成配置後,單擊Continue
。
下一步是選擇要在我們的管道中執行的作業。因為這個構建管道中有多個步驟,所以讓我們從一個開始,Empty Job
並根據我們的需要進行自定義。
在構建管道頁面內部,在我們開始新增作業之前,讓我們選擇將執行作業的代理。對於此管道,請Hosted Ubuntu 1604
從下拉列表中選擇該選項。
1.構建類庫應用程式
我們的CI管道的第一步是構建我們的類庫,其中包含包含ML.NET框架和持久模型的訓練,載入和預測功能的方法。
為此,我們將向我們新增一個.NET Core任務Agent Job 1
。
新增到管道後,讓我們配置此任務。為了使其更具描述性,我們可以給它一個名稱,如Build Class Library
。因為此任務將負責構建.NET Core類庫,所以我們將保留預設的build
Command設定。
我們要配置的另一個設定是Working Directory
。我們可以通過單擊Advanced
選項卡來完成。
對於此任務,我們將使用該MLModel
目錄。
完成配置後,單擊頂部工具欄上的Save & Queue
- > Save
。
輸入描述管道更改的詳細註釋,然後單擊Save
。
2.構建控制檯應用程式
一旦我們構建了我們將從.NET Core控制檯和ASP.NET Core Web API應用程式引用的類庫應用程式,就可以構建控制檯應用程式,這將用於訓練和持久化ML.NET模型。
與上一步類似,將新的.NET Core 構建任務新增到管道。將為此任務更改的唯一設定是Working Directory
具有值的值ModelTrainer
。
雖然不是必需的,但在完成任務配置後,單擊Save & Queue
- > Save
以儲存並註釋對管道的更改。
3.訓練並持久化ML.NET模型
現在我們的控制檯應用程式已經構建完畢,是時候執行它來訓練和持久化ML.NET模型了。為此,我們將新增另一個.NET Core任務。不同之處在於Command
現在將使用該run
值配置設定。
在Working Directory
將被設定為ModelTrainer
在前面的任務一樣。
請記住儲存並註釋管道的新更改。
4.將ML.NET模型複製到Web API目錄
執行控制檯應用程式並訓練ML.NET模型後,它將保留model.zip
在ModelTrainer呼叫
目錄中。我們可以使用此持久化版本的模型從控制檯應用程式或我們選擇的任何其他應用程式進行預測。在這種情況下,我們將通過ASP.NET Core Web API進行預測。為了讓我們的API引用此檔案,我們需要將其複製到我們ModelApi
目錄的根目錄中。執行該任務的方法是通過bash指令碼。要向我們的管道新增bash指令碼,我們需要做的就是向它新增一個Bash任務。
一旦新增到我們的管道,就可以配置任務了。我們將設定的Type
設定Inline
將顯示一個文字框,供我們輸入指令碼。
在文字框內,輸入以下內容:
# Write your commands here cp ../ModelTrainer/model.zip . # Use the environment variables input below to pass secret variables to this script
我們可以Working Directory
將此步驟設定為ModelApi
。此命令將model.zip
檔案從ModelTrainer
目錄複製到ModelApi
目錄。
完成後,將新更改儲存並註釋到管道。
5.構建ASP.NET Core Web API應用程式
現在我們在ModelApi
應用程式中有了必要的檔案,是時候構建它了。我們將向我們的管道新增一個.NET Core任務並設定Command
為build
。這Working Directory
將ModelApi
像上一個任務一樣。
完成後,儲存並註釋管道的新更改。
6.構建ASP.NET Core Web API Docker映象
ASP.NET Core Web API應用程式的部署方法是通過容器。因此,在構建應用程式之後,我們必須為它構建一個Docker映象,然後可以將其推送到您選擇的Docker登錄檔。要構建Docker映象,我們將向管道新增Docker任務。
當我們配置任務時,我們將從設定為Container Registry Type
開始Container Registry
。
這將提示設定與Docker登錄檔的服務連線(如果尚不存在)。
我們將使用的Docker登錄檔型別是Docker Hub。為連線命名,輸入Docker Hub帳戶的憑據,然後單擊Verify this connection
以確保您的憑據有效,並且可以與Docker Hub建立連線。完成後點選OK
。
該Command
設定將build
因此我們可以保留預設值是還有Dockerfile
其中會使用到Dockerfile在根目錄設定mlnetazdevopssample
目錄。
最後,我們將配置Image name
設定。我們將使用的慣例是<docker-hub-username>/<image-name>
。就我而言,lqdev
是我的Docker Hub的使用者名稱,並在lqdev/mlnetazdevopssample命名我的映象為mlnetazdevopssample
。此外,選中Include latest tag
複選框以使每個構建都是最新的,而不是使用版本號標記它。
請記住儲存並註釋最近對管道的更改。
7.將Docker Image推送到Docker Hub
CI管道的最後一步是將新構建的映象推送到Docker Hub。為此,我們將使用anoter Docker任務。
與上一個任務一樣,我們將設定Container registry type
為Container Registry
。Docker registry service connection
通過從下拉列表中選擇連線,將其設定為最近建立的連線。我們將更Command
改為push
並設定Image name
為上一步中構建的影象的名稱。命名約定是<docker-hub-username>/<image-name>:latest
。我們以前的Docker構建任務添加了最新的標記,因此請確保將其包含在此任務中。
完成後,單擊Save & Queue
- > Save & Queue
。此操作將手動觸發CI管道。
不要忘記註釋您的更改,然後單擊Save & queue
以啟動CI管道。
監控構建
構建開始時,您可以單擊左窗格中Builds
的Pipelines
部分下方。
從列表中選擇第一個構建以獲取有關構建的更多詳細資訊。
這將帶您進入實時顯示管道狀態的日誌。
確認CI管道成功
如果構建成功,請導航到https://hub.docker.com/以檢查Docker映象是否已推送到登錄檔。
持續交付(CD)管道
現在我們已經建立了CI管道,它將構建和打包我們的應用程式,現在是時候部署它了。我們可以自己做或者使用CD管道自動化它。我們的應用程式將部署到Azure Container Instances,這是一項Azure服務,提供了一種快速執行容器的方法,而無需擔心虛擬機器或業務流程服務的管理。我們的CD管道涉及的步驟如下:
- 建立Azure資源組以進行部署
- 將應用程式部署到Azure Container Instances
CD管道設定
要開始設定CD管道,請從Azure DevOps專案主頁面懸停Pipelines
並單擊Releases
。
進入該頁面後,單擊New pipeline
。
與我們的CI管道一樣,我們將從稍後開始Empty Job
配置。
觸發部署
建立管道後,就可以配置它了。我們要做的第一件事是新增一個工件。工件可以是各種各樣的東西,包括構建管道的輸出。在我們的例子中,我們的CI管道將成為我們CD管道的觸發器。要新增工件,請單擊Add an artifact
。
在配置表單,設定Source type
到Build
和Source
在前面的步驟中建立的CI管道的名稱。完成後,單擊Add
。
在配置我們的工件之後,是時候配置CD管道中的步驟了。為此,請單擊發布管道頁面部分中的Stage 1
選項,Stages
並將名稱更改為更具描述性的名稱。
完成後,關閉表單並單擊Stages標題下方的超連結。
您現在應該位於類似於CI管道作業配置頁面的頁面上。在此頁面上,我們將要單擊Agent Job
面板以將Agent pool
設定設定為Hosted Ubuntu 1604
。
完成後,就可以在CD管道中配置任務了。
1.建立Azure資源組
開始向Azure CLI
管道新增任務。在此任務中,我們將在Azure中建立一個資源組,我們將部署應用程式。
在執行任何其他操作之前,將DevOps連結到Azure訂閱,方法是從下拉列表中選擇一個,然後單擊Authorize
該訂閱將提示您對訂閱進行身份驗證。
連線Azure訂閱後,讓我們將Script Location
設定更改為Inline Script
。
在Inline Script
文字框中輸入以下內容:
az group create --name mlnetazdevopssampleresourcegroup --location eastus
這個指令碼會在Azure中建立位於eastus的
資源組命名為mlnetazdevopssampleresourcegroup
。這兩個配置項可以根據您的喜好進行調整。
2.將Docker映象部署到Azure Container Instances
CD管道中的下一步也是最後一步是部署到Azure Container Instances。要部署我們的應用程式,我們將新增另一項Azure CLI
任務。這一次,由於我們已經Azure subscription
在上一個任務中配置了我們,因此我們可以選擇服務連線而不是下拉列表中的訂閱。
與上一個任務一樣,我們的指令碼將是Inline的。
在Inline Script
文字框中輸入以下內容:
az container create --resource-group mlnetazdevopssampleresourcegroup --name mlnetcontainer --image lqdev/mlnetazdevopssample:latest --ports 80 --ip-address public
配置完此步驟後,請確保通過單擊儲存並註釋所有更改Save
。此指令碼在由管道的上一個任務建立的資源組中建立一個容器,其中包含mlnetcontainer
來自Docker影象的名稱,該影象由CI管道推送到Docker Hub。此外,它開啟埠80併為外部訪問的容器分配可公開訪問的IP地址。
然後,為了使其易於識別,請通過將滑鼠懸停在附近New release pipeline
並單擊鉛筆圖示來編輯管道的名稱。
確保儲存並註釋您的更改。
自動化CI / CD管道
在前面的步驟中,我們配置了CI和CD管道。但是,我們仍然沒有完全自動化啟動這兩者的觸發器。
CI管道觸發器
首先,讓我們通過自動化CI管道開始。為此,請轉到專案的主頁面,將滑鼠懸停在上面Pipelines
並單擊Builds
。
這將帶您進入CI管道頁面。在此頁面上,單擊Edit
。
然後,單擊Triggers
。
進入此頁面後,選中Enable continous integration
複選框,然後單擊Save & Queue
- > 儲存並註釋您的更改Save
。
CD管道觸發器
要自動化CD管道觸發器,請單擊頁面Releases
下方Pipelines
以自動化CD管道。
進入CD管道的頁面後,單擊Edit
。
然後,單擊Artifacts部分中的閃電圖示,該圖示將顯示配置表單。在此表單中,將Continuous deployment trigger
設定切換為Enabled
。
完成後,儲存並註釋您的更改。
執行CI / CD管道
雖然在將新更改簽入mlnetazdevopssample
儲存庫的主分支時將啟動前進構建和部署,但出於演示目的,我們將手動啟動我們剛剛配置的CI / CD管道。為此,請單擊左窗格中的Pipelines
下方的Builds。
從CI管道頁面單擊Queue
。
這將提示顯示一個模式,您可以在其中單擊Queue
以啟動構建。
這將啟動一個新的CI構建,隨後也將啟動您的應用程式的CD管道。
測試部署
如果一切都成功,ASP.NET Core Web API應用程式的Docker映象將部署到Azure Container Instances,可以通過公共IP地址訪問。
要檢視部署是否有效,請導航至https://portal.azure.com/並單擊Resource groups
。
此時,您應該看到CD管道建立的資源組。如果是這種情況,請單擊它。
然後,這將顯示一個頁面,顯示部署到此資源組的容器。點選它。
容器頁面將顯示有關容器的診斷和配置資訊。我們感興趣的資訊是IP address
。將滑鼠懸停在其右側並單擊顯示的圖示Click to copy
。這會將地址複製到剪貼簿。
在像Postman或Insomnia這樣的應用程式中,向Azure 發出一個HTTP POST請求,http://<ip-address>/api/predict
其中ip-address
包含Azure中容器的公共IP地址,具有以下正文。
{ "SepalLength":3.3, "SepalWidth":1.6, "PetalLength":0.2, "PetalWidth":5.1 }
如果成功,響應將是Iris-virginica
。
小結
在這篇文章中,我們實現了ML.NET應用程式的構建,打包和部署,該應用程式使用Azure DevOps實現對鳶尾花的分類進行預測。我們建立了Continous Integration和Continous Delivery管道,它將ASP.NET Core Web API的Docker映象部署到Azure Container Instances。請記住,這只是其中一種方法,Azure DevOps可以靈活地配置所有這些任務和工作流以滿足您的要求。