ResNet網絡的訓練和預測


ResNet網絡的訓練和預測

簡介 Introduction

圖像分類與CNN

圖像分類 是指將圖像信息中所反映的不同特征,把不同類別的目標區分開來的圖像處理方法,是計算機視覺中其他任務,比如目標檢測、語義分割、人臉識別等高層視覺任務的基礎。

ImageNet 大規模視覺識別挑戰賽(ILSVRC),常稱為 ImageNet 競賽,包括圖像分類、物體定位,以及物體檢測等任務,推動計算機視覺領域發展最重要的比賽之一。

在2012年的 ImageNet 競賽中,深度卷積網絡 AlexNet 橫空出世。以超出第二名10%以上的top-5准確率,勇奪 ImageNet2012 比賽的冠軍。從此,以 CNN(卷積神經網絡) 為代表的深度學習方法開始在計算機視覺領域的應用開始大放異彩,更多的更深的CNN網絡被提出,比如 ImageNet2014 比賽的冠軍 VGGNet, ImageNet2015 比賽的冠軍 ResNet。

ResNet

ResNet 是2015年ImageNet競賽的冠軍。目前,ResNet 相對對於傳統的機器學習分類算法而言,效果已經相當的出色,之后大量的檢測,分割,識別等任務也都在 ResNet 基礎上完成。

OneFlow-Benchmark 倉庫中,提供 ResNet50 v1.5 的 OneFlow 實現。在 ImageNet-2012 數據集上訓練90輪后,驗證集上的准確率能夠達到:77.318%(top1),93.622%(top5)。

更詳細的網絡參數對齊工作,見 OneFlow-Benchmark的cnns 部分

 

關於 ResNet50 v1.5 的說明:

ResNet50 v1.5 是原始 ResNet50 v1 的一個改進版本,相對於原始的模型,精度稍有提升 (~0.5% top1) 。

本文就以上面的 ResNet50 為例,一步步展現如何使用 OneFlow 進行 ResNet50 網絡的訓練和預測。

主要內容包括:

  • 准備工作
  • 項目安裝和准備工作
  • 快速開始
  • 預測/推理
  • 訓練和驗證
  • 評估
  • 更詳細的說明
  • 分布式訓練
  • 混合精度訓練與預測
  • 進階
  • 參數對齊
  • 數據集制作(ImageNet2012)
  • OneFlow 模型轉 ONNX 模型

准備工作 Requirements

別擔心,使用 OneFlow 非常容易,只要准備好下面三步,即可開始 OneFlow 的圖像識別之旅。

git clone git@github.com:Oneflow-Inc/OneFlow-Benchmark.git

cd OneFlow-Benchmark/Classification/cnns

  • 准備數據集(可選)
  • 直接使用 synthetic 虛擬合成數據集
  • 下載制作的 Imagenet(2012) 迷你數據集 解壓放入data目錄
  • 或者:制作完整 OFRecord 格式的 ImageNet 數據集(見下文進階部分)

提供了通用腳本:train.sh 和 inference.sh,它們適用於此倉庫下所有cnn網絡模型的訓練、驗證、推理。可以通過設置參數使用不同的模型、數據集來訓練/推理。

關於模型的說明:

默認情況下,使用resnet50,也可以通過改動腳本中的--model參數指定其他模型,如:--model="resnet50",--model="vgg" 等。

關於數據集的說明:

1)為了使讀者快速上手,提供了 synthetic 虛擬合成數據,“合成數據”是指不通過磁盤加載數據,而是直接在內存中生成一些隨機數據,作為神經網絡的數據輸入源。

2)同時,提供了一個小的迷你示例數據集。直接下載解壓至 cnn 項目的 data 目錄,即可快速開始訓練。讀者可以在熟悉了流程后,參考數據集制作部分,制作完整的 Imagenet2012 數據集。

3)使用 OFRcord 格式的數據集可以提高數據加載效率(但這非必須,參考數據輸入,OneFlow 支持直接加載 numpy 數據)。

快速開始 Quick Start

開始 OneFlow 的圖像識別之旅吧!

首先,切換到目錄:

cd OneFlow-Benchmark/Classification/cnns

預訓練模型

resnet50

resnet50_v1.5_model (validation accuracy: 77.318% top1,93.622% top5 )

預測/推理

下載好預訓練模型后,解壓后放入當前目錄,然后執行:

sh inference.sh

此腳本將調用模型對這張金魚圖片進行分類:

 

 

 若輸出下面的內容,則表示預測成功:

data/fish.jpg

0.87059885 goldfish, Carassius auratus

可見,模型判斷這張圖片有87.05%的概率是金魚 goldfish。

訓練和驗證(Train & Validation)

  • 訓練同樣很簡單,只需執行:

sh train.sh

即可開始模型的訓練,將看到如下輸出:

Loading synthetic data.

Loading synthetic data.

Saving model to ./output/snapshots/model_save-20200723124215/snapshot_initial_model.

Init model on demand.

train: epoch 0, iter 10, loss: 7.197278, top_1: 0.000000, top_k: 0.000000, samples/s: 61.569

train: epoch 0, iter 20, loss: 6.177684, top_1: 0.000000, top_k: 0.000000, samples/s: 122.555

Saving model to ./output/snapshots/model_save-20200723124215/snapshot_epoch_0.

train: epoch 0, iter 30, loss: 3.988656, top_1: 0.525000, top_k: 0.812500, samples/s: 120.337

train: epoch 1, iter 10, loss: 1.185733, top_1: 1.000000, top_k: 1.000000, samples/s: 80.705

train: epoch 1, iter 20, loss: 1.042017, top_1: 1.000000, top_k: 1.000000, samples/s: 118.478

Saving model to ./output/snapshots/model_save-20200723124215/snapshot_epoch_1.

...

為了方便運行演示,默認使用synthetic虛擬合成數據集,使可以快速看到模型運行的效果

同樣,你也可以使用迷你示例數據集,下載解壓后放入 cnn 項目的 data 目錄即可,然后修改訓練腳本如下:

rm -rf core.*

rm -rf ./output/snapshots/*

 

DATA_ROOT=data/imagenet/ofrecord

 

python3 of_cnn_train_val.py \

    --train_data_dir=$DATA_ROOT/train \

    --num_examples=50 \

    --train_data_part_num=1 \

    --val_data_dir=$DATA_ROOT/validation \

    --num_val_examples=50 \

    --val_data_part_num=1 \

    --num_nodes=1 \

    --gpu_num_per_node=1 \

    --model_update="momentum" \

    --learning_rate=0.001 \

    --loss_print_every_n_iter=1 \

    --batch_size_per_device=16 \

    --val_batch_size_per_device=10 \

    --num_epoch=10 \

    --model="resnet50"

運行此腳本,將在僅有50張金魚圖片的迷你 ImageNet 數據集上,訓練出一個分類模型,可以對金魚圖片進行分類。

不要着急,如果需要在完整的 ImageNet2012 數據集上進行訓練,請參考:OneFlow-Benchmark倉庫。

評估(Evaluate)

你可以使用自己訓練好的模型,或者提供的 resnet50_v1.5_model (解壓后放入當前目錄),對resnet50模型的精度進行評估。

只需運行:

sh evaluate.sh

即可獲得訓練好的模型在50000張驗證集上的准確率:

Time stamp: 2020-07-27-09:28:28

Restoring model from resnet_v15_of_best_model_val_top1_77318.

I0727 09:28:28.773988162    8411 ev_epoll_linux.c:82]        Use of signals is disabled. Epoll engine will not be used

Loading data from /dataset/ImageNet/ofrecord/validation

validation: epoch 0, iter 195, top_1: 0.773277, top_k: 0.936058, samples/s: 1578.325

validation: epoch 0, iter 195, top_1: 0.773237, top_k: 0.936078, samples/s: 1692.303

validation: epoch 0, iter 195, top_1: 0.773297, top_k: 0.936018, samples/s: 1686.896

執行 sh evaluate.sh 前,確保准備了 ImageNet(2012) 的驗證集,驗證集制作方法請參考:OneFlow-Benchmark倉庫。

從3輪的評估結果來看,模型在 ImageNet(2012) 上已經達到了77.32+%的 top1 精度。

最后,恭喜你!完成了 Resnet 模型在 ImageNet 上完整的訓練/驗證、推理和評估!

更詳細的說明 Details

分布式訓練

簡單而易用的分布式,是 OneFlow 的主打特色之一。

OneFlow 框架從底層設計上,就原生支持高效的分布式訓練。尤其對於分布式的數據並行,用戶完全不用操心算法從單機單卡擴展到多機多卡時,數據如何划分以及同步的問題。也就是說,使用 OneFlow,用戶以單機單卡的視角寫好的代碼,自動具備多機多卡分布式數據並行的能力。

如何配置並運行分布式訓練?

還是以上面"快速開始"部分演示的代碼為例,在 train.sh 中,只要用 --num_nodes 指定節點(機器)個數,同時用 --node_ips 指定節點的 IP 地址,然后用 --gpu_num_per_node 指定每個節點上使用的卡數,就輕松地完成了分布式的配置。

例如,想要在2機8卡上進行分布式訓練,像下面這樣配置:

# train.sh

python3 of_cnn_train_val.py \

    --num_nodes=2 \

    --node_ips="192.168.1.1, 192.168.1.2"

    --gpu_num_per_node=4 \

    ...

    --model="resnet50"

然后分別在兩台機器上,同時執行:

./train.sh

程序啟動后,通過 watch -n 0.1 nvidia-smi 命令可以看到,兩台機器的 GPU 都開始了工作。一段時間后,會在 --node_ips 設置中的第一台機器的屏幕上,打印輸出。

混合精度訓練與預測

目前,OneFlow 已經原生支持 float16/float32 的混合精度訓練。訓練時,模型參數(權重)使用 float16 進行訓練,同時保留 float32 用作梯度更新和計算過程。由於參數的存儲減半,會帶來訓練速度的提升。

在 OneFlow 中開啟 float16/float32 的混合精度訓練模式,ResNet50 的訓練速度理論上能達到1.7倍的加速。

如何開啟 float16 / float32 混合精度訓練?

只需要在 train.sh 腳本中添加參數 --use_fp16=True 即可。

混合精度模型

為提供了一個在 ImageNet2012 完整訓練了90個 epoch 的混合精度模型,Top_1:77.33%

可以直接下載使用:resnet50_v15_fp16

進階 Advanced

參數對齊

OneFlow 的 ResNet50 實現,為了保證和英偉達的 Mxnet 版實現對齊,從 learning rate 學習率,優化器 Optimizer 的選擇,數據增強的圖像參數設定,到更細的每一層網絡的形態,bias,weight 初始化等都做了細致且幾乎完全一致的對齊工作。具體的參數對齊工作,請參考:OneFlow-Benchmark 倉庫

數據集制作

用於圖像分類數據集簡介

用於圖像分類的公開數據集有CIFAR,ImageNet 等等,這些數據集中,以 jpeg 的格式提供原始的圖片。

  • CIFAR 是由Hinton 的學生 Alex Krizhevsky 和 Ilya Sutskever 整理的一個用於識別普適物體的小型數據集。包括CIFAR-10和CIFAR-100。
  • ImageNet ImageNet 數據集,一般是指2010-2017年間大規模視覺識別競賽 (ILSVRC) 的所使用的數據集的統稱。ImageNet 數據從2010年來稍有變化,常用 ImageNet-2012 數據集包含1000個類別,其中訓練集包含1,281,167張圖片,每個類別數據732至1300張不等,驗證集包含50,000張圖片,平均每個類別50張圖片。

完整的 ImageNet(2012)制作過程,請參考 tools 目錄下的README說明

OneFlow 模型轉 ONNX 模型

簡介

ONNX (Open Neural Network Exchange) 是一種較為廣泛使用的神經網絡中間格式,通過 ONNX 格式,OneFlow 模型可以被許多部署框架(如 OpenVINO、ONNX Runtime 和移動端的 ncnn、tnn、TEngine 等)所使用。這一節介紹如何將訓練好的 ResNet50 v1.5 模型轉換為 ONNX 模型並驗證正確性。

快速上手

提供了完整代碼:resnet_to_onnx.py 幫你輕松完成模型的轉換和測試的工作

步驟一: 下載預訓練模型:resnet50_v1.5_model ,解壓后放入當前目錄

步驟二: 執行:python3 resnet_to_onnx.py

此代碼將完成 OneFlow 模型 -> ONNX 模型的轉化,然后使用 ONNX Runtime 加載轉換后的模型對單張圖片進行測試。測試圖片如下:

 

 

 ​ 圖片來源:https://en.wikipedia.org/wiki/Tiger

輸出:

Convert to onnx success! >>  onnx/model/resnet_v15_of_best_model_val_top1_77318.onnx

data/tiger.jpg

Are the results equal? Yes

Class: tiger, Panthera tigris; score: 0.8112028241157532

如何生成 ONNX 模型

上面的示例代碼,介紹了如何轉換 OneFlow 的 ResNet 模型至 ONNX 模型,並給出了一個利用 onnx runtime 進行預測的例子,同樣,可以利用下面的步驟來完成自己訓練的 ResNet 或其他模型的轉換。

步驟一:將模型權重保存到本地

首先指定待轉換的 OneFlow 模型路徑,然后指定轉換后的 ONNX 模型存放路徑,例如示例中:

#set up your model path

flow_weights_path = 'resnet_v15_of_best_model_val_top1_77318'

onnx_model_dir = 'onnx/model'

步驟二:新建一個用於推理的 job function

然后新建一個用於推理的 job function,它只包含網絡結構本身,不包含讀取 OFRecord 的算子,並且直接接受 numpy 數組形式的輸入。可參考 resnet\_to\_onnx.py 中的 InferenceNet。

步驟三:調用 flow.onnx.export方法

接下來代碼中會調用 oneflow_to_onnx() 方法,此方法包含了核心的模型轉換方法: flow.onnx.export()

flow.onnx.export 將從 OneFlow 網絡得到 ONNX 模型,它的第一個參數是上文所說的專用於推理的 job function,第二個參數是 OneFlow 模型路徑,第三個參數是(轉換后)ONNX 模型的存放路徑

onnx_model = oneflow_to_onnx(InferenceNet, flow_weights_path, onnx_model_dir, external_data=False)

驗證 ONNX 模型的正確性

生成 ONNX 模型之后可以使用 ONNX Runtime 運行 ONNX 模型,驗證 OneFlow 模型和 ONNX 模型能夠在相同的輸入下產生相同的結果。相應的代碼在 resnet_to_onnx.py 的 check_equality。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM