背景
Ubuntu
を 22.04
から 24.04
に更新して、以前作成したトレーニング済みモデルをロードしようとしたら、読み込めなくなったので、その試行錯誤と解決方法をまとめる。
動作確認環境
• LinuxOS Ubuntu 24.04.1 LTS
• Python 3.12.3
免責事項
その前に、このスクリプトの実行は自己責任でお願いします。本スクリプトを実行することにより生じるいかなる問題に関しましても、筆者は一切責任を負いません。予めご了承ください。
from tensorflow.keras.callbacks import ModelCheckpoint
でチェックポイントを登録しようとしたら失敗した。
from tensorflow.keras.callbacks import ModelCheckpoint
checkpoint = ModelCheckpoint(filepath='MODELS/model{epoch:02d}')
ValueError: The filepath provided must end in `.keras` (Keras model format). Received: filepath=MODELS/model{epoch:02d}
どうやら、Keras3から、チェックポイントの登録、モデルの保存には、 .keras
を付けなければいけなくなったようだ。
pip freeze
で keras
と tensorflow
のバージョンを調べる
(venv) % pip freeze
keras==3.5.0
tensorflow==2.17.0
確かに、 Keras
のバージョンが 3.5.0
に上がっている。
以前の Tensorflow
のバージョン 2.15.1
のインストールを試みる
(venv) % deactivate
% rm -rf venv
% python -m venv venv
% source venv/bin/activate
(venv) % pip install tensorflow==2.15.1
ERROR: Could not find a version that satisfies the requirement tensorflow==2.15.1 (from versions: 2.16.0rc0, 2.16.1, 2.16.2, 2.17.0rc0, 2.17.0rc1, 2.17.0)
ERROR: No matching distribution found for tensorflow==2.15.1
2.16.0rc0
以上でないとインストールできないようだ。
取り敢えずチェックポイントに拡張子 .keras
を付けてトレーニングしてみる
取り敢えず拡張子 .keras
付きのモデルが作成された。
checkpoint = ModelCheckpoint(filepath='MODELS/model{epoch:02d}.keras')
history = model.fit(x_train, y_train, epochs=1, batch_size=32, validation_split=0.2, callbacks=[checkpoint])
Keras3
ではトレーニング終了後 MODELS/model01.keras
という zip
形式のトレーニング済みモデルが作成されたようだ。中身を見てみる。
model01.keras
├─ config.json
├─ metadata.json
└─ model.weights.h5
Keras2
以前のトレーニング済みモデルと中身が異なっている。因みに以前のトレーニング済みモデルはこんな感じ。
model01
├+ assets
│ └─ 空
├─ keras_metadata.pb
├─ saved_model.pb
└+ variables
├─ variables.data-00000-of-00001
└─ variables.index
拡張子 .keras
をつけてロードしてみる
from tensorflow import keras
model = keras.models.load_model('MODELS/model01.keras')
TypeError: Could not locate class 'Bias'. Make sure custom classes are decorated with `@keras.saving.register_keras_serializable()`.
During handling of the above exception, another exception occurred:
TypeError: <class 'keras.src.models.sequential.Sequential'> could not be deserialized properly. Please ensure that components that are Python object instances (layers, models, etc.) returned by `get_config()` are explicitly deserialized in the model's `from_config()` method.
カスタムクラス Bias
が配置されていないというエラー。
もう一つが、 get_config()
で返されたコンポーネントが from_config()
で逆シリアライズ化されていないというエラー。
カスタムクラスが配置されていないということなので、トレーニング済みモデルをロードする前にモデルを定義・コンパイルする
from tensorflow import keras
from tensorflow.keras import layers
class Bias(keras.layers.Layer):
# 省略
model = keras.Sequential()
model.add(Bias(""" 省略 """))
model.compile(""" 省略 """)
コンパイルしたモデルに、チェックポイントで保存したウェイトをロードする
import shutil
shutil.unpack_archive('MODELS/model01.keras', 'MODELS/model01')
shutil.ReadError: Unknown archive format 'MODELS/model01.keras'
shutil.unpack_archive
では、拡張子 zip
以外のファイルを解凍できないようだ。
zipfile.ZipFile
に変更してみる。
import zipfile
with zipfile.ZipFile('MODELS/model01.keras') as zf:
zf.extractall('MODELS/model01')
無事に MODELS
フォルダの下に model01
フォルダが作成され、その配下にモデルデータが解凍された。
MODELS
└+ model01
├─ config.json
├─ metadata.json
└─ model.weights.h5
zf.extractall
の解凍先を MODELS
にすると MODELS
フォルダの直下に、 config.json
、 metadata.json
、 model.weights.h5
が解凍されてしまう。
with zipfile.ZipFile('MODELS/model01.keras') as zf:
zf.extractall('MODELS')
MODELS
├─ config.json
├─ metadata.json
└─ model.weights.h5
モデルが複数個存在する場合、上書きされてしまうので、モデル毎に別フォルダで管理するのが無難。
解凍が終わったら、 model.weights.h5
のウェイトをロードして、モデルのフォルダ毎削除。
import shutil
model.load_weights('MODELS/model01/model.weights.h5')
shutil.rmtree('MODELS/model01')
別にモデルのフォルダを削除する必要はないが、 MODELS/model01.keras
があるので、 MODELS/model01
を置いておく必要はない。
MODELS
フォルダの直下に解凍しても良いが、後始末が面倒なので、モデル毎のフォルダを作成し、そのフォルダ毎削除するのが無難。
余談、ウェイトをロードして生成した Keras3
形式のモデルから、 Keras2
形式のモデルを生成できる
model.export('MODELS/model01')
トレーニング済みウェイトをロードして生成した Keras3
形式のモデルから model.export
を使用すると、 Keras2
形式のモデルを生成できるが、 Keras2
形式のモデルを生成したところで、 Keras3
では使い道がない。
ロードしたウェイトでトレーニング
checkpoint = ModelCheckpoint(filepath='MODELS/model{epoch:02d}.keras')
history = model.fit(x_train, y_train, initial_epoch=1, epochs=2, batch_size=32, validation_split=0.2, callbacks=[checkpoint]
チェックポイントを定義し、無事に途中からでもトレーニングに成功。チェックポイントを定義していることで、 Keras3
形式のトレーニング済みウェイトが生成される。
Keras2 と Keras3の比較
• トレーニング済みモデルをロードする時 Keras2
では、 keras.models.load_model
でモデルをロードできていたが、 Keras3
ではトレーニング済みモデルをロードできなくなった。 Keras3
でもトレーニング済みモデルをロードできるかもしれないが、その方法がわからない。
• 代わりに Keras3
では、モデルを再定義・コンパイルし、そのモデルにトレーニング済みウェイトをロード load_weights('モデルのパス/model.weights.h5')
することで、トレーニング済みモデルを生成するような感じになっている。
• Keras2
では、トレーニングを途中から再開する際、トレーニング済みモデルを読み込めば、トレーニングを途中から再開できたが、 Keras3
では、トレーニングを途中から再開する場合は、毎回モデルの定義・コンパイルを行い、そのモデルにトレーニング済みウェイトを読み込まなければならない。
最後に
今回 Ubuntu
の最新 LTS
版がリリースされてから約半年が経ち、 22.04
から 24.04
に更新してみたところ、以前 Tensorflow
でトレーニングしたトレーニング済みモデルが読み込めないという問題に遭遇しました。
長年ソフトウェア開発に身を置いていますが、 Keras
に限らずモジュールが更新されると今まで動いていたモジュールが使えなくなるということがよくあります。ソフトウェア開発をする上で、この問題は永遠のテーマと言えます。
こういう問題に遭遇すると、問題解決のために、あっという間に時間が過ぎてしまいます。何とかしてもらいたいところです。
最後まで、この記事を読んでいただき、ありがとうございました。