【2021/08メモ】windows+dockerでGPU対応の機械学習環境をつくる
2021/8時点での情報です。安定版になっていない内容が多く、一年もたったら役に立たなくなっていると思われます
わざわざ怪しいタイトルをつけたので、信憑性はそんなもんです。
ほぼ作業メモですが、ちょっとハマりどころがあったのでまとめておきます
特に参考にしたサイト様
注意点
WSL2のGPU認識などを利用するためにはwindows insider programに登録して、開発段階のwindows updateを受け取る必要があり、環境が通常のwindowsと変わります。
実際私は今windows11相当の環境になっています…
環境概要
Windows + WSL2 + Docker(WSL2バックエンド)です。
WSL2バックエンドを使用することで、nvidia周りのドライバなどを頑張って準備しなくてもGPUを認識してくれます。
1.Windows Insider Programへの登録とアップデート
あくまで2021年8月頃では必須なだけで、そのうち必須じゃなくなるかもしれませんので、この記事を見た未来の方は一度調べてください
私はBeta Channelを選択してしまいましたが、リリースプレビューで可能ならばそれに越したことは無い(最も安定しているため)ので、これからやる方はまずリリースプレビュー Channelを試すことを個人的にはお勧めします。
ここのやり方については詳しく書きません。ここを自力で突破できない人はwindows insiderで発生する問題に自力で対処できなくて苦労しそうだからです。
2. CUDA on Windows Subsystem for Linux (WSL) - Public Previewのインストール
これはwindowsにインストールします。
3. WSL2のインストール
現状では
wsl --install -d Ubuntu-20.04
などとたたけば指定のディストリビューションでインストールされます。
4.DockerDesktopのインストールとWSL2バックエンドの設定
インストールしたらdocker Desktopを開いて、WSL integrationを有効化します。
4.5 一応終わり、以降オプションです。
なんとここまでで既にWindows上で動かしたdockerコンテナから、GPUが使えるようになっています。ところがなんと、lspciなどしてもGPUを直接みることができません
(参考:https://qiita.com/ksasaki/items/ee864abd74f95fea1efa#生の-linuxとは違うところも)
これで認識されてないのかとハマりました。
皆さんは気にせず次行きましょう
5.DockerFileの準備
機械学習のための全部盛りイメージといえばKaggleのイメージなどが思いつくかもしれませんが、Kaggleのイメージはうまく動きませんでした。(nvidiaドライバの扱いが通常と異なるためだと思われます)
また、Kaggleのイメージは結構重たい(50GB弱くらいあった気がします)ので、イメージを適当に準備しましょう。
オレオレ適当DockerFileとrequirements.txtをここに置いておくので、皆さんも最強のイメージを作ってください。ベースはnvidiaのcuda+cudannイメージで、そこにこちらのサイトをパク…参考にいろいろ追加したものです。
jupyter labを動かすこと前提で、jupyterのホーム(/mlwsで設定)をvolumeマウントとして永続化します。
Dockerfile
FROM nvidia/cuda:11.4.0-cudnn8-devel-ubuntu20.04
ENV NOTO_DIR /usr/share/fonts/opentype/notosans
##ミラーを使うなどをする人が多いので入れてましたが、そこまで早くもならず無用だったので外しています。
# RUN sed -i.bak -r 's@http://(jp.)?archive.ubuntu.com/ubuntu/@http://ftp.jaist.ac.jp/pub/Linux/ubuntu/@g' /etc/apt/sources.list
## aptに時間がかなりかかるので、パッケージを絞っています。
RUN apt update \
&& apt install -y \
wget \
bzip2 \
# ca-certificates \
# libglib2.0-0 \
# libxext6 \
# libsm6 \
# libxrender1 \
git \
# mercurial \
# subversion \
# zsh \
# openssh-server \
# gcc \
# g++ \
# libatlas-base-dev \
# libboost-dev \
# libboost-system-dev \
# libboost-filesystem-dev \
curl \
# make \
unzip \
vim \
# ffmpeg \
mecab \
libmecab-dev \
mecab-ipadic-utf8 \
file \
xz-utils \
sudo \
python3 \
python3-pip
RUN mkdir -p ${NOTO_DIR} &&\
wget -q https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip -O noto.zip &&\
unzip ./noto.zip -d ${NOTO_DIR}/ &&\
chmod a+r ${NOTO_DIR}/NotoSans* &&\
rm ./noto.zip
# remove cache files
RUN apt-get autoremove -y && apt-get clean && \
rm -rf /usr/local/src/*
RUN git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git \
&& cd mecab-ipadic-neologd \
&& bin/install-mecab-ipadic-neologd -n -y
COPY requirements.txt /tmp/
RUN pip install --no-cache-dir -U pip setuptools wheel \
&& pip install --no-cache-dir -r /tmp/requirements.txt
# nodejsの導入
RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - \
&& sudo apt-get install -y nodejs
# ## JupyterLabの拡張機能
# 変数や行列の中身を確認
RUN jupyter labextension install @lckr/jupyterlab_variableinspector@3.0.7
# 自動整形
RUN pip install autopep8 \
&& pip install jupyterlab_code_formatter \
&& jupyter labextension install @ryantam626/jupyterlab_code_formatter \
&& jupyter serverextension enable --py jupyterlab_code_formatter
# jupyter の config ファイルの作成
RUN mkdir /mlws && echo "c.NotebookApp.notebook_dir = '/mlws' \n" | tee -a ${HOME}/.jupyter/jupyter_notebook_config.py
EXPOSE 8888
CMD ["python3","-m","jupyter", "lab", "--ip=0.0.0.0", "--port=8888","--allow-root","--NotebookApp.token=''"]
requirements.txt
keras
tensorflow
tensorflow-addons
pandas
numpy
scipy
matplotlib
seaborn
lightgbm
xgboost
scikit-learn
mecab-python3
jupyterlab
spacy
torch
torchvision
timm
transformers
requests
beautifulsoup4
albumentations
gensim
joblib
pillow
librosa
分離環境なのでanacondaとか入れちゃってもいいですし、お好きに
6.テスト
docker volume create mlws
docker build -t ml_base:latest .
docker run --rm -it -p 8888:8888 --gpus all --mount source=mlws,target=/mlws -t ml_base:latest
で http://localhost:8888 にアクセスすると、jupyterlabにつながるはずです。
ところで、確認できなかったGPUがちゃんと使われるのか見てみます。
jupyte labで
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
とすると、device type GPUがいることが確認できます。また、適当なirisで学習を回してみると、
iris学習コード
import tensorflow as tf
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categorical
iris = load_iris()
data_X = iris.data
data_y = to_categorical(iris.target)
train_X, test_X, train_y, test_y = train_test_split(data_X, data_y, test_size=0.3, random_state=0)
model = tf.keras.models.Sequential([
tf.keras.layers.Input(4),
tf.keras.layers.Dense(300, activation='relu'),
tf.keras.layers.Dense(300, activation='relu'),
tf.keras.layers.Dense(300, activation='relu'),
tf.keras.layers.Dense(500, activation='relu'),
tf.keras.layers.Dense(700, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),
loss='categorical_crossentropy',
metrics=['accuracy'])
model.summary()
result = model.fit(train_X, train_y, batch_size=32, epochs=3, validation_data=(test_X, test_y), verbose=1)
WARNING:tensorflow:Please add `keras.layers.InputLayer` instead of `keras.Input` to Sequential model. `keras.Input` is intended to be used by Functional model.
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_18 (Dense) (None, 300) 1500
_________________________________________________________________
dense_19 (Dense) (None, 300) 90300
_________________________________________________________________
dense_20 (Dense) (None, 300) 90300
_________________________________________________________________
dense_21 (Dense) (None, 500) 150500
_________________________________________________________________
dense_22 (Dense) (None, 700) 350700
_________________________________________________________________
dense_23 (Dense) (None, 3) 2103
=================================================================
Total params: 685,403
Trainable params: 685,403
Non-trainable params: 0
_________________________________________________________________
Epoch 1/3
4/4 [==============================] - 0s 43ms/step - loss: 3.5071 - accuracy: 0.2476 - val_loss: 1.0908 - val_accuracy: 0.2444
Epoch 2/3
4/4 [==============================] - 0s 10ms/step - loss: 0.9079 - accuracy: 0.5714 - val_loss: 1.2686 - val_accuracy: 0.6000
Epoch 3/3
4/4 [==============================] - 0s 10ms/step - loss: 0.6718 - accuracy: 0.6571 - val_loss: 0.4582 - val_accuracy: 0.7556
ということでさすがにCPUでは出なそうな速さが出てるので大丈夫そうです。
7.おわりに
繰り返しますが、ベータ版とかpublic previewとかがすごく多いので情報がコロコロ変わると思いますので、ご注意ください。
とはいえ、gpuが直接は見えなかったり、kaggleイメージそのまま使おうとしたらうまくいかなかったりいろいろあったので今回メモにしました。誰かの参考になればうれしいです。
Discussion