数年前の機械学習コードが動かない?
あなたがAIの研究者であったり、AIに関連するサービスの開発者であるならば、少し昔の機械学習モデルを動かしたい機会が少なからずあることでしょう。
しかし、いざgit cloneしてpip install -r requirements.txtするとエラーがわんさか…ということはザラにあります。
全部インストール出来たのに、実行段階でエラーになる事もしばしば…
以下では、そのような状況を打開するための方法を、私個人の経験に基づいて説明しようと思います。
使用するOSはUbuntu、実行環境はローカルまたは社内サーバー等を想定しています。
必ず使用すべきツール
以下は私が強く推奨するツールです。絶対に使った方が良いので今すぐインストールして下さい。
-
pyenv: Pythonのバージョンを自由に変えられる -
venv: Pythonのパッケージをプロジェクト毎に独立させる (インスコ不要) -
docker: システムの環境をプロジェクト毎に独立させる -
aptitude: システムパッケージの依存を賢く解決する -
update-alternatives: cudaのバージョン等を変えられる (多分インスコ不要)
その他に、慣れておいた方がよいコマンドは
-
add-apt-repository: aptリポジトリの表示・追加・削除 -
apt-key: aptリポジトリのキーの表示・追加・削除
ですかね。
結論
最初に結論を書いてしまいますが、次のセクションでより具体的なコマンドなども紹介するのでそちらもご覧ください。
私は以下のような流れで環境構築をすると良いと思います。
最初にやること
-
pyenvでPythonのバージョンを合わせる -
venv環境を作る -
requirements.txtを一括でインストールしてみる- インストール出来たらラッキー✌️
a.update-alternativesでcudaのバージョンを切り替えよう - インストール出来なかったら…
a.requirements.txtにあるパッケージを個別にインストールする
b. エラーの原因となっているパッケージを特定する
c. そのパッケージを、バージョンを様々に変えてインストールしてみる
d. もしシステムパッケージが必要なら、aptitudeでインストール
- インストール出来たらラッキー✌️
- 以上でダメなら
Dockerに頼る- 早めの諦めが肝心
- Dockerfileを書くのは面倒なので書かない
Dockerでやること
-
requirements.txtを見てtorchのバージョンを確認 - そのtorchのバージョンに対応するcudaのバージョンを例のサイトからエスパーする
- インストール時:
# pip3 install torch==X.X.X+cuXXX -f https://download.pytorch.org/whl/torch_stable.html
- インストール時:
- さらに、必要なUbuntuのバージョンを探る
- 必要なシステムパッケージが
aptitudeでインストールできるものを選ぶ
- 必要なシステムパッケージが
-
Docker Hubから
nvidia/cudaイメージのタグを探す- 例:
<cuda ver.>-cudnnX-runtime-ubuntuXX.04
- 例:
- イメージをpullしてインタラクティブシェルを作成
$ docker pull nvidia/cuda:<見つけたタグ> $ docker run --gpus all -it nvidia/cuda:<タグ> /bin/bash # apt update; apt install aptitude; aptitude install curl git # aptitude install python3.X python3-pip- Dockerコンテナの中なら
pyenvやvenvは使わなくてもいいんじゃない? - Pythonの起動は
pythonではなくpython3.X
- Dockerコンテナの中なら
- 最初にcudaが機能しているかどうかを確認する事が重要!!
# pip3 install torch==X.X.X+cuXXX -f https://download.pytorch.org/whl/torch_stable.html # python3.X >>> import torch >>> torch.version.cuda >>> torch.cuda.is_available() >>> torch.Tensor([1, 2, 3]).cuda() -
# git cloneののち# pip3 install -r requirements.txt- ここでも同様に、エラーとなるパッケージを個別にバージョン指定してインストールすると良かったりする😇
- 全て動いたら新しいDockerイメージとして保存しよう!
$ docker commit xxxxxxx <タグ名>
具体例と細かいテク
では、実際に現在の一般的な環境 (Ubuntu22.04LTSを想定) では動かないコードを動かしてみましょう。
ここでは、音声合成モデルであるGrad-TTSを動かします。
venvでのインストール①: numbaとの戦い
READMEのInstallationのところにPython3.6が使われているとありますので、Python3.6を使うための環境を整えましょう。
$ git clone https://github.com/huawei-noah/Speech-Backbones.git
$ cd SpeechBackbones/Grad-TTS/
$ pyenv install 3.6
$ pyenv global 3.6
$ python -m venv .venv
$ source .venv/bin/activate
インストールされているPythonのバージョン一覧は$ pyenv versionsで確認できます。
venvの有効化後にpythonコマンドやpipが正しく設定されているかどうかは$ which pipなどとして確認できます。pipでインストールされたパッケージ一覧は$ pip listで確認可能です。
依存関係をインストールします:
(.venv) $ pip install -r requirements.txt --no-cache-dir
失敗しました。ログを見ると、
Collecting numba>=0.43.0 (from librosa==0.8.0->-r requirements.txt (line 8))
の箇所で失敗しています。requirements.txtを見ると、librosa==0.8.0が依存に入っており、これがnumbaに依存しているようです。さらに、エラーメッセージをよく見ると
distutils.errors.DistutilsError: Couldn't find a setup script in /tmp/easy_install-yyg21p65/numpy-2.1.3.tar.gz
と出ており、numpy==2.1.3が発見できなかったと分かります。それもそのはずで、Python3.6がサポートされているnumpyのバージョンは1.19.5までです ($ pip install numpy==2.1.3とすると分かります) 。
これは、pipが出来るだけ新しいバージョンのnumbaをインストールしようとした事が原因である可能性があります。よって、最小限のバージョンのnumbaをインストールしてみましょう:
(.venv) $ pip install numba==0.43.0 --no-cache-dir
今度は以下のようなエラーが出ました:
RuntimeError: Building llvmlite requires LLVM 10.0.x or 9.0.x, got '14.0.0'. Be sure to set LLVM_CONFIG to the right executable path.
これは、numba==0.43.0が依存しているllvmliteはLLVM 10.0.xを必要とするのに、それがシステムにインストールされていないというエラーです (LLVM 14.0.0はインストールされています) 。
numba==0.43.0では古すぎたと考えられるので、今度はnumba==0.50.0をインストールしてみましょう:
(.venv) $ pip install numba==0.50.0 --no-cache-dir
Installing collected packages: llvmlite, numba
Successfully installed llvmlite-0.33.0 numba-0.50.0
上手く行きました!
venvでのインストール②: matplotlibとの戦い
では、requirements.txtのインストールをもう一度試しましょう:
(.venv) $ pip install -r requirements.txt --no-cache-dir
今度は、numba>=0.43.0に対する依存が
Requirement already satisfied: numba>=0.43.0 in ./.venv/lib/python3.6/site-packages (from librosa==0.8.0->-r requirements.txt (line 8)) (0.50.0)
となり、無事解決できました。しかし別のエラー:
Running setup.py install for pillow ... error
が出てしまいました。パッケージpillowをインストールする際にエラーが出ているようですが、requirements.txtにはpillowに対する依存が書かれていません。そこで、どのパッケージがpillowに依存しているのかを調べると、
Collecting pillow>=6.2.0 (from matplotlib==3.3.3->-r requirements.txt (line 4))
というログが見つかりました。matplotlibがpillowに依存していたようですね。
例によって、最小限のバージョンのpillowをインストールすることを試みましょう:
(.venv) $ pip install pillow==6.2.0 --no-cache-dir
Installing collected packages: pillow
Successfully installed pillow-6.2.0
通りました。それではもう一度、requirements.txtに挑戦します:
(.venv) $ pip install -r requirements.txt --no-cache-dir
Successfully installed Unidecode-1.1.2 appdirs-1.4.4 audioread-3.0.1 certifi-2024.8.30 cffi-1.15.1 charset-normalizer-2.0.12 decorator-5.1.1 idna-3.10 importlib-resources-5.4.0 inflect-5.0.2 joblib-1.1.1 librosa-0.8.0 packaging-21.3 pooch-1.6.0 pycparser-2.21 requests-2.27.1 resampy-0.4.3 scikit-learn-0.24.2 scipy-1.5.4 soundfile-0.12.1 threadpoolctl-3.1.0 tqdm-4.64.1 urllib3-1.26.20 zipp-3.6.0
インストール成功🎉
GitHubのissuesをチェックすることも大切です。あなたが環境構築に苦しんでいる時、他の人も苦しんでいます。
venvでのインストール③: torch/cudaとの戦い
ようやくrequirements.txtがインストール出来たので、次のステップに進むことが出来ます。READMEによればsetup.pyを動かす必要があるとのことなので、それもやります。
(.venv) $ cd model/monotonic_align; python setup.py build_ext --inplace; cd ../..
ここで、torchが本当に動くのかをチェックしましょう:
(.venv) $ python
>>> import torch # LIBTORCHやLD_LIBRARY_PATHを設定しているとここでエラーになることもある
>>> torch.version.cuda
'10.2'
>>> torch.cuda.is_available()
True
>>> torch.Tensor([1,2,3]).cuda()
RuntimeError: CUDA error: no kernel image is available for execution on the device
エラーになりました。つらすぎる。
しかし全ての原因はtorchとcudaのバージョンを合わせるのを忘れていることです。ここではcuda 10.2が必要であると分かるので、これをインストールしましょう。
既に何らかのバージョンのcudaをインストールしているのであれば、nvidiaのaptリポジトリ及びキーは追加しているものと思われますが、もしそうでなければそこからやって下さい。
apt経由で利用できるcudaを探します:
(.venv) $ aptitude search cuda
...
i cuda - CUDA meta-package
p cuda-11-7 - CUDA 11.7 meta-package
p cuda-11-8 - CUDA 11.8 meta-package
p cuda-12-0 - CUDA 12.0 meta-package
...
Oh…どうもUbuntu22.04LTSではcuda-11-7以降しかインスコできない。
待って! あきらめるのはまだ早いよ!🤓
実はcuda 10.2以外のバージョンでも動くことがあります。requirements.txtを見るとtorch==1.9.0がインストールされていますので、これに対応するcudaのバージョンを例のサイトからエスパーしましょう。
cuda 10.2の他にcuda 11.1が使えることが分かります。cuda 11.1を使う場合はtorchをインストールし直す必要があります。
(.venv) $ pip uninstall torch
(.venv) $ pip install torch==1.9.0+cu111 -f https://download.pytorch.org/whl/torch_stable.html
cuda 11.1とcuda 11.7は互換性があるかもしれない()ということで、cuda 11.7をインストールしてみましょう:
(.venv) $ sudo aptitude install cuda-11-7
(.venv) $ update-alternatives --config cuda # インタラクティブにcuda-11.7を選択
(.venv) $ sudo reboot
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Wed_Jun__8_16:49:14_PDT_2022
Cuda compilation tools, release 11.7, V11.7.99
Build cuda_11.7.r11.7/compiler.31442593_0
update-alternativesを初めて使う方は、以下を参考に設定すると良いでしょう:
では、torchが動くかどうかを検証します:
$ source ./.venv/bin/activate
(.venv) $ python
>>> import torch
>>> torch.version.cuda
'11.1'
>>> torch.cuda.is_available()
True
>>> torch.Tensor([1,2,3]).cuda()
tensor([1., 2., 3.], device='cuda:0')
動きましたね。事前学習済みモデルをダウンロードして推論してみましょう:
(.venv) $ python inference.py -f ./resources/filelists/synthesis.txt -c ./checkpts/grad-tts.pt
Initializing Grad-TTS...
Number of parameters: 14835032
Initializing HiFi-GAN...
Removing weight norm...
Synthesizing 0 text... Grad-TTS RTF: 0.015275078755040321
Synthesizing 1 text... Grad-TTS RTF: 0.012218788207116787
Synthesizing 2 text... Grad-TTS RTF: 0.01215144739797228
Done. Check outoutfolder for samples.
スバラシイ
Dockerを使ったインストール
上記の手順ではたまたま上手く行きましたが、cuda 11.1でしか動かないものをcuda 11.7上で動かすというのが気持ち悪いし、他のケースでは上手く行かないかも知れません。なので、以下ではDockerを用いた環境構築法もご紹介します。
各種バージョンのエスパー
今回のケースでは、
- OS: Ubuntu18.04 LTS
- torch: 1.9.0
- cuda: 11.1
- numba: 0.50.0
- pillow: 6.2.0
とするのが良いでしょう。OSがUbuntu18.04 LTSなのはcuda 11.1をインストールするためです。cudaやnumba、Pillowのバージョンは、上に書いたような試行錯誤の末に得ることが出来ます。
これらに適合するnvidia/cudaイメージのタグをDocker Hubから探しましょう。11.1.1-cudnn8-runtime-ubuntu18.04が良さそうです。
イメージのpullと各種インストール
取得したイメージから、インタラクティブシェルを立ち上げます。Dockerfileを書くよりも断然楽です。
$ docker pull nvidia/cuda:11.1.1-cudnn8-runtime-ubuntu18.04
$ docker run --gpus all -it nvidia/cuda:11.1.1-cudnn8-runtime-ubuntu18.04 /bin/bash
# apt update; apt install aptitude; aptitude install curl git
# aptitude install python3.6 python3-pip
# git clone https://github.com/huawei-noah/Speech-Backbones.git
# cd SpeechBackbones/Grad-TTS/
続いてPythonパッケージをインストールします:
# pip3 install numba==0.50.0 pillow==6.2.0
# pip3 install -r requirements.txt # torchの行はコメントアウトしておくか、後でuninstallする
# pip3 install typing-extensions==4.1.1 # なんか知らないけど必要
# pip3 install torch==1.9.0+cu111 -f https://download.pytorch.org/whl/torch_stable.html
torchが使えるか否かを確認します(略)
事前学習済みモデルをdocker cpなどでコンテナ内に放り込み、推論スクリプトを動かしてみましょう:
# cd model/monotonic_align; python3.6 setup.py build_ext --inplace; cd ../..
# python3.6 inference.py -f ./resources/filelists/synthesis.txt -c ./checkpts/grad-tts.pt
Initializing Grad-TTS...
Number of parameters: 14835032
Initializing HiFi-GAN...
Removing weight norm...
Synthesizing 0 text... Grad-TTS RTF: 0.015118690146169355
Synthesizing 1 text... Grad-TTS RTF: 0.010802815066149635
Synthesizing 2 text... Grad-TTS RTF: 0.011404373476001026
Done. Check outoutfolder for samples.
動きました。このコンテナをイメージとして保存しましょう!
# exit
$ docker ps -a # コンテナのIDを調べる
$ docker commit 6e3abbee3dc2 grad-tts
$ docker images # 新しくイメージが出来たことを確認
セットアップしたコンテナを元にDockerfileを書きたくなった場合、コマンドの履歴を元に手作業で書きましょう。historyコマンドなどで今までの履歴を見ることが出来ます。
Dockerのイメージが多くなるとストレージを食うので、増設したSSD上にイメージを置いておくと良いです。増設したSSDを/nvme1n1p1/にマウントしたとすると、
$ sudo rsync -a --info=progress2 /var/lib/docker /nvme1n1p1/.docker
$ sudo rm -r /var/lib/docker
$ sudo ln -s /nvme1n1p1/.docker /var/lib/docker
といった感じでDockerイメージを全て/nvme1n1p1/.docker/上に移すことが出来ます。
まとめ
環境構築はとてもつらい。LGTMを押してください。コメントをして下さると泣いて喜びます。