20190929のTensorFlowに関する記事は2件です。

tensorflow+kerasを扱うためのPython仮想環境はvenvとAnacondaどちらを使うべきか

結論

Anacondaを使おう

環境

OS:Ubuntu 18.04

背景

今日のディープラーニング界隈では技術の進化が飛躍的に早く、それに合わせて
tensorflowやkerasといったフレームワークの更新が頻繁に行われている。
ここで問題となるのが各モジュール間のバージョンには依存関係があり、適切なバージョンの組み合わせでないとプログラムが動作しないといったことが頻繁に発生する。
特にCUDA,cuDNN,tensorflow-gpu間の依存関係はかなりシビアで、バッチレベルが少しでも異なると平気で動かなくなる。
tensorflow公式がテスト済みの依存関係を発表しているが、このバージョンに合わせてライブラリをインストールしてもうまく動作しないことがある。
現にtensorflow-gpu-1.31.1, cuDNN-7.4, CUDA-10.0, Python3.6の組み合わせだとうまく動作しなかった。
Screenshot from 2019-09-29 21-41-16.png
特に厄介なのが、一見うまく動いているようで実はうまく動いていない場合がある。
たとえばtensorflow-gpuを使っているのにもかかわらず、GPUが認識されずCPUでモデルの学習が行われてしまうといった症状がある。
これは一見正常に学習が進んでいるように見えるのだが、実際はCPUで学習が行われてしまうため、学習に莫大な時間がかかってしまう。
fit()した際に以下のメッセージが表示されている場合はGPUで学習が行われていない。

2019-09-22 14:52:41.548583: E tensorflow/stream_executorcuda
/cuda_dnn.cc:329] Could not create cudnn handle:
 CUDNN_STATUS_INTERNAL_ERROR

なぜ仮想環境を使うのか

こういった背景がある中で、仮想環境を使っていない場合、
特定のモジュールを更新した際に過去に作成したプログラムのモジュールバージョンの依存関係を満たせなくなり動かなくなる。といったことがある。
そのため、Pythonを使う場合仮想環境を使うことが一般的である。
仮想環境といってもVMwareやVirtualBoxのようなハイパーバイザー型仮想環境とは異なり、
venvやAnacondaはライブラリのパスの切り方を変えているだけなので、ホストマシンの性能を最大限に活かすことができる。

なぜAnacondaを使うのか

Pythonの仮想環境といえばvenvを使うのが一般的だが、ディープラーニングをやりたいのであればAnacondaが最良だという結論に至った。
Anacondaを使う理由は次の通り。

  • 環境構築が楽
  • モジュールのバージョン変更が楽
  • 複数バージョンのCUDAを扱うことができる

特に大きな理由が3番目の"複数バージョンのCUDAを扱うことができる"部分である。
Anacondaを使わずに複数バージョンのCUDAを同一環境で共存させようとすると環境変数の管理が大変なことになる。
更にCUDAのバージョンアップさせる際にも癖があり、最悪ホストマシンが起動しなくなるといったこともある(経験済み)。
そのため、同一環境でCUDAを複数管理したい場合はAnacondaが最良の選択となる。
venvではこれが実現できない(パスの切り方工夫したらできるかも?)。

Anacondaを扱う上で注意する点

  • pipは使わない
  • conda install "モジュール名"ではモジュールが見つからない時がある。

Anaconda環境下でpipを使うと環境が壊れてしまうことがあるため、Anaconda環境下ではpipは使わない方が良い
これに関しては以下の記事が参考になる。
  condaとpip:混ぜるな危険
また、conda installでモジュールが見つからない場合はAnaconda Cloudで探せば大抵見つかる。
現時点ではAnaconda Cloudで使いたいモジュールが見つからなかったことはない。

Anacondaでモジュールのバージョンを変更する

Anacondaで仮想環境作成済み、モジュールインストール済みを前提として説明する。
以下のコマンドでAnaconda-Navigatorを起動する

anaconda-navigator

Environments→作成した仮想環境を選択→右側のコンボボックスが"Installed"になっていることを確認し、バージョンを変更したいモジュール名をSearch Packagesから検索する
モジュールがインストールされていれば表示されるので、☑のところを右クリックし、"mark for specific version installation"内から変更先のバージ
ョンを選択する。

すると☑がオレンジ色になるのでApply→Applyを選択するとバージョンの変更が完了となる。
Screenshot from 2019-09-29 22-53-10.png

Screenshot from 2019-09-29 22-55-08.png
Screenshot from 2019-09-29 22-55-26.png

2019/09/29時点でのおすすめ組み合わせ

上記でも述べた通り、各モジュールには依存関係があるため、tensorflow(-gpu), cudatoolkit, cudnnの組み合わせは適切なバージョン同士でなければ動作しない。
そのため、最新のモジュールを入れても動作しないことがある。
また、公式発表のテスト済みの依存関係の表通りに導入しても動かないことがある。
Anaconda環境下で動作確認済み(GPU環境)のバージョンの組み合わせは次の通り

モジュール名 バージョン
keras-gpu 2.2.4
tensorflow-gpu 1.12.0
cudatoolkit 9.0
cudnn 7.3.1

※Python3.6を使用

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerコンテナで、Keras + TensorFlow / Jupyter notebook環境を簡単にデプロイする

Kerasを活用して、デープラーニングを動作させようと考えた場合、環境整備に手間取るのがめんどくさいですよね。
今回は、Dockerコンテナから、Keras + tensorFlow / Jupyter notebook環境を簡単に整備できるようになりました。
私の個人リポジトリ"ttsubo/study_of_deeplearning_with_keras"と、このQiita記事にて、作業履歴を共有しておきます。

⬛︎ 事前準備

Dockerコンテナを動かすUbuntuサーバから、GPUが扱えるようにしておく必要があります。

(1) Ubuntuサーバ側の環境セットアップ

具体的には、Qiita記事: "Dockerで、GPU対応なコンテナ環境を整備する"のセットアップが終わっているものとします。

(2) "study_of_deeplearning_with_keras"リポジトリの取得

Dockerコンテナから、Keras + tensorFlow / Jupyter notebook環境を整備できるように、事前にリポジトリを用意しておきましたので、以下の要領で、リポジトリを取得しておいてください。

$ git clone https://github.com/ttsubo/study_of_deeplearning_with_keras.git

(3) cuDNNファイルを別途、入手する

Dockerコンテナ内にcnDNNパッケージをインストールする必要があるので、cuDNN Archive からcuDNN v7.6.2 (July 22, 2019), for CUDA 10.0をダウンロードしておいてください。なお、ダウンロードするためには事前にメンバー登録が必要です。

  • cuDNN Runtime Library for Ubuntu18.04 (Deb)
  • cuDNN Developer Library for Ubuntu18.04 (Deb)
  • cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)

そして、build/downloadフォルダに配置しておいてください。

$ cd build/download/
$ ls -l
total 314384
-rw-r--r-- 1 ttsubo ttsubo 164426244 Sep 29 14:36 libcudnn7_7.6.2.24-1+cuda10.0_amd64.deb
-rw-r--r-- 1 ttsubo ttsubo 152045132 Sep 29 14:36 libcudnn7-dev_7.6.2.24-1+cuda10.0_amd64.deb
-rw-r--r-- 1 ttsubo ttsubo   5442884 Sep 29 14:36 libcudnn7-doc_7.6.2.24-1+cuda10.0_amd64.deb

(4) Dockerイメージをビルドします

$ docker-compose build

ちなみに、Dockerfileファイルは、こんな感じです。

Dockerfile
FROM nvidia/cuda:10.0-devel-ubuntu18.04

MAINTAINER Toshiki Tsuboi <t.tsubo2000@gmail.com>

RUN apt update \
 && apt install -y \
      git-core \
      build-essential \
      python-dev \
      python-openssl \
      libssl-dev \
      libbz2-dev \
      libffi-dev \
      libsqlite3-dev \
      libreadline-dev \
      zlib1g-dev \
      libsm6 \
      libxext6 \
      libxrender-dev \
      libblas-dev \
      curl \
      vim \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# install pyenv
ENV HOME /root
ENV PYENV_ROOT $HOME/.pyenv
ENV PATH $PYENV_ROOT/bin:$PATH
RUN git clone https://github.com/pyenv/pyenv.git $HOME/.pyenv
RUN echo 'eval "$(pyenv init -)"' >> $HOME/.bashrc \
 && eval "$(pyenv init -)"

# install python using pyenv
RUN apt update \
 && apt install -y libssl1.0-dev \
 && pyenv install anaconda3-5.3.1 \
 && pyenv global anaconda3-5.3.1

# install pip
WORKDIR /
ADD https://bootstrap.pypa.io/get-pip.py /
RUN python get-pip.py \
 && rm get-pip.py

# install python package
WORKDIR /root
COPY requirements.txt /root
RUN /root/.pyenv/shims/pip install -r requirements.txt

# install cuDNN
COPY download /root/debian_packages
RUN cd /root/debian_packages \
 && dpkg -i \
  libcudnn7_7.6.2.24-1+cuda10.0_amd64.deb \
  libcudnn7-dev_7.6.2.24-1+cuda10.0_amd64.deb \
  libcudnn7-doc_7.6.2.24-1+cuda10.0_amd64.deb

#setup jupyter
RUN /root/.pyenv/shims/jupyter notebook --generate-config \
 && sed -i -e "s/#c.NotebookApp.ip = 'localhost'/c.NotebookApp.ip = '0.0.0.0'/" /root/.jupyter/jupyter_notebook_config.py \
 && sed -i -e "s/#c.NotebookApp.allow_remote_access = False/c.NotebookApp.allow_remote_access = True/" /root/.jupyter/jupyter_notebook_config.py \
 && sed -i -e "s/#c.NotebookApp.token = '<generated>'/c.NotebookApp.token = ''/" /root/.jupyter/jupyter_notebook_config.py

EXPOSE 8888
ENTRYPOINT ["sh", "-c", "/root/.pyenv/shims/jupyter notebook --allow-root"]

⬛︎ 実際に、動かしてみる

今回、動かしてみるデープラーニング用Pythonスクリプトは、Keras repoが提供しているサンプルアプリです。

keras/examples/mnist_cnn.py
'''Trains a simple convnet on the MNIST dataset.

Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

(1) Dockerコンテナを起動する

Docker-composeを使って、Dockerコンテナを起動します。
この段階で、Dockerコンテナ内では、Jupyter notebook環境も常駐するようになっています。

$ docker-compose up
Creating Keras ... done
Attaching to Keras
Keras           | [I 05:43:15.263 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
Keras           | [W 05:43:15.379 NotebookApp] All authentication is disabled.  Anyone who can connect to this server will be able to run code.
Keras           | [I 05:43:15.403 NotebookApp] JupyterLab extension loaded from /root/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/jupyterlab
Keras           | [I 05:43:15.404 NotebookApp] JupyterLab application directory is /root/.pyenv/versions/anaconda3-5.3.1/share/jupyter/lab
Keras           | [I 05:43:15.406 NotebookApp] Serving notebooks from local directory: /root
Keras           | [I 05:43:15.406 NotebookApp] The Jupyter Notebook is running at:
Keras           | [I 05:43:15.406 NotebookApp] http://(Keras or 127.0.0.1):8888/
Keras           | [I 05:43:15.406 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
Keras           | [W 05:43:15.407 NotebookApp] No web browser found: could not locate runnable browser.

(2) Dockerコンテナ内に、入って、サンプルアプリを起動する

まずは、Dockerコンテナに入ります

$ docker exec -it Keras bash

そして、サンプルアプリを起動します。$ python examples/mnist_cnn.py

root@Keras:~# python examples/mnist_cnn.py
Using TensorFlow backend.
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples

... (snip)

Train on 60000 samples, validate on 10000 samples
Epoch 1/12
2019-09-29 06:00:43.489125: I tensorflow/stream_executor/dso_loader.cc:152] successfully opened CUDA library libcublas.so.10.0 locally
60000/60000 [==============================] - 8s 127us/step - loss: 0.2654 - accuracy: 0.9186 - val_loss: 0.0628 - val_accuracy: 0.9785
Epoch 2/12
60000/60000 [==============================] - 7s 115us/step - loss: 0.0888 - accuracy: 0.9736 - val_loss: 0.0430 - val_accuracy: 0.9849
Epoch 3/12
60000/60000 [==============================] - 7s 112us/step - loss: 0.0677 - accuracy: 0.9802 - val_loss: 0.0394 - val_accuracy: 0.9871
Epoch 4/12
60000/60000 [==============================] - 7s 114us/step - loss: 0.0566 - accuracy: 0.9832 - val_loss: 0.0321 - val_accuracy: 0.9885
Epoch 5/12
60000/60000 [==============================] - 7s 114us/step - loss: 0.0480 - accuracy: 0.9860 - val_loss: 0.0350 - val_accuracy: 0.9882
Epoch 6/12
60000/60000 [==============================] - 7s 110us/step - loss: 0.0450 - accuracy: 0.9864 - val_loss: 0.0274 - val_accuracy: 0.9897
Epoch 7/12
60000/60000 [==============================] - 7s 113us/step - loss: 0.0395 - accuracy: 0.9883 - val_loss: 0.0292 - val_accuracy: 0.9903
Epoch 8/12
60000/60000 [==============================] - 7s 114us/step - loss: 0.0351 - accuracy: 0.9890 - val_loss: 0.0309 - val_accuracy: 0.9893
Epoch 9/12
60000/60000 [==============================] - 7s 112us/step - loss: 0.0342 - accuracy: 0.9892 - val_loss: 0.0288 - val_accuracy: 0.9906
Epoch 10/12
60000/60000 [==============================] - 7s 111us/step - loss: 0.0328 - accuracy: 0.9900 - val_loss: 0.0264 - val_accuracy: 0.9918
Epoch 11/12
60000/60000 [==============================] - 7s 112us/step - loss: 0.0305 - accuracy: 0.9901 - val_loss: 0.0280 - val_accuracy: 0.9916
Epoch 12/12
60000/60000 [==============================] - 7s 117us/step - loss: 0.0289 - accuracy: 0.9911 - val_loss: 0.0268 - val_accuracy: 0.9917
Test loss: 0.026753987711756782
Test accuracy: 0.9916999936103821

GPUを使用した場合、1エポック当たり、7秒程度で、学習が進んでいく様子が確認できますね。
ちなみに、CPUを使用した場合は、1エポック当たり、41秒程度で学習が進んでいきました。
私のGPU環境GeForce GTX 1060 3GBだと、CPUよりも、約6倍も、学習に要する時間が短縮できるようです。

root@Keras:~# python examples/mnist_cnn.py
Using TensorFlow backend.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 8s 1us/step
x_train shape: (60000, 28, 28, 1)
60000 train samples
10000 test samples

... (snip)

Train on 60000 samples, validate on 10000 samples
Epoch 1/12
60000/60000 [==============================] - 41s 679us/step - loss: 0.2666 - accuracy: 0.9189 - val_loss: 0.0607 - val_accuracy: 0.9819
Epoch 2/12
60000/60000 [==============================] - 41s 677us/step - loss: 0.0895 - accuracy: 0.9733 - val_loss: 0.0402 - val_accuracy: 0.9866
Epoch 3/12
60000/60000 [==============================] - 41s 677us/step - loss: 0.0673 - accuracy: 0.9798 - val_loss: 0.0365 - val_accuracy: 0.9879
Epoch 4/12
60000/60000 [==============================] - 41s 677us/step - loss: 0.0550 - accuracy: 0.9835 - val_loss: 0.0341 - val_accuracy: 0.9885
Epoch 5/12
60000/60000 [==============================] - 41s 678us/step - loss: 0.0477 - accuracy: 0.9857 - val_loss: 0.0293 - val_accuracy: 0.9908
Epoch 6/12
60000/60000 [==============================] - 41s 677us/step - loss: 0.0424 - accuracy: 0.9871 - val_loss: 0.0283 - val_accuracy: 0.9913
Epoch 7/12
60000/60000 [==============================] - 41s 678us/step - loss: 0.0387 - accuracy: 0.9881 - val_loss: 0.0275 - val_accuracy: 0.9906
Epoch 8/12
60000/60000 [==============================] - 41s 678us/step - loss: 0.0340 - accuracy: 0.9897 - val_loss: 0.0261 - val_accuracy: 0.9909
Epoch 9/12
60000/60000 [==============================] - 41s 677us/step - loss: 0.0319 - accuracy: 0.9902 - val_loss: 0.0291 - val_accuracy: 0.9906
Epoch 10/12
60000/60000 [==============================] - 41s 676us/step - loss: 0.0307 - accuracy: 0.9906 - val_loss: 0.0287 - val_accuracy: 0.9918
Epoch 11/12
60000/60000 [==============================] - 41s 676us/step - loss: 0.0277 - accuracy: 0.9916 - val_loss: 0.0282 - val_accuracy: 0.9917
Epoch 12/12
60000/60000 [==============================] - 41s 676us/step - loss: 0.0271 - accuracy: 0.9915 - val_loss: 0.0267 - val_accuracy: 0.9921
Test loss: 0.026685928908488858
Test accuracy: 0.9921000003814697

(3) 最後に、jupyter notebook経由で、サンプルアプリを起動してみる

Web browserから、http://(Keras or 127.0.0.1):8888/にアクセスします。
そして、notebookを起動すると、こんな感じの結果が確認できました。
minist_cnn.png

⬛︎ 終わりに、、、

Keras + TensorFlow / Jupyter notebook環境が簡単に、デプロイできるようになりました。
デープラーニング動作検証を通じて知識を習得する場合には、デープラーニング環境を色々とスクラップ&ビルドできるのが望ましいと思うので、まさに、Dockerコンテナ活用のわかりやすい事例だと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む