LoginSignup
12
12

More than 1 year has passed since last update.

ResNetを、PyTorchを使ってGoogle Colabで動かす。

Last updated at Posted at 2019-04-18

1. はじめに

ResNetを動かす際、ImageNetを使うのが一般的である。しかし、ImageNetは、データサイズが130GB程度と大きい。このため、大規模なGPGPUも必要である。ここでは、Google Colabで、現実的に処理できる小さいデータセットで動かす。
また、Google Colabでは、GPGPUとして、Tesla K80に続く第二世代(?)のTesla T4が提供されている。T4に搭載されているTensorCoreを動かすためAPEXを使ってみた。

2. 環境構築

2.1. データセット

ImageNetのスモールデータセットのひとつであるfast.aiが作成したImageNetteを使う。imagenette-320で300MB程度であった。参考までに、imagenetteだと、1.5GB程度、imagenette-160だと100MB程度のデータサイズである。

!wget https://s3.amazonaws.com/fast-ai-imageclas/imagenette-320.tgz
!tar xzf imagenette-320.tgz

参考までに、以下のURLを見ると、さまざまなデータセットを見ることが出来る。これ以外のパスは、ソースコードを参照のこと

!wget https://s3.amazonaws.com/fast-ai-imageclas/

2.2. プログラム設定

PyTorchのサンプルコードは、以下で取得できる。

!git clone http://github.com/pytorch/examples

3. プログラム実行および調査

3.1. プログラム実行

以下の通りにすると実行できる。そのままでもresnet18とresnet34は動いた。ただし、10エポックしか動かしていない。デフォルト(90エポック)だと、99分かかると思われる。

!python3 examples/imagenet/main.py -a resnet18 -j 2 --epochs 10 imagenette-320/

ここで、-j 2は、DataLoaderのプロセス数 (num_workersに該当する) である。デフォルトは4である。

モデル 1.0.1 1.1.0
ResNet34 719.496 733.023
ResNet18 631.731 605.559

なお、resnet50は、デフォルト設定(256バッチ)ではメモリが足りず実行できない。このため、バッチサイズを128に減らした。そしたら、10エポックは、1335秒で完走した。vgg19でも同様であった。このため、大規模のモデルではバッチサイズの調整が必須である。

!python3 examples/imagenet/main.py -a resnet50 -j 1 --batch-size 128 --epochs 10 imagenette-320/

なお、メモリが不足しているときは、以下のエラーメッセージが出て止まる。なお、PyTorchで獲得しているメモリがalready allocatedである。それ以外は、ソースコードのコメント(参考資料)を参照のこと

RuntimeError: CUDA out of memory. Tried to allocate 392.00 MiB (GPU 0; 14.73 GiB total capacity; 12.87 GiB already allocated; 74.94 MiB free; 331.18 MiB cached)

3.2. プログラム実行(APEX)

Mixed Precision対応のAPEXを使うと、早くなるようなので試してみた。
APEXの設定は、以下の通りである。

!git clone https://github.com/NVIDIA/apex
!cd apex;pip3 install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" .

ImageNet用ResNetの実行は、以下の通りである。O0がFP32であり、O3が一番最適化を行ったものである。詳細は、apex/examples/imagenetを参照のこと

!python apex/examples/imagenet/main_amp.py -a resnet18 --b 128 --workers 4 --opt-level O0 --epochs 10 imagenette-320/
!python apex/examples/imagenet/main_amp.py -a resnet18 --b 128 --workers 4 --opt-level O3 --epochs 10 imagenette-320/

結果は以下の通りであった。単位は、秒である。これから見るに、ResNetで深い場合は、Mixed Precisionの効果が大きい。ただし、浅い場合は効果が小さくなる。

モデル O0 O1 O2 O3
ResNet50 1440.268 754.425 734.879 741.573
ResNet34 726.023 589.396 543.729
ResNet18 543.681 553.569 547.377 510.681

PyTorch 1.1にてcudnn 7.6.0もColabで使えるのでやってみると、464.623秒(ResNet18の場合)であった。このため、cudnn 7.5.xから7.6.0に変えると1割程度性能向上するようである。
参考までに、1.1.0でもやってみたが、あまり変わらなかった。なお、バッチサイズ256で動くようだが速度は変わっていない。参考までに、700秒台で、200img/sec相当、1400秒台で、100img/sec相当である。

モデル O0 O1 O2 O3 O3/b256
ResNet50 1467.376 734.716 728.141
ResNet34
ResNet18

ResNet50での精度については以下の通りであった。ここでは、ImageNetではなくそのサブセットであるImageNetteを使っており、精度の値が良いことに注意を要する。なお、O3の場合200img/secで、O0の場合95img/secであった。

モデル 10 20 30 40 50
O3 Top1 79.2 83.8 87.0 93.0 90.6
O3 Top5 96.6 96.6 99.0 98.6 98.6
O0 Top1 67.8 83.2 83.4 93.4 92.6
O0 Top5 95.6 96.6 98.4 98.2 98.4

3.3. プロファイル取得

CUDAでどんな関数が使われているかは以下のコマンドを実行することで見ることが出来る。

!nvprof --print-gpu-summary --print-api-summary python3 examples/imagenet/main.py -a resnet18 -j 2 --epochs 1 imagenette-320/

出力例としては、PyTorchのインシデント#13412を参照のこと

4. CPUでの演算

同じexamplesのコードでCPU(m5a.xlarge (4コア32GBメモリ))で動かしてみた。1エポックで以下の時間がかかった。設定は、以下の通りである。PyTorch 1.5.1を使った。なお、resnetは、34までしかうごかず、50は、メモリ不足で途中終了した。

sudo apt update
sudo apt install python3-pip
pip3 install torch
pip3 install torchvision
time python3 examples/imagenet/main.py -a resnet34 --e
pochs 1 imagenette-320/
real    78m35.971s
user    148m25.564s
sys     9m6.955s

A. 参考資料

A.1. PyTorch

A.2. データセット

A.3. さらに深い情報

バッチサイズ 混合計算 XLA img/sec
デフォルト 128 × × 365
AMP 128 × 780
AMP/XLA 128 1010
AMP/XLA 256 1205

A.3.1. プロファイラによる測定

nvprofを使って、プロファイルをとることができる。オプションについては、マニュアルを参照願いたい。なお、プロファイラは出力多い。そのままだとブラウザがハングしかねないので一旦ファイルに出力する必要がある。
なお、APIは、libcudart相当のI/Fでの時間を示している。一方GPUは、GPUカーネルコード等のGPUでの実行時間等を示している。

!nvprof --print-gpu-summary python3 examples/imagenet/main.py -a resnet18 -j 2 --epochs 1 imagenette-320/ >& gpusum.log
!head -200 gpusum.log
!nvprof --print-api-summary python3 examples/imagenet/main.py -a resnet18 -j 2 --epochs 1 imagenette-320/ >& gpusum.log
!head -200 apisum.log

A.3.2. モデルの追加

examplesのコードは、torchvisionのコードを使っているので、最新版を使うこと等により新たなモデルを追加することが出来る。入れ替えは以下の手順で出来る。

!pip uninstall torchvision
!git clone http://github.com/pytorch/vision
!cd vision;python setup.py install

なお、モデルのコードはtorchvision/modelsにある

A.3.3. EfficientNet

最近EfficientNetという効率の良いアルゴリズムが出たようである。実行は、簡単で以下のようにすればよい。なお、gastaiのデータを使って、検証しているスクリプトも提供されている。これによるとあまり良い結果が出ていないようである。Training from scratch on Imagewoof with the efficientnet_pytorch repo

!git clone https://github.com/lukemelas/EfficientNet-PyTorch
!pip install efficientnet_pytorch
!cd EfficientNet-PyTorch/examples/imagenet/;python main.py /content/imagenette-320 -e -a 'efficientnet-b3' --pretrained --gpu 0 --batch-size 128
12
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12