如何在Kubernetes上部署一個(gè)深度學(xué)習(xí)模型
- 了解如何使用 Kubermatic Kubernetes 平臺(tái)來(lái)部署、擴(kuò)展與管理圖像識(shí)別預(yù)測(cè)的深度學(xué)習(xí)模型。
隨著企業(yè)增加了對(duì)人工智能(AI)、機(jī)器學(xué)習(xí)(ML)與深度學(xué)習(xí)(DL)的使用,出現(xiàn)了一個(gè)關(guān)鍵問(wèn)題:如何將機(jī)器學(xué)習(xí)的開(kāi)發(fā)進(jìn)行規(guī)模化與產(chǎn)業(yè)化?這些討論經(jīng)常聚焦于機(jī)器學(xué)習(xí)模型本身;然而,模型僅僅只是完整解決方案的其中一環(huán)。為了達(dá)到生產(chǎn)環(huán)境的應(yīng)用和規(guī)模,模型的開(kāi)發(fā)過(guò)程必須還包括一個(gè)可以說(shuō)明開(kāi)發(fā)前后關(guān)鍵活動(dòng)以及可公用部署的可重復(fù)過(guò)程。
本文演示了如何使用 Kubermatic Kubernetes 平臺(tái)對(duì)圖像識(shí)別預(yù)測(cè)的深度學(xué)習(xí)模型進(jìn)行部署、擴(kuò)展與管理。
Kubermatic Kubernetes 平臺(tái)是一個(gè)生產(chǎn)級(jí)的開(kāi)源 Kubernetes 集群管理工具,提供靈活性和自動(dòng)化,與機(jī)器學(xué)習(xí)/深度學(xué)習(xí)工作流程整合,具有完整的集群生命周期管理。
開(kāi)始
這個(gè)例子部署了一個(gè)用于圖像識(shí)別的深度學(xué)習(xí)模型。它使用了 CIFAR-10 數(shù)據(jù)集,包含了 60,000 張分屬 10 個(gè)類別的 32x32 彩色圖,同時(shí)使用了 Apache MXNet 的 Gluon 與 NVIDIA GPU 進(jìn)行加速計(jì)算。如果你希望使用 CIFAR-10 數(shù)據(jù)集的預(yù)訓(xùn)練模型,可以查閱其 入門(mén)指南。
使用訓(xùn)練集中的樣本對(duì)模型訓(xùn)練 200 次,只要訓(xùn)練誤差保持緩慢減少,就可以保證模型不會(huì)過(guò)擬合。下方圖展示了訓(xùn)練的過(guò)程:
訓(xùn)練結(jié)束后,必須保存模型訓(xùn)練所得到的參數(shù),以便稍后可以加載它們:
- file_name = "net.params"
- net.save_parameters(file_name)
一旦你的模型訓(xùn)練好了,就可以用 Flask 服務(wù)器來(lái)封裝它。下方的程序演示了如何接收請(qǐng)求中的一張圖片作為參數(shù),并在響應(yīng)中返回模型的預(yù)測(cè)結(jié)果:
- from gluoncv.model_zoo import get_model
- import matplotlib.pyplot as plt
- from mxnet import gluon, nd, image
- from mxnet.gluon.data.vision import transforms
- from gluoncv import utils
- from PIL import Image
- import io
- import flask
- app = flask.Flask(__name__)
- @app.route("/predict",methods=["POST"])
- def predict():
- if flask.request.method == "POST":
- if flask.request.files.get("img"):
- img = Image.open(io.BytesIO(flask.request.files["img"].read()))
- transform_fn = transforms.Compose([
- transforms.Resize(32),
- transforms.CenterCrop(32),
- transforms.ToTensor(),
- transforms.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010])])
- img = transform_fn(nd.array(img))
- net = get_model('cifar_resnet20_v1', classes=10)
- net.load_parameters('net.params')
- pred = net(img.expand_dims(axis=0))
- class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
- 'dog', 'frog', 'horse', 'ship', 'truck']
- ind = nd.argmax(pred, axis=1).astype('int')
- prediction = 'The input picture is classified as [%s], with probability %.3f.'%
- (class_names[ind.asscalar()], nd.softmax(pred)[0][ind].asscalar())
- return prediction
- if __name__ == '__main__':
- app.run(host='0.0.0.0')
容器化模型
在將模型部署到 Kubernetes 前,你需要先安裝 Docker 并使用你的模型創(chuàng)建一個(gè)鏡像。
下載、安裝并啟動(dòng) Docker:
- sudo yum install -y yum-utils device-mapper-persistent-data lvm2
- sudo yum-config-manager --add-repo <https://download.docker.com/linux/centos/docker-ce.repo>
- sudo yum install docker-ce
- sudo systemctl start docker
創(chuàng)建一個(gè)你用來(lái)管理代碼與依賴的文件夾:
- mkdir kubermatic-dl
- cd kubermatic-dl
創(chuàng)建 requirements.txt 文件管理代碼運(yùn)行時(shí)需要的所有依賴:
- flask
- gluoncv
- matplotlib
- mxnet
- requests
- Pillow
創(chuàng)建 Dockerfile,Docker 將根據(jù)這個(gè)文件創(chuàng)建鏡像:
- FROM python:3.6
- WORKDIR /app
- COPY requirements.txt /app
- RUN pip install -r ./requirements.txt
- COPY app.py /app
- CMD ["python", "app.py"]
這個(gè) Dockerfile 主要可以分為三個(gè)部分。首先,Docker 會(huì)下載 Python 的基礎(chǔ)鏡像。然后,Docker 會(huì)使用 Python 的包管理工具 pip 安裝 requirements.txt 記錄的包。最后,Docker 會(huì)通過(guò)執(zhí)行 python app.py 來(lái)運(yùn)行你的腳本。
構(gòu)建 Docker 容器:
- sudo docker build -t kubermatic-dl:latest .
這條命令使用 kubermatic-dl 鏡像為你當(dāng)前工作目錄的代碼創(chuàng)建了一個(gè)容器。
使用
- sudo docker run -d -p 5000:5000 kubermatic-dl
命令檢查你的容器可以在你的主機(jī)上正常運(yùn)行。
使用
- sudo docker ps -a
命令查看你本地容器的運(yùn)行狀態(tài):
查看容器的運(yùn)行狀態(tài)
將你的模型上傳到 Docker Hub
在向 Kubernetes 上部署模型前,你的鏡像首先需要是公開(kāi)可用的。你可以通過(guò)將你的模型上傳到 Docker Hub 來(lái)將它公開(kāi)。(如果你沒(méi)有 Docker Hub 的賬號(hào),你需要先創(chuàng)建一個(gè))
在終端中登錄 Docker Hub 賬號(hào):
- sudo docker login
給你的鏡像打上標(biāo)簽,這樣你的模型上傳到 Docker Hub 后也能擁有版本信息:
- sudo docker tag <your-image-id> <your-docker-hub-name>/<your-app-name>
- sudo docker push <your-docker-hub-name>/<your-app-name>
給鏡像打上 tag
使用
- sudo docker images
命令檢查你的鏡像的 ID。
部署你的模型到 Kubernetes 集群
首先在 Kubermatic Kubernetes 平臺(tái)創(chuàng)建一個(gè)項(xiàng)目, 然后根據(jù) 快速開(kāi)始 創(chuàng)建一個(gè) Kubernetes 集群。
創(chuàng)建一個(gè) Kubernetes 集群
下載用于訪問(wèn)你的集群的 kubeconfig,將它放置在下載目錄中,并記得設(shè)置合適的環(huán)境變量,使得你的環(huán)境能找到它:
Kubernetes 集群示例
使用 kubectl 命令檢查集群信息,例如,需要檢查 kube-system 是否在你的集群正常啟動(dòng)了就可以使用命令 kubectl cluster-info。
為了在集群中運(yùn)行容器,你需要?jiǎng)?chuàng)建一個(gè)部署用的配置文件(deployment.yaml),再運(yùn)行 apply 命令將其應(yīng)用于集群中:
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: kubermatic-dl-deployment
- spec:
- selector:
- matchLabels:
- app: kubermatic-dl
- replicas: 3
- template:
- metadata:
- labels:
- app: kubermatic-dl
- spec:
- containers:
- - name: kubermatic-dl
- image: kubermatic00/kubermatic-dl:latest
- imagePullPolicy: Always
- ports:
- - containerPort: 8080
- kubectl apply -f deployment.yaml`
為了將你的部署開(kāi)放到公網(wǎng)環(huán)境,你需要一個(gè)能夠給你的容器創(chuàng)建外部可達(dá) IP 地址的服務(wù):
- kubectl expose deployment kubermatic-dl-deployment --type=LoadBalancer --port 80 --target-port 5000`
就快大功告成了!首先檢查你布署的服務(wù)的狀態(tài),然后通過(guò) IP 請(qǐng)求的你圖像識(shí)別 API:
- kubectl get service
最后根據(jù)你的外部 IP 使用以下兩張圖片對(duì)你的圖像識(shí)別服務(wù)進(jìn)行測(cè)試:
總結(jié)
在這篇教程中,你可以創(chuàng)建一個(gè)深度學(xué)習(xí)模型,并且使用 Flask 提供 REST API 服務(wù)。它介紹了如何將應(yīng)用放在 Docker 容器中,如何將這個(gè)鏡像上傳到 Docker Hub 中,以及如何使用 Kubernetes 部署你的服務(wù)。只需幾個(gè)簡(jiǎn)單的命令,你就可以使用 Kubermatic Kubernetes 平臺(tái)部署該應(yīng)用程序,并且開(kāi)放服務(wù)給別人使用。