A certain engineer "COMPLEX"

開発メモ その171 ChainerのモデルデータをONNXに変換してみる

Introduction


ChainerはPythonで動きます。
学習はPythonで良くてもシステムに組み込む際にPythonは聊か都合が悪いです。
なので、学習結果であるモデルファイルをPython以外の言語で扱えるように、共通データフォーマットであるONNX (Open Neural Network Exchange)に変換してみます。

How to


シンプルなMNISTのサンプルで生成されるモデルファイルを変換してみます。
まずはChainerの環境を構築。Windows上の仮想環境を想定。

環境構築

Introduction以前、CUDAを含むChainerのインストール手法を書きましたが、もう少しわかりやすく整理しました。ResolutionCUDA_PATHの確認Chainerで利用するCUDAを確認し...

を参考にし、下記のコマンドを実行します。


> python -m pip install --upgrade pip
> python -m pip install cupy==5.3.0
> python -m pip install cupy-cuda92==5.3.0
> python -m pip install chainer==5.3.0
> python -m pip install onnx-chainer

インストール後はCUDAを認識しているかを確認します。


> python -c "import chainer; chainer.print_runtime_info()"
Platform: Windows-10-10.0.17763-SP0
Chainer: 5.3.0
NumPy: 1.16.2
CuPy:
CuPy Version : 5.3.0
CUDA Root : C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2
CUDA Build Version : 9020
CUDA Driver Version : 10000
CUDA Runtime Version : 9020
cuDNN Build Version : 7402
cuDNN Version : 7402
NCCL Build Version : None
NCCL Runtime Version : None
iDeep: Not Available

学習と変換

ソースをクローンし、train_mnist.pyを修正します。


> git clone https://github.com/chainer/chainer
> cd chainer
> git checkout v5.3.0
> cd examples\mnist

修正前はモデルファイルを出力しないためです。
修正は下記2箇所。

箇所1


#!/usr/bin/env python
import argparse

import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training
from chainer.training import extensions

+ import os
+ from chainer import serializers
+ import onnx_chainer
+ import cupy as xp

箇所2


if args.resume:
# Resume from a snapshot
chainer.serializers.load_npz(args.resume, trainer)

# Run the training
trainer.run()

+ model_file = os.path.join(args.out, 'mnist.model')
+ onnx_file = os.path.join(args.out, 'mnist.onnx')
+ serializers.save_npz(model_file, model)
+ chainer.config.train = False
+ # ダミーデータ
+ x = xp.zeros((1, 1, 28, 28), dtype=xp.float32)
+ onnx_chainer.export(model.predictor, x, filename=onnx_file)

if __name__ == '__main__':
main()

下記を実行します。


> python train_mnist.py --gpu 0
GPU: 0
# unit: 1000
# Minibatch-size: 100
# epoch: 20

Downloading from http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz...
Downloading from http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz...
D:\Works\Python\envs\Chainer_5.3.0\lib\site-packages\chainer\training\extensions\plot_report.py:25: UserWarning: matplotlib is not installed on your environment, so nothing will be plotted at this time. Please install matplotlib to plot figures.

$ pip install matplotlib

warnings.warn('matplotlib is not installed on your environment, '
epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time
1 0.189437 0.0972368 0.94235 0.9701 8.70826
2 0.0736203 0.0654 0.977182 0.9789 11.5016
3 0.0483072 0.0657967 0.984433 0.9786 13.9685
4 0.0344889 0.0775722 0.988614 0.9779 16.4064
5 0.0307565 0.073484 0.990132 0.9808 18.8182
6 0.0247791 0.0676734 0.991932 0.981 21.2477
7 0.0187978 0.0756141 0.993648 0.9822 23.7888
8 0.0151227 0.0729054 0.994965 0.9836 26.2349
9 0.0162507 0.09349 0.994649 0.9805 28.6772
10 0.0186082 0.07771 0.994565 0.983 31.1291
11 0.0121478 0.0878187 0.996282 0.9829 33.575
12 0.0139532 0.103692 0.995515 0.9803 36.1334
13 0.0128902 0.0869704 0.996015 0.9812 38.5139
14 0.00887171 0.0960986 0.997182 0.9807 40.966
15 0.00950978 0.0941747 0.997016 0.9835 43.492
16 0.0117687 0.112775 0.996632 0.9805 45.8972
17 0.012322 0.109815 0.996782 0.9803 48.2932
18 0.00880352 0.10031 0.997383 0.9818 50.731
19 0.00929279 0.118552 0.997365 0.979 53.3326
20 0.00607901 0.0849677 0.99825 0.9852 55.8271

学習の結果、result\mnist.modelresult\mnist.onnxが出力されています。

開発メモ その170 M2DetをUbuntu18.04で使ってみる(学習編)

Introduction


前回の続き。
今回は学習を行ってみます。

How to


公式によると下記のコマンドで学習できるとのこと。


python train.py -c=configs/m2det512_vgg.py --ngpu 4 -t True

しかしこのコマンドはTensorBoradを使った学習になります。
つまりTensorFlowが必要になります。
必要ない場合は


python train.py -c=configs/m2det512_vgg.py --ngpu 4

でOK。
--npgu引数は利用するGPUの数。4個をサンプルとして表記しておくあたり、どれだけリソースを使うのか、とビクビクします。

モデルファイル

まず、pretrainedモデルをダウンロードします。
これは前回ダウンロードしたものとは異なります。
公式リンクにも書いておらず、ファイル名から検索をかけた結果、下記のページにリンクが書いてありました。

A PyTorch Implementation of Single Shot MultiBox Detector - amdegroot/ssd.pytorch


wget https://s3.amazonaws.com/amdegroot-models/vgg16_reducedfc.pth
mkdir weights
mv vgg16_reducedfc.pth weights

データセット

データセットをダウンロードします。しかし、これも公式には書いていません。
上述のssd.pytorchでスクリプトが用意されています。


git clone https://github.com/amdegroot/ssd.pytorch

そして、このリポジトリにある下記のスクリプトからデータセットをダウンロードします。

  • COCO
    • ./data/scripts/COCO2014.sh
    • ~/data にダウンロードされる
  • VOC2007
    • ./data/scripts/VOC2007.sh
    • ~/data にダウンロードされる
  • VOC2012
    • ./data/scripts/VOC2012.sh
    • ~/data にダウンロードされる

必要に応じてシンボリックリンクで退避するなど工夫する


ln -s /media/hdd/work/data ~/data

ダウンロード完了後、

  • COCO
    • ~/data/coco/annotations/annotations の中身を ** ~/data/coco/annotations** に移動 その場所に展開
    • ~/data/coco/images/train2014~/data/coco/images/val2014が存在することを確認
    • wget https://github.com/insikk/coco_dataset_trainval35k/blob/master/instances_valminusminival2014.json.zip?raw=true -O instances_valminusminival2014.json.zip
    • =/data/cocoで実行、展開、annotationsへ移動

し、data/coco.pyを下記のように変更します。


def __init__(self, root, image_sets, preproc=None, target_transform=None,
dataset_name='COCO'):
self.root = root
self.data_path = os.path.join(os.path.expanduser("~"),'data')
- self.cache_path = os.path.join(self.data_path, 'coco_cache')
+ self.cache_path = os.path.join(self.data_path, 'coco')
self.image_set = image_sets

そして前述の学習コマンドを実行します。


python train.py -c=configs/m2det512_vgg.py --ngpu 1

がいろいろエラーが。

エラー1

data/coco.py を直していない時のエラー


creating index...
index created!
Traceback (most recent call last):
File "train.py", line 58, in
dataset = get_dataloader(cfg, args.dataset, 'train_sets')
File "/media/hdd/work/local/M2Det/utils/core.py", line 93, in get_dataloader
getattr(cfg.dataset, dataset)[setname], _preproc)
File "/media/hdd/work/local/M2Det/data/coco.py", line 65, in __init__
self.annotations.extend(self._load_coco_annotations(coco_name, indexes,_COCO))
File "/media/hdd/work/local/M2Det/data/coco.py", line 101, in _load_coco_annotations
with open(cache_file, 'wb') as fid:
FileNotFoundError: [Errno 2] No such file or directory: '/home/takuya/data/coco_cache/train2014_gt_roidb.pkl'

エラー2

バッチサイズが大きすぎる。
configs/m2det512_vgg.pyper_batch_size を小さくする


===> Training M2Det on COCO
Traceback (most recent call last):
File "train.py", line 86, in
out = net(images)
File "/media/hdd/Ubuntu18.04/python/M2Det/lib/python3.6/site-packages/torch/nn/modules/module.py", line 477, in __call__
result = self.forward(*input, **kwargs)
File "/media/hdd/work/local/M2Det/m2det.py", line 106, in forward
x = self.base[k](x)
File "/media/hdd/Ubuntu18.04/python/M2Det/lib/python3.6/site-packages/torch/nn/modules/module.py", line 477, in __call__
result = self.forward(*input, **kwargs)
File "/media/hdd/Ubuntu18.04/python/M2Det/lib/python3.6/site-packages/torch/nn/modules/conv.py", line 301, in forward
self.padding, self.dilation, self.groups)
RuntimeError: CUDA error: out of memory

これらを超えて学習が始まりましたが、まったく終わりません。
COCOのデータの画像数が多いのもありますが、1080だとバッチサイズ4が限界で、1epoch回すのに6hかかりました。
なので学習は断念しました。

開発メモ その169 M2DetをUbuntu18.04で使ってみる(デモ編)

Introduction


2019年最新のObject DetectionであるM2Detを使ってみます。
目標は自作のデータセットを使うこと。
まずはサンプルを実行してみます。

How to


公式ページはこちら。

M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network - qijiezhao/M2Det

なお

  • 推奨はAnacondaのようですが、ピュアなPythonで試します。
  • Python 3.6.7
  • CUDA 9.2

という前提です。

仮想環境構築

仮想環境を作成しアクティベートします。


sudo apt-get install python3-venv python3-tk
python3-m venv M2Det
source M2Det/bin/activate

環境変数設定

CUDAの環境変数を設定します。
設定済みならスキップ。


VERSION=9.2
export CUDA_HOME=/usr/local/cuda-${VERSION}
export PATH=/usr/local/cuda-${VERSION}/bin:${PATH}
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${CUDA_HOME}/lib64

設定後、下記のコマンドで確認を行います。


$ nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Tue_Jun_12_23:07:04_CDT_2018
Cuda compilation tools, release 9.2, V9.2.148

パッケージのインストール

M2DetPyTorch0.4.1をサポートと明言していますので従います。
古いバージョンは下記のページから入手します。
自分の環境のCUDAと合わせて適切なファイルをダウンロードします。

An open source deep learning platform that provides a seamless path from research prototyping to production deployment.

今回はtorch-0.4.1-cp36-cp36m-linux_x86_64.whlになります。
なお、途中の--cache-dirは、自環境でディスク容量不足のエラーが出たための対策です。


$ python -m pip install torch-0.4.1-cp36-cp36m-linux_x86_64.whl
Processing ./torch-0.4.1-cp36-cp36m-linux_x86_64.whl
Could not install packages due to an EnvironmentError: [Errno 28] デバイスに空き領域がありません

wget https://download.pytorch.org/whl/cu92/torch-0.4.1-cp36-cp36m-linux_x86_64.whl

python -m pip install pip --upgrade
python -m pip install numpy
python -m pip install --cache-dir=./cache --build ./cache torch-0.4.1-cp36-cp36m-linux_x86_64.whl
python -m pip install torchvision
python -m pip install opencv-python tqdm
python -m pip install cython matplotlib addict termcolor python3-tk

インストール後、下記のようにしてPyTorchがCUDAを認識しているかどうかを確認します。


$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> print(torch.cuda.is_available())
True
>>> torch.cuda.get_device_name(0)
'GeForce GTX 1080'

ソースの入手


git clone https://github.com/qijiezhao/M2Det.git

pycocotoolsとnms

ソースに付属のスクリプトを使ってpycocotoolsnmsをインストールします。


cd M2Det
chmod +x make.sh
./make.sh

デモ

まず、pretrainedファイルをダウンロードします。

ダウンロードしたファイルはどこでもいいので移動します。
そして、下記のコマンドを実行します。
ダウンロードしたファイルの移動先をどこでもよいといったのは、-m引数にダウンロードしたファイルのパスを指定するからです。


python demo.py -c=configs/m2det512_vgg.py -m=m2det512_vgg.pth --show

実行時はGUI画面が必要です。SSHからだと、


pos:(15.4,175.9,34.7,213.7), ids:handbag, score:0.009
pos:(97.1,248.4,128.3,304.3), ids:handbag, score:0.002
: cannot connect to X server

とエラーが出るためです。
ただし、--showを外しせば画面には表示されません。
出力結果がimgsディレクトリに書き出されます。

GUI上で実行すると下記のように画像が一定間隔で切り割って結果が表示されます。
(クリックして拡大するとアニメーションします)

ちなみに、実行時のGPUの使用メモリは約3600MBでした。

開発メモ その168 Windowsコンテナを使ってみる

Introduction


開発中のOSSでWindows Server Coreへの対応についてのissueがあったので、調査がてら導入してみる。
Windows Server 2016を使います。
評価版で検証を行います。

How to


下記の方が教えてくれました。

この記事は、(http://www.takanyan.net/windows-server-container-1/)の記事を転記したものです。Windows Server 2016からDocker...

Windowsの最新化

全てのセキュリティパッチを含む更新を行います。

コンテナの有効化

役割と機能の追加からコンテナを有効化します。

インストール

管理者権限でPowerShellを起動。
場合によっては下記のように*Nuget**の更新が必要になりますが、その場合はYesと答え、もう一度コマンドを実行します。


> Install-Module -Name DockerMsftProvider -Repository PSGallery –Force

NuGet provider is required to continue
PowerShellGet requires NuGet provider version '2.8.5.201' or newer to interact with NuGet-based repositories. The NuGet provider must be available in 'C:\Program Files\PackageManagement\ProviderAssemblies' or
'C:\Users\Administrator\AppData\Local\PackageManagement\ProviderAssemblies'. You can also install the NuGet provider by running 'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force'. Do you want PowerShellGet to
install and import the NuGet provider now?
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): Y
> Install-Module -Name DockerMsftProvider -Repository PSGallery –Force

パッケージソースからのインストールを信頼するかどうかの確認。
Yesと答えます。
少し時間がかかりますが、待っているとインストールが完了します。
完了後、再起動します。
再起動後、dockerをインストールします。


PS C:\Users\Administrator> Install-Package -Name docker -ProviderName DockerMsftProvider

The package(s) come(s) from a package source that is not marked as trusted.
Are you sure you want to install software from 'DockerDefault'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): Y

Name Version Source Summary
---- ------- ------ -------
Docker 18.09.3 DockerDefault Contains Docker EE for use with Windows Server.

確認


> docker version
Client:
Version: 18.09.3
API version: 1.39
Go version: go1.10.8
Git commit: 142dfcedca
Built: 02/28/2019 06:33:17
OS/Arch: windows/amd64
Experimental: false

Server:
Engine:
Version: 18.09.3
API version: 1.39 (minimum version 1.24)
Go version: go1.10.8
Git commit: 142dfcedca
Built: 02/28/2019 06:31:15
OS/Arch: windows/amd64
Experimental: false

実行

コードの用意

動かしたいサンプルは

  • Windows Server Core 2016
  • dotnet core のコンソール

となります。
コードは下記になります。


using System;

namespace Sample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(System.Environment.OSVersion.Platform);
}
}
}

コンテナ内でソースを用意するのは面倒なので、あらかじめ用意しておいて、ビルド時にコピーするようにします。

サンプル実行

下記のDockerfileを作成します。


FROM mcr.microsoft.com/windows/servercore:10.0.14393.2665

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# Install .NET Core SDK
ENV DOTNET_SDK_VERSION 2.2.104

RUN Invoke-WebRequest -OutFile dotnet.zip https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$Env:DOTNET_SDK_VERSION/dotnet-sdk-$Env:DOTNET_SDK_VERSION-win-x64.zip; \
$dotnet_sha512 = '2e73f64a7fdf0f9e03a58a1824375dab91cae658c1863d5130047064643a5c035db25251c443e9e0eded73ffe7b33ae6e1be4e16083da6122dfc1a7d6e2f1564'; \
if ((Get-FileHash dotnet.zip -Algorithm sha512).Hash -ne $dotnet_sha512) { \
Write-Host 'CHECKSUM VERIFICATION FAILED!'; \
exit 1; \
}; \
\
Expand-Archive dotnet.zip -DestinationPath $Env:ProgramFiles\dotnet; \
Remove-Item -Force dotnet.zip

SHELL ["cmd", "/S", "/C"]

RUN ["C:/Program Files/dotnet/dotnet.exe", "new", "console", "-n", "Sample"]
COPY ["Program.cs", "c:/Sample"]
WORKDIR Sample

そして実行。
dotnetの初回起動時の復元処理に時間がかかります。
終わらなかったら、一度Ctrl+CでbuildをキャンセルするとOKです。


$ docker build -t test .
$ docker run -t test cmd
> "C:\Program Files\dotnet\dotnet.exe" run -c Release
Win32NT

詳細なバージョン情報も表示してみます。


powershell [System.Environment]::OSVersion

Platform ServicePack Version VersionString
-------- ----------- ------- -------------
Win32NT 10.0.14393.0 Microsoft Windows NT 10.0.14393.0

開発メモ その167 Raspberry Pi 3をWindows 10でエミュレートする

Introduction


備忘録。
RaspberryPIを仮想環境で使いたくなったのでメモ。
ただし、現時点ではARM64のエミュレートはできませんでした。

How to


下記の方が教えてくれました。

どうも、ビンの王冠をスプーンで開けようとして指を怪我したニンゲンです。(怠慢ヨクナイネ)ちなみにビンの王冠と芥川龍之介は同い年なんですよ、知らなくて良い雑学で...

QEMUのインストール

下記から最新版をダウンロードしてインストール。

Raspbian Jessieのダウンロード

下記からダウンロード。
最新のStrechは動かなかったので断念。

QEMU用カーネルとDevice Treeファイル

下記から、

  • versatile-pb.dtb
  • kernel-qemu-4.4.34-jessie

をダウンロード。
kernel-qemuはバージョンが随時変わります。

Qemu kernel for emulating Rpi on QEMU. Contribute to dhruvvyas90/qemu-rpi-kernel development by creating an account on GitHub.

下準備

仮想マシンでも何でも良いのでダウンロードしたRaspbianのイメージを仮想マシンにコピー。

セクターの確認


$ fdisk -l 2017-01-11-raspbian-jessie-lite.img
Disk 2017-01-11-raspbian-jessie-lite.img: 1.3 GiB, 1390411776 bytes, 2715648 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x244b8248

Device Boot Start End Sectors Size Id Type
2017-01-11-raspbian-jessie-lite.img1 8192 137215 129024 63M c W95 FAT32 (LBA)
2017-01-11-raspbian-jessie-lite.img2 137216 2715647 2578432 1.2G 83 Linux

マウント


$ sudo mount -v -o offset=$((512*137216)) -t ext4 ./2017-01-11-raspbian-jessie-lite.img /mnt/
mount: /dev/loop0 mounted on /mnt.

ファイルシステムテーブルの編集


$ sudo vi /mnt/etc/fstab

proc /proc proc defaults 0 0
-/dev/mmcblk0p1 /boot vfat defaults 0 2
- /dev/mmcblk0p2 / ext4 defaults,noatime 0 1
+ #/dev/mmcblk0p1 /boot vfat defaults 0 2
+ #/dev/mmcblk0p2 / ext4 defaults,noatime 0 1

ld.so.preloadの編集


$ sudo editor /mnt/etc/ld.so.preload

- /usr/lib/arm-linux-gnueabihf/libarmmem.so
+ #/usr/lib/arm-linux-gnueabihf/libarmmem.so

アンマウント


$ sudo umount /mnt

起動

-hdaでダウンロードしたRaspbianのイメージを指定します。これがHDDになります


set QEMU="C:\Program Files\qemu\qemu-system-arm.exe"
%QEMU% -kernel kernel-qemu-4.4.34-jessie ^
-cpu arm1176 ^
-m 256 ^
-M versatilepb ^
-serial stdio ^
-append "root=/dev/sda2 rootfstype=ext4 rw" ^
-hda 2017-01-11-raspbian-jessie-lite.img ^
-net nic ^
-net user,hostfwd=tcp::20022-:22