kerasで自作レイヤーを含むモデルをload_modelするときのエラー処理
エラーと原因
- 自作レイヤーを読み込む際に,初期定義された重みの形状とは異なることに関するエラー.
ValueError: Layer #0 (named "custom_conv" in the current model) was found to correspond to layer custom_conv in the save file. However the new layer custom_conv expects 3 weights, but the saved weights have 4 elements.
tensorflow.python.framework.errors_impl.InvalidArgumentError: Dimension 3 in both shapes must be equal, but are 16 and 1. Shapes are [3,3,3,16] and [3,3,3,1]. for 'Assign_64' (op: 'Assign') with input shapes: [3,3,3,16], [3,3,3,1].
- 原因の箇所
モデルの学習自体は下記CuntomConvレイヤーにおいてoutput_chs=[16,16,16,16]
で実行した.
保存されたモデルのCuntomConvが持つ重みと自作レイヤーCuntomConvが初期状態で持つ重みの形状が異なることが原因だと思う.
# conv2Dを並列に複数行いconcatするようなレイヤー # output_chsで各convの出力チャンネル数を指定している class CuntomConv(Layer): def __init__(self, kernel_initializer='he_normal', output_chs=[1,1,1,1], kernel_regularizer=None, kernel_constraint=None, **kwargs): ... pretrained_model = load_model(pretrained_model_path, compile=False, custom_objects={'CuntomConv': CuntomConv})
解決策
custom_objectsに与える自作レイヤーの初期重み形状を,保存したモデルの自作レイヤーと同じものにする.
具体的には,自作レイヤーを継承しoutput_chs
を変更したレイヤーを作成し,custom_objectsに与える.
output_chs = [16,16,16,16] class _CunsomConv(CunsomConv): def __init__(self, kernel_initializer='he_normal', output_chs=output_chs, kernel_regularizer=None, kernel_constraint=None, **kwargs): super().__init__(kernel_initializer='he_normal', output_chs=output_chs, kernel_regularizer=None, kernel_constraint=None, **kwargs) pretrained_model = load_model(pretrained_model_path, compile=False, custom_objects={'CunsomConv': _CunsomConv})
試行錯誤で対処したので間違っているかもしれないが,参考になる情報が転がっていなかったのでここに残しておく.