看圖片識車型,本身寫個這樣的程序其實一點也不難

專屬圖1.png

看圖片識車型,本身寫個這樣的程序其實一點也不難:python

媳婦把前車剮了,給我打電話。
媳婦:「老公,我把別人車給剮了。」
我:「啥車呀?」
媳婦:「標我不認識,B開頭的。」
我:「比亞迪啊,你本身解決吧。」
媳婦:「不不不,我認識比亞迪。」
我:「寶馬?沒事,我去取點錢。」
媳婦:「也不是寶馬。」
我:「我擦,你個敗家娘們,不會懟了個賓利吧?」
這時,電話那頭傳來一個陌生的男聲:「我那個叫布加迪。」
我:「……」git

不認識車標,辨不清車型,有時候還真挺難的。github

其實在基於深度學習的圖像分類領域,狀況也是這樣。寫一個能認識汽車的程序,這沒啥技術難度。可要想從衆多汽車的照片中找出具體的品牌型號,這就有點棘手了。算法

車輛檢測及型號識別,這種技術就被普遍應用於物業、交通管理等場景。經過在停車場出入口、路口、高速卡口等位置採集圖片數據,對車輛的數量、型號等進行識別,能夠以較高效率對車型、數量信息等進行採集。隨後經過採集的數據就能夠在不一樣場景中輔助業務開展,如商場停車位的規劃、路況規劃或者公安系統追蹤肇事車輛等。docker

本文所涉及的內容將引入遷移學習的思想。什麼是遷移學習?深度學習中須要大量數據和計算資源,且需花費大量時間來訓練模型,但在實際中難以知足這些需求。而使用遷移學習則能有效下降數據量、計算量和計算時間,並能定製在新場景的業務需求,可謂一大利器。apache

遷移學習不是一種算法,而是一種機器學習思想,應用到深度學習就是微調(Fine-tune)。經過修改預訓練網絡模型結構(如修改樣本類別輸出個數),選擇性載入預訓練網絡模型權重,再用本身的數據集從新訓練模型就是微調的基本步驟。微調可以快速訓練好一個模型,用相對較小的數據量,還能達到不錯的結果。編程

本解決方案使用 Amazon SageMaker,它能夠幫助開發人員和數據科學家構建、訓練和部署 ML 模型。Amazon SageMaker 是一項徹底託管的服務,涵蓋了 ML 的整個工做流,能夠標記和準備數據、選擇算法、訓練模型、調整和優化模型以便部署、預測和執行操做。同時,本方案基於MXNet,Apache MXNet(孵化)是一個深度學習框架,旨在提升效率和靈活性。它可供咱們混合符號和命令式編程,以最大限度地提升效率和生產力。json

下文會重點介紹在 Amazon SageMaker 中如何基於 MXNet,使用本身的數據來微調一個預訓練的圖像分類模型而且達到較高的準確率來構建一個車型號分類器。bash

解決方案概覽

在此示例中,咱們將使用 Amazon SageMaker 執行如下操做:網絡

  1. 環境準備
  2. 使用 Jupyter Notebook 下載數據集並將其進行數據預處理
  3. 使用預訓練好的模型鏡像進行模型微調
  4. 將模型進行託管部署
  5. 調用已部署的模型接口進行在線推理

1.環境準備

首先,咱們須要建立一些使用 AWS 服務所需的受權和環境。包含三部分:

  1. 模型訓練所需的權限,這個會自動從建立筆記本的 Role 中自動獲取
  2. 存儲訓練數據和模型的 S3 存儲桶
  3. Amazon Sagemaker 中預訓練好的圖像分類模型 Docker 鏡像
%%time
import boto3
import re
from sagemaker import get_execution_role
from sagemaker.amazon.amazon_estimator import get_image_uri
 
role = get_execution_role()
 
bucket='app-cars-classfication' # customize to your bucket
 
training_image = get_image_uri(boto3.Session().region_name, 'image-classification')

2.數據預處理

本文使用了斯坦福大學提供的開源數據集 Cars dataset,該數據集包含了196種不一樣汽車品牌車型的16185張圖片。其中咱們將使用8144張做爲訓練集,8041張做爲測試集,每一個車型號在訓練和測試集中分佈均衡。您能夠訪問該數據集主頁查看完整的數聽說明和進行下載,示例圖片以下:

image-recognition-of-car-models-based-on-amazon-sagemaker1.png

爲提升 IO 效率,不會直接讀取圖片文件,而是先將圖片列表和標籤轉換爲 RecordIO 格式的二進制文件,訓練時就能夠順序讀取數據,大大提升了IO速率。MXNet 社區提供了一個很好的圖片轉換工具 im2rec.py,可進行快速圖像轉換。主要利用的是 MXNet im2rec.py 工具生成 List 和 Record 文件,並按照 Validation 的數據和 Training 數據的比例進行自動的數據拆分。具體命令以下圖,首先生成標籤爲汽車種類個數的 List 文件以後,按照多個併發線程的方式進行 Record 格式轉換,並存在定義的目錄內。具體轉換的 Shell 腳本內容以下。須要注意的是,這裏的 data_path 爲此 Shell 腳本的入參,須要本身指定爲本身存放數據集的本地路徑:

#!/usr/bin/env bash
## The process file for image classification data transform to the recordio format
# current directory contains only one zip file
 
git clone https://github.com/apache/incubator-mxnet.git
source activate amazonei_mxnet_p36
unzip *.zip
mkdir train
mkdir validation
 
data_path=$1
echo "data_path: ${data_path}"
train_path=train/
echo "train_path: ${train_path}"
val_path=validation/
echo "val_path: ${val_path}"
 
python incubator-mxnet/tools/im2rec.py \
  --list \
  --train-ratio 0.8 \
  --recursive \
  $data_path/data $data_path
 
python incubator-mxnet/tools/im2rec.py \
    --resize 224 \
    --center-crop \
    --num-thread 4 \
    $data_path/data $data_path
 
mv ${data_path}data_train.rec $train_path
mv ${data_path}data_val.rec $val_path

轉換結束後,能夠看到在 Train 和 Validation 目錄中分別生成了兩個文件:data_train.rec 和 data_val.rec,咱們須要將其上傳至已建立的 S3 存儲桶內供後續模型訓練使用:

import os 
import boto3
 
     
def upload_to_s3(file):
    s3 = boto3.resource('s3')
    data = open(file, "rb")
    key = file
    s3.Bucket(bucket).put_object(Key=key, Body=data)
 
 
# caltech-256
s3_train_key = "car_data_sample/train"
s3_validation_key = "car_data_sample/validation"
s3_train = 's3://{}/{}/'.format(bucket, s3_train_key)
s3_validation = 's3://{}/{}/'.format(bucket, s3_validation_key)
 
upload_to_s3('car_data_sample/train/data_train.rec')
 
upload_to_s3('car_data_sample/validation/data_val.rec')

3.使用遷移學習進行模型訓練

數據集準備結束以後,就能夠開始模型的訓練了。但在開始訓練任務以前,須要配置模型訓練的一系列超參數,具體的超參數含義以下:

  • Num_layers:神經網絡的層數,本例中能夠選擇1八、3四、50、10一、152和200。不少經典網絡模型的名字中包含的數字就表明了 Layer 個數,如 vgg16中的16就表明了權重層的個數。
  • Image_shape:輸入圖像的通道數,像素的長寬。
  • Num_training_samples:訓練樣本的個數。
  • Num_classes:訓練樣本圖像分類的類目數,本例中爲了簡介,只選取了三個 Class 作範例。
  • mini_batch_size:每輪訓練的輸入一批數據包含的數目。
  • epochs:訓練輪次。
  • learning_rate:訓練學習率。
  • use_pretrained_model:是否使用預訓練模型進行遷移學習,如爲1,則初始化中使用已經基於一個較大的開源數據集,如 imagenet,學習的網絡結構。
# The algorithm supports multiple network depth (number of layers). They are 18, 34, 50, 101, 152 and 200
# For this training, we will use 18 layers
num_layers = 18
# we need to specify the input image shape for the training data
image_shape = "3,224,224"
# we also need to specify the number of training samples in the training set
# for caltech it is 15420
num_training_samples = 96
# specify the number of output classes
num_classes = 3
# batch size for training
mini_batch_size =  30
# number of epochs
epochs = 100
# learning rate
learning_rate = 0.01
top_k=2
# Since we are using transfer learning, we set use_pretrained_model to 1 so that weights can be 
# initialized with pre-trained weights
use_pretrained_model = 1

以後,咱們進行必要的 SageMaker API 建立,構建對應的訓練任務。其中有指定訓練的輸入與輸出,訓練的計算實例配置,這裏咱們使用的是 ml.p2.xlarge GPU 實例。須要注意的是,這裏 Sagemaker notebook 進行本地的數據處理、模型訓練、模型推理是不一樣環境,能夠根據不一樣的計算任務的需求進行不一樣的機型選擇。

%%time
import time
import boto3
from time import gmtime, strftime
 
 
s3 = boto3.client('s3')
# create unique job name 
job_name_prefix = 'cars-imageclassification'
timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
job_name = job_name_prefix + timestamp
training_params = \
{
    # specify the training docker image
    "AlgorithmSpecification": {
        "TrainingImage": training_image,
        "TrainingInputMode": "File"
    },
    "RoleArn": role,
    "OutputDataConfig": {
        "S3OutputPath": 's3://{}/{}/output'.format(bucket, job_name_prefix)
    },
    "ResourceConfig": {
        "InstanceCount": 1,
        "InstanceType": "ml.p2.xlarge",
        "VolumeSizeInGB": 50
    },
    "TrainingJobName": job_name,
    "HyperParameters": {
        "image_shape": image_shape,
        "num_layers": str(num_layers),
        "num_training_samples": str(num_training_samples),
        "num_classes": str(num_classes),
        "mini_batch_size": str(mini_batch_size),
        "epochs": str(epochs),
        "learning_rate": str(learning_rate),
        "use_pretrained_model": str(use_pretrained_model)
    },
    "StoppingCondition": {
        "MaxRuntimeInSeconds": 360000
    },
#Training data should be inside a subdirectory called "train"
#Validation data should be inside a subdirectory called "validation"
#The algorithm currently only supports fullyreplicated model (where data is copied onto each machine)
    "InputDataConfig": [
        {
            "ChannelName": "train",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3_train,
                    "S3DataDistributionType": "FullyReplicated"
                }
            },
            "ContentType": "application/x-recordio",
            "CompressionType": "None"
        },
        {
            "ChannelName": "validation",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "S3Prefix",
                    "S3Uri": s3_validatio

到這裏,咱們就能夠直接調用 SageMaker API 來啓動訓練任務。須要注意的是,咱們只是用一個簡單的 API:sagemaker.create_training_job,而且根據第三步中的參數配置,就直接能夠進行輕鬆的訓練了。中間沒有任何的環境構建,部署,甚至是神經網絡模型設計的過程。

# create the Amazon SageMaker training job
sagemaker = boto3.client(service_name='sagemaker')
sagemaker.create_training_job(**training_params)
 
# confirm that the training job has started
status = sagemaker.describe_training_job(TrainingJobName=job_name)['TrainingJobStatus']
print('Training job current status: {}'.format(status))
 
try:
    # wait for the job to finish and report the ending status
    sagemaker.get_waiter('training_job_completed_or_stopped').wait(TrainingJobName=job_name)
    training_info = sagemaker.describe_training_job(TrainingJobName=job_name)
    status = training_info['TrainingJobStatus']
    print("Training job ended with status: " + status)
except:
    print('Training failed to start')
     # if exception is raised, that means it has failed
    message = sagemaker.describe_training_job(TrainingJobName=job_name)['FailureReason']
    print('Training failed with the following error: {}'.format(message))

完成上述步驟後,就能夠在 Sagemaker Console 中看到本身的訓練任務。當 Status 爲 Completed 時,表明訓練完成。整個訓練過程大概持續15分鐘,這個時間會根據選擇的機型和設置的 epochs 個數等而有所差別。

image-recognition-of-car-models-based-on-amazon-sagemaker2.png

同時,在訓練過程當中,咱們還能夠經過監控 Cloudwatch log 來查看訓練過程當中的 loss 變化:

image-recognition-of-car-models-based-on-amazon-sagemaker3.png

4.模型部署

訓練結束後,咱們在以前配置的 S3 存儲桶就得到了最新的模型文件。接下來將其進行線上部署,這樣就能夠經過接受來自客戶端的 Restful API 請求進行預測。

首先建立模型:

%%time
import boto3
from time import gmtime, strftime
 
sage = boto3.Session().client(service_name='sagemaker') 
 
model_name="cars-imageclassification-" + time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
print(model_name)
info = sage.describe_training_job(TrainingJobName=job_name)
model_data = info['ModelArtifacts']['S3ModelArtifacts']
print(model_data)
 
hosting_image = get_image_uri(boto3.Session().region_name, 'image-classification')
 
primary_container = {
    'Image': hosting_image,
    'ModelDataUrl': model_data,
}
 
create_model_response = sage.create_model(
    ModelName = model_name,
    ExecutionRoleArn = role,
    PrimaryContainer = primary_container)
 
print(create_model_response['ModelArn'])

而後配置接口,能夠看到,這裏推理使用的實例是 ml.m4.xlarge:

from time import gmtime, strftime
 
timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
endpoint_config_name = job_name_prefix + '-epc-' + timestamp
endpoint_config_response = sage.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType':'ml.m4.xlarge',
        'InitialInstanceCount':1,
        'ModelName':model_name,
        'VariantName':'AllTraffic'}])
 
print('Endpoint configuration name: {}'.format(endpoint_config_name))
print('Endpoint configuration arn:  {}'.format(endpoint_config_response['EndpointConfigArn']))

第三步使用上面配置的模型和端口配置建立終結點,這一步一般須要比較長的時間,通常終結點的建立須要10分鐘左右:

%%time
import time
 
timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
endpoint_name = job_name_prefix + '-ep-' + timestamp
print('Endpoint name: {}'.format(endpoint_name))
 
endpoint_params = {
    'EndpointName': endpoint_name,
    'EndpointConfigName': endpoint_config_name,
}
endpoint_response = sagemaker.create_endpoint(**endpoint_params)
print('EndpointArn = {}'.format(endpoint_response['EndpointArn']))

在等待端口建立的時候,能夠經過查看端口建立狀態來得到建立的狀態:

# get the status of the endpoint
response = sagemaker.describe_endpoint(EndpointName=endpoint_name)
status = response['EndpointStatus']
print('EndpointStatus = {}'.format(status))
# wait until the status has changed
sagemaker.get_waiter('endpoint_in_service').wait(EndpointName=endpoint_name)
# print the status of the endpoint
endpoint_response = sagemaker.describe_endpoint(EndpointName=endpoint_name)
status = endpoint_response['EndpointStatus']
print('Endpoint creation ended with EndpointStatus = {}'.format(status))

若是上述代碼運行結果爲 Endpoint creation ended with EndpointStatus = InService,那麼表明已經成功建立了一個終結點。咱們也能夠經過 Sagemaker Console 查看到已經建立好的終結點。

5.推理及應用

如今咱們使用一個隨意挑選的汽車圖片進行型號分類。本例挑選了一張 Acura 的 Acura RL Sedan 2012 車型,圖片以下:

image-recognition-of-car-models-based-on-amazon-sagemaker4.png

咱們能夠直接調用建立的終結點進行推理,能夠看到結果與機率,並能看到準確判斷出了相對應的分類。這裏的機率並非很是高,但鑑於咱們做爲範例只訓練了很少的 epoch,已是個很不錯的結果了。若是想要獲得更高的準確率,請使用完整數據集進行更多輪次的訓練。

import json
import numpy as np
with open(file_name, 'rb') as f:
    payload = f.read()
    payload = bytearray(payload)
response = runtime.invoke_endpoint(EndpointName=endpoint_name, 
                                   ContentType='application/x-image', 
                                   Body=payload)
result = response['Body'].read()
# result will be in json format and convert it to ndarray
result = json.loads(result)
# the result will output the probabilities for all classes
# find the class with maximum probability and print the class index
index = np.argmax(result)
object_categories = ['Acura Integra Type R 2001', 'Acura RL Sedan 2012', 'Acura TL Sedan 2012']
print("Result: label - " + object_categories[index] + ", probability - " + str(result[index]))

image-recognition-of-car-models-based-on-amazon-sagemaker5.png

號外,號外,號外!!!

今晚八點,#AWS Live Coding# 將演示如何利用 AWS Serverless 和 Machine Learning 服務來快速構建語音翻譯器:你只須要說出中文,AWS(AWS Lambda)就會幫你把語音轉換成文本(Amazon Transcribe),翻譯成選擇的語言(好比英文)(Amazon Translate),而後轉換成對應的語音(Amazon Polly)。
你就能夠造出神奇的寶貝魚,科技讓溝通無障礙~

直播通道:https://live.bilibili.com/219...

海報.jpg

底圖2.png

相關文章
相關標籤/搜索