Jupyter NotebookサーバーのTensor Board対応化


Jupyter Notebookサーバーを構築して数ヶ月となりました。この間Jupyter Notebookを活用してTensor Flowの勉強をしたり、Kaggleの画像認識コンペに参加して、Tensor Flowでモデルを構築したりしてきましたが、Tensor Boardが使えない1ことが分かりました。今回はdocker-compose.ymlをカスタマイズしてTensor Boardを使える様にしようと思います。

過去の記事

Tensor Boardへの対応化

localhostでTensor Boardを実行している場合は、実行時に表示されるURLをWebブラウザで開けばTensor Boardを表示させることが出来ます。しかし、Docker上で実行してるJupyter Notebookサーバー上のNotebookでTensorboardを実行可能にするためにはコンテナ上の60062ポートを公開する必要が有ります。公開したポートを介してアクセスすることでTensor Boardが利用出来る様になります。このサーバーは過去記事の方法で構築している為、Docker Composeベースで設定を行います。

コンテナの停止

リモートサーバーにログインし、docker-compse.ymlが格納されているディレクトリに移動します。ディレクトリに移動後、コンテナを一旦停止します。

docker-compose stop

docker-compose.ymlの改良

docker-compose.ymlを改良して6006ポートを公開する様に設定します。

6006ポートの公開設定を追加
version: "2.4"                                                                                                                                               
services:
    tensorflow_notebook:
        build:
            context: .
            dockerfile: Dockerfile
        runtime: nvidia
        environment:
            - NVIDIA_VISIBLE_DEVICES=all
            - NVIDIA_DRIVER_CAPABILITIES=all
        ports:
            - 8888:8888
            - 6006:6006
        volumes:
            - ../work:/home/jovyan/work
        restart: always

コンテナの再起動

docker-compose.ymlの編集を終えたら、コンテナを再起動します。ここで、デフォルトのパスワードでJupyter Notebookサーバーを使いたくない場合は、過去記事の手順を参考にパスワードを変更する行程を実施して下さい。

docker-compose up -d

設定確認

ポートが公開出来ているか確認します。無事6006ポートの公開設定が出来ました。

$ docker-compose ps
                         Name                                       Command              State                       Ports                     
-----------------------------------------------------------------------------------------------------------------------------------------------
jupyter-notebook-server-container_tensorflow_notebook_1   tini -g -- start-notebook.sh   Up      0.0.0.0:6006->6006/tcp, 0.0.0.0:8888->8888/tcp

$\Large{SSHによるポートフォワーディング}$

2020/9/13訂正: SSHによるポートフォワーディングは今回の構築方法では、不要であることが分かりました。

この行程は不要

サーバー側の設定は終わりましたので、次はクライアント側の設定を行います。サーバーの6006ポートをクライアントの6006ポートにバインドします。バインドする方法として以下のコマンドを実行します。
sshによるポートフォワーディング
ssh -fNL 6006:localhost:6006 <USER_NAME>@<SERVER_NAME>
  • 補足説明
    • -Lオプション: ポートフォワードの実行
    • -fオプション: バックグラウンド実行
    • -Nオプション: コマンド入力の無効化

~/.ssh/configに以下の内容3を追記すれば、コマンドの大部分を省略出来ます。

~/.ssh/config
Host HOST_NAME
  HostName HOST_NAME
  User USER_NAME
  LocalForward 6006 127.0.0.1:6006
  IdentityFile IDENTIFY_FILE_PATH

ポートフォワードは以下のコマンドで実行出来ます。

ssh -fN HOST_NAME

実行結果をlsofコマンドで確認します。正しくポートフォワード出来ています。

実行結果
$ lsof -i:6006
COMMAND  PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ssh     6575 USER_NAME    8u  IPv6 0x58f4e09519d9696d      0t0  TCP localhost:6006 (LISTEN)
ssh     6575 USER_NAME    9u  IPv4 0x58f4e0952735ec85      0t0  TCP localhost:6006 (LISTEN)

2020/9/13追記 Windowsの場合
Windowsにはlsofコマンドが2020年9月現在有りません。netstatコマンドを上手く使うことで見える様です。

Tensor Boardの動作確認

いよいよTensor Boardの動作確認を行います。公式チュートリアルの内容をそのまま利用します。今回利用するTensor FlowはVer2.3.0です。

JupyterNotebookの内容
import tensorflow as tf
import datetime, os

fashion_mnist = tf.keras.datasets.fashion_mnist

(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

def create_model():
    return tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(512, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

def train_model():
    model = create_model()
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    logdir = os.path.join("logs", datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
    tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
    model.fit(x=x_train, y=y_train, epochs=5, validation_data=(x_test, y_test), callbacks=[tensorboard_callback])
学習の実行
train_model()

Jupyter Notebook上にTensor Boardを表示させる拡張機能を読み込みます。

%load_ext tensorboard

必ず--bind_allオプションを付けて下さい。Dockerコンテナ上で実行されているTensor Boardにクライアントからアクセス出来る様になります。

TensorBoardの起動
%tensorboard --logdir logs --bind_all

以下の様に、Jupyter Notebook上にTensor Boardを表示出来ました。

ブラウザのアドレスバーからlocalhost:6006にアクセスすることで、Webページとして表示させることも出来ます。

  • 今回の検証に用いたJupyter Notebookのファイルはこちらのリンクからダウンロード出来ます。

まとめ

Docker上でコンテナとして起動しているJupyter Notebookサーバー上で実行したTensor Boardをクライアントからアクセスして閲覧出来る様に改良しました。Tenor Boardをモデルの学習、評価に活用してきたいと思います。

Reference


  1. Tensor Boardを実行することは出来ますが、クライアント端末のブラウザから見に行くことが出来ないという現象に見舞われています。 

  2. Tensor Boardはデフォルトで6006ポートを使用しています。別のポートを使用することも出来ますが、明示的に指定する必要が有る為、今回はデフォルトポートを公開することにします。 

  3. サーバーへのログインには公開鍵方式を用いている想定です。パスワードログインの場合はIdentityFileの指定は不要です。