LoginSignup
16
14

More than 3 years have passed since last update.

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

Posted at

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コンテナ活用のわかりやすい事例だと思います。

16
14
0

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
16
14