0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Docker】Optuna Dashboardの構築

Posted at

こんにちは。Optuna Dashboardというものがあると知り、それをDockerで環境構築しながら可視化を試みます。

やりたいこと

★Jupyterlab上でOptunaを用い最適化したモデルの学習過程をOptuna Dashboardで可視化するDocker環境を構築すること(GPU使用)

上記を実現しようとすると様々な工程があるので、細かく区切って考えていきます。

完成イメージ
このようなダッシュボードをWEBブラウザ上で見る
image.png

流れ

  • Docker関連
    • ディレクトリを作成
    • GPU環境を構築
    • docker compose.ymlの作成
    • Dockerfileの作成
    • requirement.txtの作成
      ⇒ コンテナを構築・起動させる
  • 学習関連
    • データベースを作成
    • jupyterlabでoptunaのstudyを作成する
    • Optuna dashboardに接続
      ⇒ ダッシュボード完成!

Docker関連

ディレクトリを作成

このディレクトリがDocker Composeのプロジェクト名に使われます。このプロジェクト名によって、個々の環境が分離されますので、なんのコンテナか分かりやすく作ります。今後作るファイルはこのディレクトリに保存します。

project/
├── docker-compose.yaml
├── Dockerfile
├── requirements.txt
└── data/ 

GPU環境を作成

私はこのサイトを見ながら行い、無事コンテナ内にCUDA 12.1がインストールするところまでできました。
https://highreso.jp/edgehub/machinelearning/ubuntudocker.html#index_id5

docker compose.ymlの作成

コンテナを作成するには、どういうコンテナを作成するのかYAML(ヤムル)形式のファイルで定義します。
今回は以下4つのサービスを構築していきます。

  • jupyterlab:機械学習のコードを書いて実行する開発環境
  • PostgreSQL:Optunaの試行データを保存するデータベース
  • pgAdmin:PostgreSQLを視覚的に管理するためのGUI
  • Optuna Dashboard:Optunaの試行結果を可視化するためのウェブインターフェース
services:
  gpu-container:
    container_name: XX-gpu-container
    build:
      context: .
      dockerfile: Dockerfile
    runtime: nvidia
    environment:
      - NDIVIA_VISIBLE_DEVICES-all
      - NDIVIA_DRIVER_CAPABILITIES=compute,utility
      - JUPYTER_ENABLE_LAB=yes
    restart: unless-stopped
    stdin_open: true
    tty: true
    ports:
      - "XXXX:8888"  # JupyterLab
    # Dockerコンテナとホストマシン(ローカルPC)の間でディレクトリを共有する設定
    volumes:
      - ./notebooks:/home/jovyan/notebooks
    command: >
      jupyter lab --allow-root --ip=0.0.0.0 --port=8888 --NotebookApp.token=''
    networks:
      - XX-network

  postgres:
    image: postgres:17-bullseye #イメージからコンテナを作成
    container_name: XX-postgres
    environment:
      POSTGRES_USER: optuna_user
      POSTGRES_PASSWORD: optuna_password
      POSTGRES_DB: optuna_db
    ports:
      - "XXXX:5432"  # 外部ポート XXXX -> 内部ポート 5432
    volumes:
      - postgres_data:/var/lib/postgresql/data # データを永続化するため
    restart: always
    networks:
      - XX-network

  pgadmin:
    image: dpage/pgadmin4 # イメージからコンテナを作成
    container_name: XX-pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: XXXXXXXX@XXXX.com  # pgAdmin のログイン用メールアドレス(任意)
      PGADMIN_DEFAULT_PASSWORD: XXXX          # pgAdmin のログイン用パスワード(任意)
    ports:
      - "XXXX:80"  # 外部ポート XXXX -> 内部ポート 80
    depends_on:
      - postgres # PostgreSQLサービスが起動していることを前提に動作
    restart: always
    networks:
      - XX-network
  
  optuna_dashboard:
    image: ghcr.io/optuna/optuna-dashboard # イメージからコンテナを作成
    container_name: XX-optuna_dashboard
    ports:
      - "XXXX:8080"  # 外部ポート XXXX -> 内部ポート 8080
    depends_on:
      - postgres
    restart: always
    networks:
      - XX-network

volumes:
  postgres_data: # ホストにデータを保存

networks:
  XX-network:
    driver: bridge

コンテナ名とポート番号(外部)は任意です。今回はXXとして記載しているので適宜ご変更ください。
構成はこんな感じです。

services:
  jupyter: # コンテナ名
    image: # イメージ名
    port: # ポート番号
    environment: # 環境変数の設定
    depends_on: # コンテナ間の依存関係
    restart: # コンテナの再起動の設定
volumes: # コンテナに接続するボリューム

コンテナとは?イメージとは?

  • コンテナは独立した実行環境
  • イメージはコンテナを作成するための指示が記載された読み取り専用のテンプレート
    ⇒ 今回は、imageを指定しており、Docker Hub(公式のイメージリポジトリ)やGitHub Container Registry (GHCR)かを参照してダウンロードしています

Dockerfileの作成

# Stage 1: Build stage
# ビルド環境を作成し、必要なすべての依存関係をインストールするステージ

# ベースイメージを指定
FROM nvidia/cuda:12.1.1-base-ubuntu20.04 AS builder

# rootユーザーに切り替え
USER root

# 環境変数を定義
ENV NB_UID=1000
ENV NB_GID=100
ENV HOME=/home/jovyan

# システムパッケージの更新とインストール
RUN apt-get update && apt get install -y --no-install-recommends \
    curl \
    build-essential \
    gcc \
    libpq-dev \
    python3 \
    python3-pip \
    python3-dev && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# requirements.txtをコンテナ内にコピー
COPY requirements.txt /tmp/requirements.txt

# Pythonパッケージのインストール
RUN pip install --upgrade pip && \
    pip install -r /tmp/requirements.txt && \
    pip install jupyterlab && \
    rm /tmp/requirements.txt
    
# $PATHにインストール先を追加
ENV PATH=$PATH:/usr/local/bin/:/root/.local/bin

# CUDA 12.1
RUN pip install torch=2.4.1 torchvision=0.19.1 torchaudio=2.4.1 --index-url https://download.pytorch.org/whl/cu121

# 必要なディレクトリを作成
RUN mkdir -p $HOME/.local/share/jupyter && \
    mkdir -p $HOME/notebooks && \
    chown -R $NB_UID:$NB_GID $HOME

# Stage 2: Final stage
# 実行環境用の軽量イメージを作成し、不要な開発ツールを排除

# ベースイメージを指定
FROM nvidia/cuda:12.1.1-base-ubuntu20.04

# rootユーザーに切り替え
USER root

# 環境変数を再定義
ENV NB_UID=1000
ENV NB_GID=100
ENV HOME=/home/jovyan

# Stage 1 から必要なファイルをコピー
COPY --from=builder /usr /usr
COPY --from=builder $HOME $HOME

# 作業ディレクトリの作成と所有権の付与
RUN mkdir -p /home/jovyan/notebooks && chown -R $NB_UID:$NB_GID /home/jovyan/notebooks
RUN mkdir -p /home/jovyan/.local/share/jupyter/runtime && \
    chown -R $NB_UID:$NB_GID /home/jovyan/.local

# 必要に応じてJupyterのポートを開放
EXPOSE 8888

# デフォルトのユーザーに戻す
USER $NB_UID

# 作業ディレクトリを設定
WORKDIR /home/jovyan/notebooks

# jupyterlabの起動コマンドを設定
CMD ["jupyter". "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root"]

上記は試行錯誤の上、できたコードであり、もっと簡潔に書けたり省略できるところもあると思います。
torch のバージョンによっては 異なる CUDA バージョンが必要になるので確認が必要です。
公式サイト: https://pytorch.org/get-started/previous-versions/
torch のバージョンに対応する CUDA を確認する方法:

python -c "import torch; print(torch.version.cuda)"

requirement.txtの作成

開発環境を管理するために使うライブラリを記載します。
あくまで例となりますので、ご自身が必要なものを入れてください。

numpy==1.26.4
pandas==2.1.4
seaborn==0.13.2
matplotlib==3.5.3
japanize-matplotlib==1.1.3
scikit-learn==1.5.2
sqlalchemy==2.0.37
psycopg2-binary==2.9.10
optuna==4.1.0
optuna-dashboard==0.17.0
ipywidgets==8.0.7

※ psycopg2もしくはpsycopg2-binaryのインストールは必ず必要です!

  • psycopg2 ⇒ 本番環境
    PythonでPostgreSQLデータベースと接続するためのライブラリ。
    SQLクエリの実行やデータベースの操作を簡単に行える。
  • psycopg2-binary ⇒ 開発環境
    psycopg2 のバイナリパッケージ版。
    ビルド済みのC拡張モジュールが含まれているため、依存ライブラリやコンパイルが不要で簡単にインストールできる。

コンテナを構築・起動させる

下準備ができました。
ここから、imageを実際に構築していきます。
まずは、ターミナル(Windowsの場合)を開いて、実行環境のディレクトリに移動します。

  • コンテナを構築・起動させる
docker-compose up -d --build

今のままではrelation "version_info" does not existFATAL: database "optuna_db" does not existなどのエラーメッセージが出ると思いますが、次で対応していきます。

学習関連

データベースを作成

今回のoptuna dashboardはデータベースからデータを取ってくるような形になっています。
データベースはコマンドからも作れますが、pdadminにアクセスしてGUI操作をしていきます。
image.png
ログイン時はdocker_compose.ymlで指定したメールアドレスとパスワードを入力します。

PGADMIN_DEFAULT_EMAIL: XXXXXXXX@XXXX.com  # pgAdmin のログイン用メールアドレス(任意)
PGADMIN_DEFAULT_PASSWORD: XXXX          # pgAdmin のログイン用パスワード(任意)
  1. Add New Serverをクリック
  2. Generalタブ
    • Name:XX-postgres
      image.png
  3. Conectionタブ
    • Host name/address:XX-postgres
    • Port:5432
    • Maintanance database:optuna_db
    • Username:optuna_user
    • Password:otpuna_password
      ※上記はDocker compose.ymlに書かれているものです

コマンド操作はこちら

docker exec -it XX-postgres psql -U optuna_user -d postgres
CREATE DATABASE optuna_db;
CREATE USER optuna_user WITH PASSWORD 'optuna_password';
GRANT ALL PRIVILEGES ON DATABASE optuna_db TO optuna_user;

データベースができたら確認してみます。

docker exec -it XX-postgres psql -U optuna_user -d optuna_db

optuna_dbの中に入れたら成功です!

jupyterlabでoptunaのstudyを作成する

まず、データベースに接続するために、先述したpsycopg2をインポートする必要があります。

import psycopg2

これを実行してImportError: libpq.so.5: cannot open shared object file: No such file or directoryになる場合は、portfolio3-jupyterコンテナに入ってから、を手動でインポートします。

docker exec -it --user root portfolio3-jupyter bash
apt-get update && apt-get install -y libpq-dev

ちなみに、ルートユーザーでない場合は権限がないと出力されインストールできませんでした。

docker exec -it XX-jupyter bash
apt-get update && apt-get install -y libpq-dev

# エラー表示
Reading package lists... Done
E: List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied)

では、otpunaのstudyを作り、テーブルを作成します。
これを行わないまま次項に進むと、relation "version_info" does not existエラーが発生しました。

import optuna
storage_url = "postgresql+psycopg2://optuna_user:optuna_password@XX-postgres:5432/optuna_db"
study = optuna.create_study(storage=storage_url, study_name="example_study", load_if_exists=True)
print("Optuna storage connected!")

Optuna dashboardに接続

本来Docker compose.ymlのコマンドで指定するべきですが、私はコマンドの記載方法でエラーになってしまったので、ここでは手動でoptuna dashboardを起動させて、PostgreSQLのデータベースに接続します。

docker run -it --rm --network cpu-version_portfolio-network -p XXXX:8080 ghcr.io/optuna/optuna-dashboard postgresql+psycopg2://optuna_user:optuna_password@XX-postgres:5432/optuna_db --port 8080 --host 0.0.0.0

この後、実際にhttp://localhost:XXXXにアクセスしてみるとこのような画面が出てきます。XXXXはホストのポートであり、ここからコンテナの 8080 に繋がることになります。

image.png

では実際に学習させてみましょう。

def objective(trial):
    x = trial.suggest_float("x", -100, 100)
    y = trial.suggest_categorical("y", [-1, 0, 1])
    return x**2 + y

if __name__ == "__main__":
   
    # OptunaのStudyを作成
    study = optuna.create_study(
        storage=storage_url,
        study_name="example_study",
        load_if_exists=True  # Studyが既に存在する場合はロード
    )
    study.optimize(objective, n_trials=100)
    print(f"Best value: {study.best_value} (params: {study.best_params})")

Best value: -0.7740110290467385 (params: {'x': -0.4753829729315739, 'y': -1})が出力されました。
optuna dashboardものぞいてみると、きちんと出力されています!:v:
image.png

番外編

今回GPUを使用する前提で書きましたが、GPUがないPCを使う場合は、gpu-countainerが必要ありません。
参考までに、CPU版のコードも記載します。コンテナの構成は同様ですが、コンテナの作り方が異なってきます。

Dockerfile

# ベースイメージを指定
FROM jupyter/base-notebook:python-3.11 AS builder

ベースがjupyterになります。

Docker compose.yml

services:
  jupyter:
    build:  # Dockerfile を利用する設定を追加
      context: .
      dockerfile: Dockerfile
    container_name: portfolio3-jupyter
    ports:
      - "XXXX:8888"  # JupyterLab
    # Docker コンテナとホストマシン(ローカルPC)の間でディレクトリを共有する設定
    volumes:
      - ./notebooks:/home/jovyan/work/notebooks
    environment:
      - JUPYTER_ENABLE_LAB=yes
    restart: unless-stopped 
    command: >
      jupyter lab --ip=0.0.0.0 --no-browser --NotebookApp.token='' --NotebookApp.password=''
    networks:
      - XX-network

以上です、読んでいただきありがとうございました。

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?