AutoGluon 0.2.0によるAutoML環境(Docker前提)の作り方

# １．はじめに

AutoGluonは、その性能の良さから2020年に話題になった[^1]AutoMLツールである。例えば、とあるKaggleコンペで99%の人間に勝ったという話[^2]もある。

翌2021年4月にはバージョン0.2.0が公開[^3]されたが、環境によってはマニュアル通りにインストールするだけでは十分正しい動作がなされないことがある。また、残念なことにWindows非対応で、LinuxかMacにしか対応していない。

本記事では、AutoGluon 0.2.0を実行するDockerコンテナと、それをVSCodeから利用するための手順を解説する。この手順は、少なくとも筆者の持つUbuntu 20.04.2 LTSの環境で動作確認している。Dockerコンテナを使う前提としたので、本記事の内容を応用すればWindowsでもAutoGluonを利用できるようになるかもしれない[^4]。

またDockerを使わずとも、本記事で説明するrequirements.txtを利用すれば、Linux環境ならAutoGluonを正しくインストールすることはおそらく可能と思われる。少なくとも筆者の環境では動作確認している。

なお、「そもそも、AutoGluonで何ができるか知りたい！」という方には、下記リンク先の記事がオススメである。この記事では、AutoGluon 0.2.0のチュートリアルである「tabular-quickstart」に記載されたコードの解説をしている。
[【機械学習】AutoGluonの使い方・クイックスタートの解説(表形式データ) - どこにでもいる30代SEの学習ブログ](https://predora005.hatenablog.com/entry/2021/06/17/000000)

[^1]: 例えば、[https://upura.hatenablog.com/entry/2020/03/18/190300](https://upura.hatenablog.com/entry/2020/03/18/190300)を参照。
[^2]: [https://twitter.com/jaguring1/status/1240108860796366853](https://twitter.com/jaguring1/status/1240108860796366853)
[^3]: [https://pypi.org/project/autogluon/0.2.0/](https://pypi.org/project/autogluon/0.2.0/)
[^4]: 実際にサウサンプトン大の学生さんが、Docker Desktop for Windowsを使ってAutoGluonを動かした報告を中国語で行っている。詳しくは、[https://zhuanlan.zhihu.com/p/370999648](https://zhuanlan.zhihu.com/p/370999648)を参照。

# ２．AutoGluon用のDockerfileの作り方

本章では、AutoGluonの公式インストール手順によって起こりうる問題点を指摘し、その代案となるインストール方法をDockerfileに記述する方法を述べる。

## ２．１．公式のインストール手順

2021年6月現在の公式サイト[^5]によると、GPUが存在してCUDA10.1が利用できるLinux環境では、以下のコマンド実行によりAutoGluonがインストール可能としている。

```bash
python3 -m pip install -U pip
python3 -m pip install -U setuptools wheel
python3 -m pip install -U "mxnet-cu101<2.0.0"
python3 -m pip install autogluon
```

なお、10.1以外のバージョンのCUDAを利用する環境ではmxnet-cu101ではなく、利用しているバージョンのCUDAに対応するmxnetをインストールする必要がある。例えばCUDA11.0を使っているならmxnet-cu110をかわりにインストールする必要がある。
また、GPUを使わない環境にインストールしたいなら、mxnet-cu101のかわりにmxnetをインストールすればよい。

## ２．２．公式手順の問題点

しかし、筆者が「nvidia/cuda:10.1-cudnn7-runtime-ubuntu18.04」のDockerイメージを利用し、Python3.7を用いて一連のインストールを試みたところ、以下2点の問題が生じることがわかった。

1. AutoGluonが、Jupyter用のtqdmのプログレスバーを表示する際に、`AttributeError: 'tqdm' object has no attribute 'disp'`が発生して異常終了する。
1. Daskのプロファイラ画面など、bokehを利用する画面が出力できない。

前者の原因は、マニュアル通りのインストール方法では適切なバージョンのipywidgetsがインストールされないこと[^6]である。また後者の原因は、同じく適切なバージョンのbokehがインストールされないことである。これらはGPU依存ではないはずなので、予めipywidgetsやbokehが適切にインストールされている環境でなければ、本件はLinux環境全般で再現する恐れがある。

[^5]: [https://auto.gluon.ai/stable/index.html#installation](https://auto.gluon.ai/stable/index.html#installation)
[^6]: 原因特定にあたっては、[https://blog.csdn.net/weixin_40539826/article/details/112854159](https://blog.csdn.net/weixin_40539826/article/details/112854159)を参考にした。

## ２．３．requirements.txtの設定

前節で挙げた問題の対策として、以下のrequirements.txtを作成した。前述の通り、筆者がCUDA10.1環境を利用しているため、ここではmxnet-cu101をインストールしている例を挙げた。２．１節に記載の通り、mxnet-cu101の部分はそれぞれの環境に合わせて適宜変更が必要となる。

```plaintext
autogluon==0.2.0
bokeh==2.1.1
dask==2021.5.0
ipywidgets==7.6.3
mxnet-cu101==1.8.0.post0
tqdm==4.60.0
```

## ２．４．Dockerfileの定義

先に述べたとおり、今回はDocker環境上でAutoGluonを実行する。そのためのDockerfileは以下の通り定義した。ここでは、VSCodeとの連携に必要なユーザ設定などもあわせて行っている。

なお、本Dockerfileの作成にあたってはQiitaの記事[「VS CodeでDocker開発コンテナを便利に使おう」](https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0)を参考にした。

```Dockerfile
ARG nvidia_cuda_version=10.1-cudnn7-runtime-ubuntu18.04
FROM nvidia/cuda:${nvidia_cuda_version}

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

ARG REQUIREMENTS_TXT=requirements.txt

RUN apt update && apt -y full-upgrade \
    && apt -y install build-essential swig \
    && apt -y install apt-utils \
    && apt -y install --no-install-recommends apt-utils dialog 2>&1 \
    && apt -y install git iproute2 procps lsb-release \
    && apt -y install \
    python3.7 \
    python3-pip \
    python3-venv \
    python3.7-venv \
    && apt -y install python3.7-dev \
    && python3.7 -m pip install -U pip \
    && python3.7 -m pip install setuptools wheel \
    && groupadd --gid $USER_GID $USERNAME \
    && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
    && apt -y install sudo \
    && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
    && chmod 0440 /etc/sudoers.d/$USERNAME \
    && rm -rf /var/lib/apt/lists/*
    
COPY $REQUIREMENTS_TXT /tmp/
RUN python3.7 -m pip install -r /tmp/$REQUIREMENTS_TXT
```

# ３．VSCodeからDocker上のAutoGluonを利用するための手順

前章で作成したDockerfileを用いて、VSCodeから利用できるAutoGluon環境を構築・利用する手順を説明する。本章の執筆にあたっては、先に紹介した[「VS CodeでDocker開発コンテナを便利に使おう」](https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0)を大いに参考とした。

## ３．１．拡張機能「Remote-Containers」のインストール

Dockerコンテナ上のPythonやJupyterをVSCodeから利用するためには、拡張機能「Remote-Containers」[^7]が必要となる。これは、VSCodeのExtensionsタブから直接インストールすることができる。

[^7]: [https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)

## ３．２．devcontainer.jsonの定義

次に、Dockerコンテナを利用するための設定ファイルである、devcontainer.jsonを作成する。本ファイルには、DockerコンテナとVSCodeの連携に必要な設定や、利用したい拡張機能の情報を列挙していく。その記述例を以下に示す。

ただし、`"runArgs": ["--gpus", "all"],`の部分はDocker側からGPUを利用するための設定なので、CPUのみを利用する場合は削除が必要となる。

```json
{"name": "autogluon",
    "context": "..",
    "dockerFile": "Dockerfile",
    "settings": {
        "http.proxySupport": "off",
        "jupyter.alwaysTrustNotebooks": true,
        "python.pythonPath": "/usr/bin/python3.7",
        "python.linting.enabled": true,
        "terminal.integrated.shell.linux": "/bin/bash"
    },
    "appPort": [ 9000 ],
    "remoteUser": "vscode",
    "extensions": [
        "ms-python.vscode-pylance",
        "ms-python.python",
        "ms-toolsai.jupyter",
    ],
    "workspaceFolder": "/home/vscode",
    "workspaceMount": "type=bind,source=${localWorkspaceFolder},target=/home/vscode/autogluon/,type=bind",
    "runArgs": ["--gpus", "all"],
    "remoteUser": "vscode"
}
```

## ３．３．workspaceの設定

最後に、Dockerコンテナを利用するworkspaceの設定方法について述べる。

あらかじめ所望のworkspaceをVSCodeで作成したのち、そのルート直下に.devcontainerという名前の隠しディレクトリを作成する必要がある。.devcontainerの中には、これまでに作成したDockerfileとdevcontainer.jsonを配置する。また、Dockerfileが参照するrequirements.txtを、workspaceのルート直下に忘れず置く必要もある[^8]。

[^8]: devcontainer.jsonの`context`で、本ファイルの一つ上のディレクトリ(workspaceのルートに相当)を指定していることが理由。

まとめると、下記のファイル配置を行う必要がある。(ここでのルートはworkspaceのもの)

```plaintext
.
├── .devcontainer
│   ├── Dockerfile
│   └── devcontainer.json
├── requirements.txt
└── workspace.code-workspace
```

以上の設定をしたあとでworkspaceをVSCodeで開き直せば、Dockerイメージの作成からビルド処理が進む。ビルドが終われば、ローカル環境とまったく変わらない使い方で、コンテナ上にあるPythonを実行してAutoGluonを利用できるようになっている。

# ４．AutoGluonのコード実行例

前章までの手順で作ったworkspaceを使えば、AutoGluonを利用したコードを動かすことができるはずである。ipywidgetsが適切にインストールできているなら、下記のキャプチャのようにtqdmがカラーのプログレスバーを出力できるようになっている。
![Screenshot from 2021-06-20 13-30-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268034/7ea48c96-1b29-8d98-85bb-aeca947b4627.png)

## ４．１．サンプルコードの入手方法

AutoGluon 0.2.0は、以前のバージョンのものとAPIが大きく変わっている。そのため、これより前に書かれたQiitaの記事にあるAutoGluonのコードはほぼ、そのままでは動かなくなっている。

AutoGluon 0.2.0のサンプルコードは、公式のチュートリアルページからのコピペで入手できる。もっとも単純なものは冒頭でも言及した[tabular-quickstart](https://auto.gluon.ai/stable/tutorials/tabular_prediction/tabular-quickstart.html)にある。

## ４．２．コード実行中に表示されるダイアログ

VSCodeでAutoGluonのコードを実行する際、処理によっては「Path does not exist」というタイトルのダイアログが表示され、「SummaryOfModels.htmlが見つからないように見える」と言われることがある。
![Screenshot from 2021-06-20 11-31-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268034/18177b9d-7638-a878-299d-4bc9ad105b25.png)

しかしbokehが適切にインストールできていれば、下記のような内容のSummaryOfModels.htmlが、ダイアログに書かれていたパスに正しく出力されていることが確認できる。なお、直接ホストにインストールしたAutoGluonで同じ処理を実行すると、このHTMLは問題なく自動でブラウザオープンされる[^9]。

[^9]: SummaryOfModels.htmlが出力されるパスは、devcontainer.jsonの設定によりホスト側と紐づけている。そのため、ホスト側のパスを自動オープンできる方法があれば、本節の問題は発生しなくなると思われる。だが、筆者はまだその方法を把握していない。

![Screenshot from 2021-06-20 14-55-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268034/8cb950e2-9ec7-91be-f68d-a8388e6fb3cb.png)

これは、AutoGluonが学習に使った各アルゴリズムの精度と予測時間を並べたものになっている。これを見ることで、どのアルゴリズムを使えば精度的にも時間的にも要件を満たせるかをすぐに把握できる。

# ５．おわりに

AutoGluon 0.2.0は本来なら、AutoMLとしての強力さのみならず、画面出力機能も充実しており使いやすいツールである。しかし、現状はインストールに難のあるツールでもある。

本記事を書いたのは、こうした問題からAutoGluonが使われないことはもったいないと思ったためである。これをきっかけに、一人でも多くの方がAutoGluonを利用していただけるようになったら幸いである。

また、AutoGluonの`TabularPredictor`にある`fit`メソッドは、scikit-learnの教師あり学習クラスのものとは互換性がない。scikit-learnの`fit`は説明変数と目的変数を別々の引数で渡す作りになっているが、`TabularPredictor`のものは両者を同じデータフレームにまとめて渡す作りになっているためである。

```python
# TabularPredictorでは、fitメソッドの引数が1つだけであることに注意
predictor = TabularPredictor(label=label, path=save_path).fit(train_data)
```

そのため、例えば`TabularPredictor`をscikit-learnの`Pipeline`と連携させたくとも、そのままではできない。もちろん、scikit-learnの学習ロジックを差し替える際は、引数のデータフレームの加工処理が余分に必要となる。

ただし、簡単なラッパクラスを書けば互換性を実現できそうに見えるので、今後はその開発・公開を予定している。

【2021/07/13追記】ラッパクラスは既に作っています。以下の記事で紹介しています。
https://qiita.com/kzkymn/items/4df067f6f45d36df1740