こんにちは、ピリカ開発チームの九鬼(niccari)です。
機械学習周りで物体検出したいとき、TensorFlowとともにObject Detection APIを利用することがあります。
Object Detection API側のアップデートで新規Docker環境が動かなくなったことがありました。
TL; DR
tensorflowおよびtensorflow関連ライブラリでバージョンを揃えればOKです。以下どちらかを行います。
- ベースとなるimageで最新のTensorFlow (GPU)バージョンのimageを使用する
- (workaround) Dockerfile内で同一バージョンのtensorflow, tensorflow-text, tf-models-officialをインストールする
- TensorFlow 2.4.0未満の場合、Object Detection APIの特定コミットをチェックアウトする
検証環境
- Ubuntu 20.04 LTS(カーネル: 5.4.0-81-generic)
- Docker version 19.03.13
- Dockerfile: Object Detection API公式で提供されているDockerfileから、ベースとなるimageを
tensorflow/tensorflow:2.4.0-gpu
に変更したもの
発生した問題
Object Detection API学習用のDockerコンテナを作って、model_main_tf2.pyで学習をかけました。すると、tensorflow-textのライブラリ部分で参照エラーが発生しクラッシュしました。
tensorflow.python.framework.errors_impl.NotFoundError: /usr/local/lib/python3.6/dist-packages/tensorflow_text/python/metrics/_text_similarity_metric_ops.so: undefined symbol: _ZN10tensorflow8OpKernel11TraceStringEPNS_15OpKernelContextEb
このエラーが出る理由は、tensorflow関連ライブラリ間でバージョンが一致していないためです。バージョンが異なると、tensorflow関連ライブラリのバイナリ間で差異が出ます。そのため、一部シンボルを読み出せなくなる可能性があります。
なぜバージョンが一致しなくなるかですが、Object Detection API(object_detectionライブラリ)のインストール時、常に最新のtensorflowライブラリをインストールしてしまうためです。これにより、2つのバージョンのtensorflowライブラリがインストールされてしまい、整合性が取れなくなります(詳しい理由については付記を参照ください)。
対策
tensorflowライブラリとその関連ライブラリのバージョンを合わせればよいので、以下のどちらかで解消されます。
- ベースとなるimageで最新のTensorFlow (GPU)バージョンのimageを使用する
- Dockerfile内で同一バージョンのtensorflow, tensorflow-text, tf-models-officialをインストールする
- TensorFlow 2.4.0未満の場合、Object Detection APIの特定コミットをチェックアウトする
1.ベースとなるimageで最新のTensorFlow (GPU)バージョンのimageを使用する
DockerfileでベースにしているTensorFlow (GPU)を最新版に変更します。
2021.09.23現在、2.6.0が最新です。そこで、Dockerfileを以下の通り書き換えます(適宜、最新のバージョンに読み替えてください)。
- FROM tensorflow/tensorflow:2.2.0-gpu + FROM tensorflow/tensorflow:2.6.0-gpu
2. (workaround) Dockerfile内で同一バージョンのtensorflow, tensorflow-text, tf-models-officialをインストールする
学習環境側で制約があり、どうしてもTensorFlowのバージョンを特定のバージョンに揃えたい場合があります。
その場合、Dockerfileを以下のように書き換えます。
※ TensorFlow 2.5.0をNVIDIA GPUと共に使いたい場合
FROM tensorflow/tensorflow:2.5.0-gpu ARG DEBIAN_FRONTEND=noninteractive # Install apt dependencies RUN apt-get update && apt-get install -y \ git \ gpg-agent \ python3-cairocffi \ protobuf-compiler \ python3-pil \ python3-lxml \ python3-tk \ wget # Add new user to avoid running as root RUN useradd -ms /bin/bash tensorflow USER tensorflow WORKDIR /home/tensorflow # Clone Object Detection API RUN git clone https://github.com/tensorflow/models/ /home/tensorflow/models/ # Workaround: If you use TF 2.2.x, uncomment the line below. # WORKDIR /home/tensorflow/models/ # RUN git checkout 03a6d6c8e79b426231a4d5ba0cf45be9afc8bad5 # Workaround: If you use TF 2.3.x, uncomment the line below. # WORKDIR /home/tensorflow/models/ # RUN git checkout cf82a72480a41a62b4bbe0f1378d319f0d6f5d5c # Compile protobuf configs RUN (cd /home/tensorflow/models/research/ && protoc object_detection/protos/*.proto --python_out=.) WORKDIR /home/tensorflow/models/research/ RUN cp object_detection/packages/tf2/setup.py ./ ENV PATH="/home/tensorflow/.local/bin:${PATH}" # Workaround (For Tensorflow < 2.5.1): Remove tf-models-official dependency from object_detection, will install it manually. RUN sed -i -e 's/^.*tf-models-official.*$//g' ./setup.py RUN python -m pip install -U pip # Workaround: Lock tensorflow and corresponding tf-models-official versions. RUN python -m pip install tensorflow==2.5.0 tensorflow-text==2.5.0 tf-models-official==2.5.0 RUN python -m pip install . ENV TF_CPP_MIN_LOG_LEVEL 3
変更点1. 使いたいバージョンのtensorflow、および対応するtensorflow-textとtf-models-official(学習済みモデル利用のためのライブラリ)を手動でインストールします。なお、tensorflow/tensorflow:x.x.x-gpuをベースimageとして使う場合、初期状態でtensorflowライブラリは入っていないため、特定バージョンのTensorFlowを指定する必要があります。
RUN python -m pip install -U pip + + # Workaround: install tensorflow and corresponding tf-models-official versions. + RUN python -m pip install tensorflow==2.5.0 tensorflow-text==2.5.0 tf-models-official==2.5.0 RUN python -m pip install . ENV TF_CPP_MIN_LOG_LEVEL 3
変更点2. (使いたいTensorFlowのバージョンが2.5.1未満の場合) object_detectionライブラリの依存関係から、tf-models-officialを削除してください(その代わりに、変更点1でtensorflowに対応したバージョンのtf-models-officialをインストールしています)。
ENV PATH="/home/tensorflow/.local/bin:${PATH}" + # Workaround (For tensorflow < 2.5.1): Remove tf-models-official dependency from object_detection, will install it manually. + RUN sed -i -e 's/^.*tf-models-official.*$//g' ./setup.py RUN python -m pip install -U pip
最新のobject_detectionライブラリのsetup.pyでは、tf-models-official>=2.5.1に依存関係に指定されています。そのため、それ以前のtf-models-officialを依存関係を含めるために上記変更が必要です(object_detectionライブラリはバージョニング未対応で、過去のリリースバージョンを特定することが難しいことが理由です)。
変更点3. (使いたいTensorFlowのバージョンが2.4.0未満の場合) インストールに使うobject_detectionのソースコードについて、古いコミットを指定します。最新のobject_detectionライブラリでは、tf-models-officialの2.4.0未満に対応していないため実行時エラーになります*1。
以下の部分について、TensorFlow 2.2.xを使う場合は上の2行、2.3.xを使う場合は下の2行をコメントアウトしてください。
TensorFlow 2.2.xの場合
+ + # Workaround: If you use TF 2.2.x, uncomment the line below. + WORKDIR /home/tensorflow/models/ + RUN git checkout 03a6d6c8e79b426231a4d5ba0cf45be9afc8bad5
TensorFlow 2.3.xの場合
+ + # Workaround: If you use TF 2.3.x, uncomment the line below. + WORKDIR /home/tensorflow/models/ + RUN git checkout cf82a72480a41a62b4bbe0f1378d319f0d6f5d5c
以上の変更により、使いたいバージョンのTensorFlowのみがインストールされ、学習が可能になります。
付記: なぜObject Detection APIで最新のTensorFlowライブラリがインストールされてしまうのか?
object_detectionライブラリは、setup.py上でtf-models-officialライブラリ(学習済みモデルを使うためのライブラリ)を依存関係に持ちます。
REQUIRED_PACKAGES = [
...,
'tf-models-official>=2.5.1',
]
tf-models-officialライブラリのsetup.pyを見てみると、
... if project_name == 'tf-models-nightly': version += '.dev' + datetime.datetime.now().strftime('%Y%m%d') install_requires.append('tf-nightly') install_requires.append('tensorflow-text-nightly') else: install_requires.append('tensorflow>=2.4.0') install_requires.append('tensorflow-text>=2.4.0') ...
となっていて、特定バージョン*2以上のtensorflow, tensorflow-textライブラリを依存関係を持ちます。そのため、すでにtensorflowライブラリをインストールしていても最新のバージョンがインストールされます。
一方で、tensorflow-gpuは自動的にアップデートされません。そのため、前述の通りtensorflowとバージョンが不整合になり得ます。
参考: どうすればこの問題が起こらないか?
ライブラリ側で以下の2点が対応されれば、本問題は解消されます。また、TensorFlow 2.4.0未満でObject Detection APIが実行時エラー問題も解消されます。
- object_detectionライブラリがtf-models-officialライブラリ同様にTensorFlowのバージョンに揃えてバージョニングされている
- 例えば、TensorFlow 2.4.0に対し、tf-models-officialとobject_detectionのバージョンがともに2.4.0になる
- tf-models-officialが特定のTensorFlowのバージョンに依存関係が固定されている
- 例えば、TensorFlow 2.4.0に対し、tensorflow==2.4.0, tensorflow-text==2.4.0が依存関係で固定されている
参考ページ
公式GitHub issue #9911: Dockerfile installs two tensorflow versions when building
以上、ご覧いただきありがとうございました!