Windows10でGPUを利用するCaffe環境の構築
WindowsでのCaffeの環境構築と、MNISTデータセットを使った学習、画像の分類までの流れ(2019/4/14時点)。
環境
- OS: Windows10 64bit
- GPU: NVDIA GeForce GTX 760
導入:ダウンロード
README記載のリンクからビルド済みバイナリをダウンロードでき、環境構築はそれで完了となる。
導入:ビルド
せっかくなので、READMEに沿ってソースコードからビルドしてみる。
必要物
- Visual Studio 2015(コンパイラ cl.exeを使用)
- cmake (>3.4)
cl.exeは、C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\***(アーキテクチャ名)
に配置されている。
それぞれパスを通しておく。
オプション
pycaffe、GPUを利用するため次を導入。
- Anaconda Python 3.5
- CUDA Toolkit 8.5
- cuDNN v5
cuDNNは、解凍し中のcudaフォルダをC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0
以下に配置する。
ビルド手順
1. リポジトリのclone
git clone
でCaffeのリポジトリをcloneする(ここではC:\projects\
に配置)。
cloneしたフォルダに移動し、windowsブランチに切り替える。
c:\projects>git clone https://github.com/BVLC/caffe.git Cloning into 'caffe'... remote: Enumerating objects: 65066, done. remote: Total 65066 (delta 0), reused 0 (delta 0), pack-reused 65066 Receiving objects: 100% (65066/65066), 72.54 MiB | 246.00 KiB/s, done. Resolving deltas: 100% (41108/41108), done. c:\projects>cd caffe c:\projects\caffe>git checkout windows Branch windows set up to track remote branch windows from origin. Switched to a new branch 'windows'
2. ビルド設定の変更
各自の環境に合わせて、ビルド時の設定を変更する。
script\build_win.cmdの編集
if DEFINED APPVEYOR ( ... ) else (
以下の変数を次のように変更する。
CPU_ONLY=0
:GPUを使用。PYTHON_VERSION=3
:Python3を使用。RUN_INSTALL=1
:インストールを実行。WITH_NINJA=0
:Ninjaビルドシステム(高速なビルドシステムらしい)を利用しない。
… ) else ( :: Change the settings here to match your setup :: Change MSVC_VERSION to 12 to use VS 2013 if NOT DEFINED MSVC_VERSION set MSVC_VERSION=14 :: Change to 1 to use Ninja generator (builds much faster) if NOT DEFINED WITH_NINJA set WITH_NINJA=0 :: Change to 1 to build caffe without CUDA support if NOT DEFINED CPU_ONLY set CPU_ONLY=0 ... :: Change to 3 if using python 3.5 (only 2.7 and 3.5 are supported) if NOT DEFINED PYTHON_VERSION set PYTHON_VERSION=3 ... :: Build the install target if NOT DEFINED RUN_INSTALL set RUN_INSTALL=1 ) …
また、CMakeのオプションを次のように変更する。
- DCOPY_PREREQUISITES:BOOL=0
:バイナリ生成時にDLLをコピーしない。-DCUDNN_ROOT=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0 ^
:cuDNNのパスを追加。
... cmake -G"!CMAKE_GENERATOR!" ^ -DBLAS=Open ^ -DCMAKE_BUILD_TYPE:STRING=%CMAKE_CONFIG% ^ -DBUILD_SHARED_LIBS:BOOL=%CMAKE_BUILD_SHARED_LIBS% ^ -DBUILD_python:BOOL=%BUILD_PYTHON% ^ -DBUILD_python_layer:BOOL=%BUILD_PYTHON_LAYER% ^ -DBUILD_matlab:BOOL=%BUILD_MATLAB% ^ -DCPU_ONLY:BOOL=%CPU_ONLY% ^ -DCOPY_PREREQUISITES:BOOL=0 ^ -DINSTALL_PREREQUISITES:BOOL=1 ^ -DUSE_NCCL:BOOL=!USE_NCCL! ^ -DCUDA_ARCH_NAME:STRING=%CUDA_ARCH_NAME% ^ -DCUDNN_ROOT=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0 ^ "%~dp0\.." ...
CMakeList.txtの編集
使用するコンパイラとしてcl.exeを設定する。
project(Caffe C CXX)
の前に記載すること。
また、パスの分離記号に\
(バックスラッシュ)を使うと失敗するので注意。
... # C compiler set(CMAKE_C_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe") set(CMAKE_CXX_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe") ...
3. ビルド
scripts\build_win.cmdを実行し、Configurationの生成からCaffeのビルドまでを実施する。
インストールを設定すると、build\tools\install
以下に実行バイナリが配置される(通常はbuild\tools\Release\
以下)。
コマンドラインツールcaffe.exeを実行して次のような表示がされれば、ビルドは成功。
c:\projects\caffe>.\build\install\bin\caffe.exe caffe.exe: command line brew usage: caffe <command> <args> commands: train train or finetune a model test score a model device_query show GPU diagnostic information time benchmark model execution time No modules matched: use -help
Pythonモジュールはbuild\install\python
以下に生成される。
適宜パスを通したり、site-packageにコピーするなどすれば利用可能となる。
MNISTデータセットでのテスト
おなじみMNISTデータセットを使って、学習・認識のテストをしてみる。
データセットのダウンロード
上記webサイトから次の4種類のデータをダウンロードし、解凍したファイルをexamples\mnist
以下に配置する(7-zipではうまく解凍できなかったため、MSYS2を経由してgzip -d
で解凍した)。
- train-images-idx3-ubyte.gz:学習用画像データ
- train-labels-idx1-ubyte.gz:学習用ラベルデータ
- t10k-images-idx3-ubyte.gz:検証用画像データ
- t10k-labels-idx1-ubyte.gz:検証用ラベルデータ
LMDBの生成
build\install\bin
以下のツールconvert_mnist_data.exeを実行し、上記データファイルを学習・テスト用のLMDBデータに変換する。
パスの設定が大変なので、次のbatスクリプトを実行すると楽。
SET EXE=%~dp0%\..\..\build\install\bin\convert_mnist_data.exe SET ROOT=%~dp0% %EXE% %ROOT%\train-images-idx3-ubyte %ROOT%\train-labels-idx1-ubyte %ROOT%\mnist_train_lmdb --backend=lmdb %EXE% %ROOT%\t10k-images-idx3-ubyte %ROOT%\t10k-labels-idx1-ubyte %ROOT%\mnist_test_lmdb --backend=lmdb
学習用データmnist_train_lmdbおよび、検証用データmnist_test_lmdbが生成される。
学習
ネットワークとしてLeNetを使用し、MNISTデータセットを学習する。 学習には次のファイルを使用する。
- examples\mnist\Release\lenet_train_test.prototxt:ネットワーク定義。学習時、検証時に利用するパラメータを含む。
- examples\mnist\Release\lenet_solver.prototxt:solverの定義。
このsolverはおおまかに次のような設定となっている。
- Momentum SGDによる最適化
- バッチサイズ64のミニバッチ学習
- 10000回学習、500回ごとに検証
- 5000回ごとに結果を保存
Caffeのルートフォルダに移動し、caffe.exe train --solver=...
で学習を実施する。
prototxtが読み込まれた後学習が開始され、設定した周期でのパラメータを次のファイルとして出力する。
- .caffemodel:ネットワークの重みパラメータ
- .solverstate:solverのパラメータ
c:\projects\caffe>.\build\install\bin\caffe.exe train --solver=.\examples\mnist\lenet_solver.prototxt I0414 00:14:25.140101 7368 caffe.cpp:219] Using GPUs 0 I0414 00:14:25.328984 7368 caffe.cpp:224] GPU 0: GeForce GTX 760 I0414 00:14:25.594820 7368 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead. I0414 00:14:25.629798 7368 solver.cpp:44] Initializing solver from parameters: ... I0414 00:14:25.713747 7368 solver.cpp:330] Iteration 0, Testing net (#0) I0414 00:14:27.022940 5740 data_layer.cpp:73] Restarting data prefetching from start. I0414 00:14:27.076906 7368 solver.cpp:397] Test net output #0: accuracy = 0.1214 I0414 00:14:27.077906 7368 solver.cpp:397] Test net output #1: loss = 2.38325 (* 1 = 2.38325 loss) ... I0414 00:18:33.994693 7368 solver.cpp:447] Snapshotting to binary proto file examples/mnist/lenet_iter_10000.caffemodel I0414 00:18:34.027674 7368 sgd_solver.cpp:273] Snapshotting solver state to binary proto file examples/mnist/lenet_iter_10000.solverstate I0414 00:18:34.049660 7368 solver.cpp:310] Iteration 10000, loss = 0.00193049 I0414 00:18:34.049660 7368 solver.cpp:330] Iteration 10000, Testing net (#0) I0414 00:18:35.302888 5740 data_layer.cpp:73] Restarting data prefetching from start. I0414 00:18:35.353857 7368 solver.cpp:397] Test net output #0: accuracy = 0.9915 I0414 00:18:35.353857 7368 solver.cpp:397] Test net output #1: loss = 0.0263693 (* 1 = 0.0263693 loss) I0414 00:18:35.354856 7368 solver.cpp:315] Optimization Done. I0414 00:18:35.354856 7368 caffe.cpp:260] Optimization Done.
GPUを使用すると5分程度で学習が終わり、10000回学習した結果のパラメータとしてlenet_iter_10000.caffemodelが得られた。
分類
学習結果のパラメータを利用し、画像の分類を実施してみた。
lenet_deploy.prototxtの作成
分類用のネットワークに学習時の設定は必要ないため、次のように簡略化したlenet_deploy.prototxtを作成する。
name: "LeNet" layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 1 dim: 1 dim: 28 dim: 28 } } } layer { name: "conv1" type: "Convolution" bottom: "data" top: "conv1" convolution_param { num_output: 20 kernel_size: 5 stride: 1 } } layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 2 stride: 2 } } layer { name: "conv2" type: "Convolution" bottom: "pool1" top: "conv2" convolution_param { num_output: 50 kernel_size: 5 stride: 1 } } layer { name: "pool2" type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { pool: MAX kernel_size: 2 stride: 2 } } layer { name: "ip1" type: "InnerProduct" bottom: "pool2" top: "ip1" inner_product_param { num_output: 500 } } layer { name: "relu1" type: "ReLU" bottom: "ip1" top: "ip1" } layer { name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" inner_product_param { num_output: 10 } } layer { name: "prob" type: "Softmax" bottom: "ip2" top: "prob" }
Pythonスクリプトの作成
コマンドライン引数として与えた画像を分類する、次のスクリプトを作成する。
""" classification_test.py """ import sys import os import numpy as np import caffe # model, weightの読み込み model = "lenet_deploy.prototxt" weights = "lenet_iter_10000.caffemodel" # LeNetの構築 net = caffe.Classifier(model, weights, channel_swap=[0], image_dims=(28, 28)) # 画像データの変換 image = sys.argv[1] input_image = caffe.io.load_image(image, color=False) # 分類 predict = net.predict([input_image], False) # 分類結果の出力 print("prediction class: {}".format(predict[0].argmax()))
画像の用意と分類
MNISTのデータは黒背景でサイズ28x28[pixel]のグレースケール画像となっているため、形式に合わせて0~9の数字が描かれたPNG画像を作成した。
上記スクリプトを実行すると、コマンドライン引数で指定した画像が0~9の10クラスに分類され、結果がコンソールに出力される。
c:\projects\caffe\examples\mnist>python classification_test.py 0.png WARNING: Logging before InitGoogleLogging() is written to STDERR W0414 01:12:09.519904 1504 _caffe.cpp:175] DEPRECATION WARNING - deprecated use of Python interface W0414 01:12:09.520903 1504 _caffe.cpp:176] Use this instead (with the named "weights" parameter): ... prediction class: 0
10枚の画像それぞれの分類結果は次のようになり、1.pngのみ分類を誤る結果となった。
正解 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
分類 | 0 | 2 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
すんなりと分類成功とはいかないようである。