1. 程式人生 > 其它 >PaddlePaddle:在 Serverless 架構上十幾行程式碼實現 OCR 能力

PaddlePaddle:在 Serverless 架構上十幾行程式碼實現 OCR 能力

飛槳 (PaddlePaddle) 以百度多年的深度學習技術研究和業務應用為基礎,是中國首個自主研發、功能完備、 開源開放的產業級深度學習平臺,集深度學習核心訓練和推理框架、基礎模型庫、端到端開發套件和豐富的工具元件於一體。


飛槳 (PaddlePaddle) 以百度多年的深度學習技術研究和業務應用為基礎,是中國首個自主研發、功能完備、 開源開放的產業級深度學習平臺,集深度學習核心訓練和推理框架、基礎模型庫、端到端開發套件和豐富的工具元件於一體。

飛槳深度學習框架採用基於程式設計邏輯的組網正規化,對於普通開發者而言更容易上手,同時支援宣告式和指令式程式設計,兼具開發的靈活性和高效能。另外飛槳不僅廣泛相容第三方開源框架訓練的模型部署,並且為不同的場景的生產環境提供了完備的推理引擎,包括適用於高效能伺服器及雲端推理的原生推理庫 Paddle Inference,面向分散式、流水線生產環境下自動上雲、A/B 測試等高階功能的服務化推理框架 Paddle Serving,針對於移動端、物聯網場景的輕量化推理引擎 Paddle Lite,以及在瀏覽器、小程式等環境下使用的前端推理引擎 Paddle.js。同時,透過與不同場景下的主流硬體高度適配優化及異構計算的支援, 飛槳的推理效能也領先絕大部分的主流實現。

安裝飛槳


飛槳可以被認為是一個 Python 的依賴庫,官方提供了 pip,conda,原始碼編譯等多種安裝方法。以 pip 安裝方法為例,飛槳提供了 CPU 和 GPU 兩個版本安裝方法:

  • CPU 版本安裝方法:

pip install paddlepaddle

  • GPU 版本安裝方法:

pip install paddlepaddle-gpu

實踐:手寫數字識別任務

MNIST 是非常有名的手寫體數字識別資料集,在無論是 Tensorflow 的官方網站還是 PaddlePaddle 的新手入門,都是通過它做實戰講解,它由手寫體數字的圖片和相對應的標籤組成,如:


MNIST 資料集分為訓練影象和測試影象。訓練影象 60000 張,測試影象 10000 張,每一個圖片代表 0-9 中的一個數字,且圖片大小均為 28*28 的矩陣。這一小節將會以 PaddlePaddle 官方提供的 MNIST 手寫數字識別任務為例,進行 PaddlePaddle 框架的基本學習。與其他深度學習任務一樣,飛槳同樣要通過以下四個步驟完成一個相對完整的深度學習任務:

  1. 資料集的準備和載入;
  2. 模型構建;
  3. 模型訓練;
  4. 模型評估。

載入內建資料集

飛槳框架內建了一些常見的資料集,在這個示例中,開發者可以載入飛槳框架的內建資料集,例如本案例所涉及到的手寫數字體資料集。這裡載入兩個資料集,一個用來訓練模型,一個用來評估模型。

import paddle.vision.transforms as T
transform = T.Normalize(mean=[127.5], std=[127.5], data_format='CHW')
下載資料集
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
val_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

模型搭建

通過 Sequential 將一層一層的網路結構組建起來。注意,需要先對資料進行 Flatten 操作,將 [1, 28, 28] 形狀的圖片資料改變形狀為 [1, 784]。

mnist = paddle.nn.Sequential(
paddle.nn.Flatten(),
paddle.nn.Linear(784, 512),
paddle.nn.ReLU(),
paddle.nn.Dropout(0.2),
paddle.nn.Linear(512, 10))

模型訓練


在訓練模型前,需要配置訓練模型時損失的計算方法與優化方法,開發者可以使用飛槳框架提供的 prepare 完成,之後使用 fit 介面來開始訓練模型。

# 預計模型結構生成模型物件,便於進行後續的配置、訓練和驗證
model=paddle.Model(mnist)
_# 模型訓練相關配置,準備損失計算方法,優化器和精度計算方法_model.prepare(paddle.optimizer.Adam(parameters=model.parameters()), paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy())
# 開始模型訓練
model.fit(train_dataset,
epochs=5,
batch_size=64,
verbose=1)

訓練結果:

The loss value printed in the log is the current step, and the metric is the average value of previous steps.Epoch 1/5step 938/938 [] - loss: 0.1801 - acc: 0.9032 - 8ms/stepEpoch 2/5step 938/938 [] - loss: 0.0544 - acc: 0.9502 - 8ms/stepEpoch 3/5step 938/938 [] - loss: 0.0069 - acc: 0.9595 - 7ms/stepEpoch 4/5step 938/938 [] - loss: 0.0094 - acc: 0.9638 - 7ms/stepEpoch 5/5step938/938[==============================]-loss:0.1414-acc:0.9670-8ms/step

模型評估


開發者可以使用預先定義的驗證資料集來評估前一步訓練得到的模型的精度。

model.evaluate(val_dataset, verbose=0)

結果如下:

{'loss': [2.145765e-06], 'acc': 0.9751}

可以看出,初步訓練得到的模型效果在 97.5% 附近,在逐漸瞭解飛槳後,開發者可以通過調整其中的訓練引數來提升模型的精度。

與 Serverless 架構結合

PaddlePaddle 團隊首次開源文字識別模型套件 PaddleOCR,目標是打造豐富、領先、實用的文字識別模型/工具庫。該模型套件是一個實用的超輕量 OCR 系統。主要由DB文字檢測、檢測框矯正和 CRNN 文字識別三部分組成。該系統從骨幹網路選擇和調整、預測頭部的設計、資料增強、學習率變換策略、正則化引數選擇、預訓練模型使用以及模型自動裁剪量化 8 個方面,採用 19 個有效策略,對各個模組的模型進行效果調優和瘦身,最終得到整體大小為 3.5M 的超輕量中英文 OCR 和 2.8M 的英文數字 OCR。

本地開發


# index.py
import base64
import bottle
import random
frompaddleocrimportPaddleOCR
ocr=PaddleOCR(use_gpu=False)
@bottle.route('/ocr', method='POST')
def login():
filePath = './temp/' + (''.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 5)))
with open(filePath, 'wb') as f:
f.write(base64.b64decode(bottle.request.body.read().decode("utf-8").split(',')[1]))
ocrResult = ocr.ocr(filePath, cls=False)
return{'result':[[line[1][0],float(line[1][1])]forlineinocrResult]}
bottle.run(host='0.0.0.0', port=8080)

開發完成之後,執行該專案:

python index.py

可以看到服務已經啟動:


然後通過 Postman 工具進行測試,首先準備一張圖片(此處以 PaddleOCR 專案內建的測試圖片為例):


通過將圖片轉換為 Base64 編碼,並以 POST 方法請求剛剛啟動的 Web 服務,可以看到 PaddleOCR 的執行結果:

部署到 Serverless 架構


目前各大雲廠商的 FaaS 平臺均已經逐漸支援容器映象部署。所以,可以將專案打包成映象,並通過 Serverless Devs 部署到阿里雲函式計算。

部署前準備

首先需要完成 Dockerfile 檔案:

FROMpython:3.7-slim
RUN apt update && apt install gcc libglib2.0-dev libgl1-mesa-glx libsm6 libxrender1 -y && pip install paddlepaddle bottle scikit-build paddleocrlescikit-buildpaddleocr
# Create app directory
WORKDIR/usr/src/app
# Bundle app source
COPY . .

編寫符合 Serverless Devs 規範的 Yaml 文件:

# s.yaml
edition: 1.0.0
name: paddle-ocr
access: default
services:
paddle-ocr:
component: fc
props:
region: cn-shanghai
service:
name: paddle-ocr
description: paddle-ocr service
function:
name: paddle-ocr-function
runtime: custom-container
caPort: 8080
codeUri: ./
timeout: 60
customContainerConfig:
image: 'registry.cn-shanghai.aliyuncs.com/custom-container/paddle-ocr:0.0.1'
command: '["python"]'
args: '["index.py"]'
triggers:

  • name: httpTrigger
    type: http
    config:
    authType: anonymous
    methods:
  • GET
  • POST
    customDomains:
  • domainName: auto
    protocol: HTTP
    routeConfigs:
  • path: /*

專案部署


首先構建映象,此處可以通過 Serverless Devs 進行構建:

s build --use-docker


構建完成之後,可以通過工具直接進行部署:

s deploy --push-registry acr-internet --use-local -y

部署完成,可以看到系統返回的測試地址:

專案測試

此時,可以通過該測試地址進行測試,同樣得到了預期效果:

專案優化

通過對部署在 Serverless 架構上的專案進行請求,可以看到冷啟動和熱啟動的時間消耗:


通過冷啟動與熱啟動的對比,我們可以發現,在熱啟動時,整個系統的效能是相對優秀的。但是遇到冷啟動整個專案的響應時常是不可控的,此時可以考慮一下途徑進行優化:

  1. 縮減容器映象的體積,減少不必要的依賴、檔案等,清理掉安裝依賴時留下的快取等;因為函式計算的冷啟動包括映象拉取時間;
  2. 部分流程進行優化,例如在 PaddleOCR 專案中有明確說明:“paddleocr 會自動下載 ppocr 輕量級模型作為預設模型”,所以這就意味著該專案在 Serverless 架構的冷啟動過程中,相對比熱啟動還增加了一個模型下載和解壓的流程,所以這一部分在必要時是可以打入到容器映象中,進而減少冷啟動帶來的影響;
  3. 開啟映象加速,可以有效降低容器映象的冷啟動,在阿里雲函式計算官方文件中有相關映象加速的效能測試描述:“開啟函式計算的映象加速後,可提速 2~5 倍,將分鐘級的映象拉取縮短至秒級”;
  4. 例項預留,最大程度上降低冷啟動率。通過例項預留,可以通過多種演算法/策略進行例項的預熱和預啟動,可以最大程度上降低 Serverless 架構冷啟動帶來的影響;