Serverless 架構下 Python 輕鬆搞定圖像分類

2021-01-12 阿里云云棲號

簡介: 本文將會通過一個有趣的 Python 庫,快速將圖像分類的功能搭建在雲函數上,並且和 API 網關結合,對外提供 API 功能,實現一個 Serverless 架構的「圖像分類 API」。

前言

圖像分類是人工智慧領域的一個熱門話題。通俗解釋就是,根據各自在圖像信息中所反映的不同特徵,把不同類別的目標區分開來的圖像處理方法。

它利用計算機對圖像進行定量分析,把圖像或圖像中的每個像元或區域劃歸為若干個類別中的某一種,以代替人的視覺判讀。

圖像分類在實際生產生活中也是經常遇到的,而且針對不同領域或者需求有著很強的針對性。例如通過拍攝花朵識別花朵信息、通過人臉比對人物信息等。

通常情況下,這些圖像識別或者分類的工具,都是在客戶端進行數據採集,在服務端進行運算獲得結果,也就是說一般情況下都是有專門的 API 實現圖像識別的。例如各大雲廠商都會為我們有償提供類似的能力:

阿里雲圖像識別頁面:

華為雲圖像識別頁面:

本文將會通過一個有趣的 Python 庫,快速將圖像分類的功能搭建在雲函數上,並且和 API 網關結合,對外提供 API 功能,實現一個 Serverless 架構的「圖像分類 API」。

首先和大家介紹一下需要的依賴庫:ImageAI。通過該依賴的官方文檔我們可以看到這樣的描述:

ImageAI 是一個 python 庫,旨在使開發人員能夠使用簡單的幾行代碼構建具有包含深度學習和計算機視覺功能的應用程式和系統。ImageAI 本著簡潔的原則,支持最先進的機器學習算法,用於圖像預測、自定義圖像預測、物體檢測、視頻檢測、視頻對象跟蹤和圖像預測訓練。ImageAI 目前支持使用在 ImageNet-1000 數據集上訓練的 4 種不同機器學習算法進行圖像預測和訓練。ImageAI 還支持使用在 COCO 數據集上訓練的 RetinaNet 進行對象檢測、視頻檢測和對象跟蹤。最終,ImageAI 將為計算機視覺提供更廣泛和更專業化的支持,包括但不限於特殊環境和特殊領域的圖像識別。

也就是說這個依賴庫,可以幫助我們完成基本的圖像識別和視頻的目標提取,雖然他給了一些數據集和模型,但是我們也可以根據自身需要對其進行額外的訓練,進行定製化拓展。通過官方給的代碼,我們可以看到一個簡單的 Demo:

# -*- coding: utf-8 -*-from imageai.Prediction import ImagePrediction# 模型加載prediction = ImagePrediction()prediction.setModelTypeAsResNet()prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5 )for eachPrediction, eachProbability in zip(predictions, probabilities): print(str(eachPrediction) + " : " + str(eachProbability))當我們指定的 picture.jpg 圖片為:

我們在執行之後的結果是:

laptop : 71.43893241882324notebook : 16.265612840652466modem : 4.899394512176514hard_disc : 4.007557779550552mouse : 1.2981942854821682如果在使用過程中覺得模型 resnet50_weights_tf_dim_ordering_tf_kernels.h5 過大,耗時過長,可以按需求選擇模型:

SqueezeNet(文件大小:4.82 MB,預測時間最短,精準度適中)ResNet50 by Microsoft Research (文件大小:98 MB,預測時間較快,精準度高)InceptionV3 by Google Brain team (文件大小:91.6 MB,預測時間慢,精度更高)DenseNet121 by Facebook AI Research (文件大小:31.6 MB,預測時間較慢,精度最高)模型下載地址可參考 Github 地址:https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0

或者參考 ImageAI 官方文檔:https://imageai-cn.readthedocs.io/zh_CN/latest/ImageAI_Image_Prediction.html

項目 Serverless 化

將項目按照函數計算的需求,編寫好入口方法,以及做好項目初始化,同時在當前項目下創建文件夾 model,並將模型文件拷貝到該文件夾:

項目整體流程:

實現代碼:

# -*- coding: utf-8 -*-from imageai.Prediction import ImagePredictionimport jsonimport uuidimport base64import random# Responseclass Response: def __init__(self, start_response, response, errorCode=None): self.start = start_response responseBody = { 'Error': {"Code": errorCode, "Message": response}, } if errorCode else { 'Response': response } # 默認增加uuid,便於後期定位 responseBody['ResponseId'] = str(uuid.uuid1()) print("Response: ", json.dumps(responseBody)) self.response = json.dumps(responseBody) def __iter__(self): status = '200' response_headers = [('Content-type', 'application/json; charset=UTF-8')] self.start(status, response_headers) yield self.response.encode("utf-8")# 隨機字符串randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', num))# 模型加載print("Init model")prediction = ImagePrediction()prediction.setModelTypeAsResNet()print("Load model")prediction.setModelPath("/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()print("Load complete")def handler(environ, start_response): try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 requestBody = json.loads(environ['wsgi.input'].read(request_body_size).decode("utf-8")) # 圖片獲取 print("Get pucture") imageName = randomStr(10) imageData = base64.b64decode(requestBody["image"]) imagePath = "/tmp/" + imageName with open(imagePath, 'wb') as f: f.write(imageData) # 內容預測 print("Predicting ... ") result = {} predictions, probabilities = prediction.predictImage(imagePath, result_count=5) print(zip(predictions, probabilities)) for eachPrediction, eachProbability in zip(predictions, probabilities): result[str(eachPrediction)] = str(eachProbability) return Response(start_response, result)所需要的依賴:

tensorflow==1.13.1numpy==1.19.4scipy==1.5.4opencv-python==4.4.0.46pillow==8.0.1matplotlib==3.3.3h5py==3.1.0keras==2.4.3imageai==2.1.5編寫部署所需要的配置文件:

ServerlessBookImageAIDemo: Component: fc Provider: alibaba Access: release Properties: Region: cn-beijing Service: Name: ServerlessBook Description: Serverless圖書案例 Log: Auto Nas: Auto Function: Name: serverless_imageAI Description: 圖片目標檢測 CodeUri: Src: ./src Excludes: - src/.fun - src/model Handler: index.handler Environment: - Key: PYTHONUSERBASE Value: /mnt/auto/.fun/python MemorySize: 3072 Runtime: python3 Timeout: 60 Triggers: - Name: ImageAI Type: HTTP Parameters: AuthType: ANONYMOUS Methods: - GET - POST - PUT Domains: - Domain: Auto在代碼與配置中,可以看到有目錄:/mnt/auto/ 的存在,該部分實際上是 nas 掛載之後的地址,只需提前寫入到代碼中即可,下一個環節會進行 nas 的創建以及掛載點配置的具體操作。

項目部署與測試

在完成上述步驟之後,可以通過:

s deploy進行項目部署,部署完成可以看到結果:

完成部署之後,可以通過:

s install docker進行依賴的安裝:

依賴安裝完成可以看到在目錄下生成了 .fun 的目錄,該目錄就是通過 docker 打包出來的依賴文件,這些依賴正是我們在 requirements.txt 文件中聲明的依賴內容。

完成之後,我們通過:

s nas sync ./src/.fun將依賴目錄打包上傳到 nas,成功之後再將 model 目錄打包上傳:

s nas sync ./src/model完成之後可以通過:

s nas ls --all查看目錄詳情:

完成之後,我們可以編寫腳本進行測試,同樣適用剛才的測試圖片,通過代碼:

import jsonimport urllib.requestimport base64import timewith open("picture.jpg", 'rb') as f: data = base64.b64encode(f.read()).decode()url = 'http://35685264-1295939377467795.test.functioncompute.com/'timeStart = time.time()print(urllib.request.urlopen(urllib.request.Request( url=url, data=json.dumps({'image': data}).encode("utf-8"))).read().decode("utf-8"))print("Time: ", time.time() - timeStart)可以看到結果:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "1d74ae7e-298a-11eb-8374-024215000701"}Time: 29.16020894050598可以看到,函數計算順利地返回了預期結果,但是整體耗時卻超乎想像,有近 30s,此時我們再次執行一下測試腳本:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "4b8be48a-298a-11eb-ba97-024215000501"}Time: 1.1511380672454834可以看到,再次執行的時間僅有 1.15 秒,比上次整整提升了 28 秒之多。

項目優化

在上一輪的測試中可以看到,項目首次啟動和二次啟動的耗時差距,其實這個時間差,主要是函數在加載模型的時候浪費了極長的時間。

即使在本地,我們也可以簡單測試:

# -*- coding: utf-8 -*-import timetimeStart = time.time()# 模型加載from imageai.Prediction import ImagePredictionprediction = ImagePrediction()prediction.setModelTypeAsResNet()prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()print("Load Time: ", time.time() - timeStart)timeStart = time.time()predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5)for eachPrediction, eachProbability in zip(predictions, probabilities): print(str(eachPrediction) + " : " + str(eachProbability))print("Predict Time: ", time.time() - timeStart)執行結果:

Load Time: 5.549695014953613laptop : 71.43893241882324notebook : 16.265612840652466modem : 4.899394512176514hard_disc : 4.007557779550552mouse : 1.2981942854821682Predict Time: 0.8137111663818359可以看到,在加載 imageAI 模塊以及加載模型文件的過程中,一共耗時 5.5 秒,在預測部分僅有不到 1 秒鐘的時間。而在函數計算中,機器性能本身就沒有我本地的性能高,此時為了避免每次裝載模型導致的響應時間過長,在部署的代碼中,可以看到模型裝載過程實際上是被放在了入口方法之外。這樣做的一個好處是,項目每次執行的時候,不一定會有冷啟動,也就是說在某些復用的前提下是可以復用一些對象的,即無需每次都重新加載模型、導入依賴等。

所以在實際項目中,為了避免頻繁請求,實例重複裝載、創建某些資源,我們可以將部分資源放在初始化的時候進行。這樣可以大幅度提高項目的整體性能,同時配合廠商所提供的預留能力,可以基本上杜絕函數冷啟動帶來的負面影響。

總結

近年來,人工智慧與雲計算的發展突飛猛進,在 Serverless 架構中,如何運行傳統的人工智慧項目已經逐漸成為很多人所需要了解的事情。本文主要介紹了通過一個已有的依賴庫(ImageAI)實現一個圖像分類和預測的接口。藉助這個例子,其實有幾個事情是可以被明確的:

Serverless 架構可以運行人工智慧相關項目;Serverless 可以很好地兼容 Tensorflow 等機器學習/深度學習的工具;雖然說函數計算本身有空間限制,但是實際上增加了硬碟掛載能力之後,函數計算本身的能力將會得到大幅度的拓展。當然,本文也算是拋磚引玉,希望讀者在本文之後,可以發揮自己的想像,將更多的 AI 項目與 Serverless 架構進行進一步結合。

作者:江昱

本文為阿里雲原創內容,未經允許不得轉載

相關焦點

  • 使用Jenkins、Docker 構建部署 Serverless 應用
    serverless 命令行是使用 nodejs 開發的,所以會需要 nodejs 環境。 此外,計劃部署的應用是用 python 開發的,也會需要到 python 環境。
  • 輕鬆學Pytorch-使用ResNet50實現圖像分類
    Hello大家好,這篇文章給大家詳細介紹一下pytorch中最重要的組件torchvision,它包含了常見的數據集、模型架構與預訓練模型權重文件、常見圖像變換、計算機視覺任務訓練。可以是說是pytorch中非常有用的模型遷移學習神器。本文將會介紹如何使用torchvison的預訓練模型ResNet50實現圖像分類。
  • TPU加AutoML:50美元快速訓練高效的ImageNet圖像分類網絡
    昨日,Jeff Dean 在推特上表示他們在 ImageNet 圖像分類上發布了新的 DAWNBench 結果,新型 AmoebaNet-D 網絡在 TPU 上實現了最低的訓練時間和最少的訓練成本。在這一個基準測試上,基於進化策略的 DAWNBench 要比殘差網絡效果更好,且訓練成本降低了一倍。
  • Serverless Framework 2.18.0 發布 - OSCHINA - 中文開源技術交流...
    Serverless 架構開發框架 Serverless Framework 發布了 2.18.0 版本,該框架使用 AWS Lambda、Azure Functions、Google CloudFunctions
  • 使用一行Python代碼從圖像讀取文本
    雖然圖像分類和涉及到一定程度計算機視覺的任務可能需要大量的代碼和紮實的理解,但是從格式良好的圖像中讀取文本在Python中卻是簡單的,並且可以應用於許多現實生活中的問題。在今天的帖子中,我想證明這一點。雖然會安裝一些庫,但不會花很多時間。
  • python|圖像識別
    時下我們不得不承認,科技的發展對現代生活有著決定性的影響。令人喜憂參半的是,科技變化之快,讓我們幾乎無法跟上其腳步,更不用說預測未來了。影響力之大和最吸引人的技術就是圖像識別,圖像識別技術是人工智慧的一個重要領域,它是指利用計算機對圖像進行處理、分析和理解,以識別各種不同模式的目標和對象的技術。
  • 程式設計師的樂趣,生成自定義二維碼,5行Python代碼就搞定
    Python 提供了一個可以輕鬆實現這樣的功能的 qrcode 包,首先就從下載 Python 包開始:pip install pillowpip install qrcode然後創建一個存儲之前文章頁面連結(https://towardsdatascience.com/face-detection-in-10-lines-for-beginners
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    3遊戲循環和鍵盤事件 4精靈和精靈組 5框架搭建 6背景圖像 7敵人飛機 8英雄飛機 9發射子彈以及碰撞檢測 4部分視頻課程 1網絡編程 2多任務 3web伺服器v3.1 4python高級語法v3.1 5mysql資料庫
  • 一文總結數據科學家常用的Python庫(下)
    /* LIME */LIME是一種算法(和庫),可以解釋任何分類器或回歸量的預測。LIME如何做到這一點?通過一個可解釋的模型來近似它。靈感來自「為什麼我應該相信你?」:解釋任何分類器的預測「,這個模型解釋器可用於生成任何分類算法的解釋器。
  • 常用的十大 python 圖像處理工具
    作者 | Parul Pandey翻譯 | 安其羅喬爾、JimmyHua 編輯 | 王立魚原文連結:https://towardsdatascience.com/image-manipulation-tools-for-python-6eb0908ed61f
  • opencv-python獲取圖像:面向對象與面向過程
    獲取圖像的方式有:1,讀取本地圖片,2,調用筆記本自帶攝像頭或usb攝像頭,3,調用網絡攝像頭。讀取圖片學過數字圖像處理的小夥伴應該很熟悉,在數字圖像處理課上,這是一張標準的測試圖片。Lena圖像在科研領域流行的原因:1.該圖適度的混合了細節、平滑區域、陰影和紋理,從而能很好的測試各種圖像處理算法。2.Lenna是個美女,對於圖像處理界的研究者(大部分都是男性)來說,美女圖可以有效地吸引他們來做研究。
  • AWS發布新一代Amazon Aurora Serverless
    此次AWS繼續這一強勁勢頭,發布了新一代Amazon Aurora Serverless,一個使SQL Server遷移到Amazon Aurora更方便的新功能,以及一個讓更多企業組織更輕鬆的從SQL Server遷移到PostgreSQL的開源項目,。
  • 如何批量處理圖像自動白平衡?(附源碼)
    還好我會python,100行代碼輕鬆搞定》的文章。最近收到網友評論:「有無批量處理圖像自動白平衡的例子?「可達鴨表示:安排!什麼是圖像白平衡?肯定有人會問什麼是白平衡,這裡給大家簡單說一下。python魔術方法:可以這麼說,就是函數的聲明和調用所使用的名稱不同,而且調用的方式非常方便。項目設計首先申明,本代碼是根據網上開源的代碼進行修改的。加入了python的設計理念和批量處理的思路。
  • python圖像處理-gif動圖
    python圖像處理-1python圖像處理-批量生成純色圖片python圖像處理-添加文字python圖像處理-貼圖
  • 用Python畫朵玫瑰,只要五分鐘
    最近一個項目在用python,想著這次不用java了,用python給媽媽個禮物吧。Turtle庫是Python語言中一個非常強大的繪製圖像的函數庫,她提供了很多強大的方法,可以方便快速的繪圖,今天我們就來試一下,畫朵玫瑰送給媽媽。
  • 數據工程師需要掌握的 18 個 Python 庫
    利用函數的調用,MATLAB中可以輕鬆的利用一行命令來繪製,然後再用一系列的函數調整結果。它有一套完全仿照MATLAB的函數形式的繪圖接口,在matplotlib.pyplot模塊中。這套函數接口方便MATLAB用戶過度到matplotlib。
  • opencv-python圖像預處理-濾波
    為了消除外界環境對圖像採集的幹擾,增強圖像的邊緣及灰度跳變的部分,使圖像變得清晰以及提高圖像處理速度需要對圖像進行預處理操作,主要是對圖像進行濾波和增強操作。使用的方法可以分為空間域處理和頻率域處理兩類。空間域指圖像平面本身,這類圖像處理方法用各種模板直接與圖像進行卷積運算,實現對圖像的處理。
  • 機器學習初學者入門實踐:怎樣輕鬆創造高精度分類網絡
    準備一個帶有分類圖像的數據集2. 定義網絡架構3. 使用準備好的數據集訓練和驗證這個網絡下面我們會做這三個步驟,以體現從頭開始和使用預訓練的網絡之間的差異,同時也展示如何使用 Caffe 和 DIGITS 上最常用的兩個預訓練的網絡 AlexNet、 GoogLeNet。
  • python人工智慧-圖像識別
    PIL:(Python Imaging Library)是Python平臺上的圖像處理標準庫,功能非常強大。pytesseract:圖像識別庫。我這裡使用的是python3.6,PIL不支持python3所以使用如下命令pip install pytesseractpip install pillow如果是python2,則在命令行執行如下命令:pip install pytesseractpip install PIL這時候我們去運行上面的代碼會發現如下錯誤
  • 掌握深度學習,數據不足也能進行圖像分類!
    ——吳恩達圖像分類即根據固定類別對輸入的圖像設置標籤。儘管計算機視覺過於簡單,但是它在實際中仍有廣泛的應用,而圖像分類就是其中的核心問題之一。在本文中,小芯將示範如何在數據不足的情況下應用深度學習。現已創建特製汽車和巴士分類器兩個數據集,每個數據集包含100個圖像。其中,訓練集有70個圖像,驗證集有30個。挑戰1.