wide and deep

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})


試行錯誤で対処したので間違っているかもしれないが,参考になる情報が転がっていなかったのでここに残しておく.