PyTorchの勉強用に、jupyterとvisdomが同時に動くdocker-imageを作る
PyTorchの学習を可視化するには、
Facebookが公開しているvisdomを使うのが良さそうなのですが、
いろいろ試すのに、環境作ったり、立ち上げるのも手間なので、
jupyterとvisdomをまとめて動かせるdocker-imageを作りました。
本エントリは、その作成に関するメモです。
visdom
https://github.com/facebookresearch/visdom
※TensorFlowでいうTensorBoardみたいなものという理解で良さそうです。
Dockerfileと起動方法
最終的に作成したDockerfileと起動方法を示します。
Dockerfile
Dockerfileは以下の通りです。
FROM ubuntu:20.04
RUN apt-get update \
&& apt-get install -y python3 python3-pip supervisor
RUN pip3 install torch==1.7.1+cpu torchvision==0.8.2+cpu -f https://download.pytorch.org/whl/torch_stable.html \
&& pip3 install visdom jupyter
RUN echo "\
[supervisord]\n\
nodaemon=true\n\
[program:visdom]\n\
command=visdom\n\
[program:jupyter]\n\
command=jupyter notebook --ip=* --no-browser --allow-root\n\
stdout_logfile=/dev/stdout\n\
stdout_logfile_maxbytes=0\n\
stderr_logfile=/dev/stderr\n\
std_logfile_maxbytes=0\n\
" > /etc/supervisor/conf.d/supervisord.conf
EXPOSE 8888 8097
WORKDIR /work
CMD ["/usr/bin/supervisord"]
CUDA(nvidia-docker)を使いたい場合は、
ベースイメージ、インストールするPyTorchを変更します。
CUDA 11.0であれば、以下のような感じになると思います。
FROM nvidia/cuda:11.1-devel-ubuntu16.04
RUN pip3 install torch==1.7.1+cu110 torchvision==0.8.2+cu110 -f https://download.pytorch.org/whl/torch_stable.html \
ベースイメージ、PyTorchの指定は、
それぞれ、以下で調べます。
nvidia/cuda | dockerhub
https://hub.docker.com/r/nvidia/cuda/
GET STARTED | PyTorch
https://pytorch.org/get-started/locally/
イメージのビルド
以下のように、イメージをビルドします。
docker build . -t torchvisdom
起動方法
作成したイメージは、以下のポートでサービス起動するので、それぞれ指定して実行します。
- jupyter: Port: 8888
- visdom: Port: 8097
docker run -v `pwd`:/work -p 8888:8888 -p 8097:8097 torchvisdom
接続方法
ブラウザを開いて、以下のURLから各サービスを利用します。
jupyterはtokenの入力を求められるので、ターミナルに表示されているtokenを入力します。
- jupyter: http://127.0.0.1:8888/
- visdom: http://127.0.0.1:8097/
適当なサンプルを動かす
環境が出来たので、以下のページにあるサンプルに、
損失関数の可視化を追加して動かすことにします。
LEARNING PYTORCH WITH EXAMPLES | PyTorch
https://pytorch.org/tutorials/beginner/pytorch_with_examples.html
前段部分、学習部分のコードに分けていますが、
学習部分のコードを実行すると、
次の画像のように、visdomに損失関数の収束の様子が表示されます。
前段部分のコードです。
import torch
import math
import visdom # visdomでの可視化のために追加
import numpy as np
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # Uncomment this to run on GPU
vis = visdom.Visdom(env='sample_1') # visdomでの可視化のために追加
# Create random input and output data
x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype)
y = torch.sin(x)
# Randomly initialize weights
a = torch.randn((), device=device, dtype=dtype)
b = torch.randn((), device=device, dtype=dtype)
c = torch.randn((), device=device, dtype=dtype)
d = torch.randn((), device=device, dtype=dtype)
学習部分のコードです。
learning_rate = 1e-6
for t in range(2000):
# Forward pass: compute predicted y
y_pred = a + b * x + c * x ** 2 + d * x ** 3
# Compute and print loss
loss = (y_pred - y).pow(2).sum().item()
if t % 100 == 99:
print(t, loss)
vis.line(X=np.array([t]), Y=np.array([loss]), update='append', win='loss', name='loss') # visdomでの可視化のために追加
# Backprop to compute gradients of a, b, c, d with respect to loss
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()
# Update weights using gradient descent
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= learning_rate * grad_c
d -= learning_rate * grad_d
print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3')
参考にした情報
Dockerで、複数プロセス動かす方法として、
Supervisorを使う方法が紹介されています。
Supervisor を Docker で使う | docker-docs-ja https://docs.docker.jp/engine/admin/using_supervisord.html
Supervisorを使うと、
jupyterのtokenが標準エラー出力に表示されなくなってしまうので、
次の方法で変更しています。
[メモ] Dockerでsupervisordを使うときにログを標準出力する | sugiki / Qiita https://qiita.com/sugiki/items/86515393664cb5ce16ff
以上。