web-dev-qa-db-ja.com

ValueError:不明なレイヤー:CapsuleLayer

CapsuleLayerという名前のカスタムレイヤーを定義しました。実際のモデルは別のクラスで定義されています。重みを実際のモデルにロードし、モデルを_.h5_ファイルに保存しました。しかし、load_model(filepath)を使用してモデルをロードしようとすると、エラーが発生します

ValueError:不明なレイヤー:CapsuleLayer

保存したモデルの読み込み中に、カスタムレイヤーをモデルに組み込むにはどうすればよいですか。

7
Sounak Ray

C.f. Keras FAQ、 "保存されたモデルでのカスタムレイヤー(または他のカスタムオブジェクト)の処理"

ロードするモデルにカスタムレイヤーまたは他のカスタムクラスまたは関数が含まれている場合は、custom_objects引数を介してそれらをロードメカニズムに渡すことができます。

_from keras.models import load_model
# Assuming your model includes instance of an "AttentionLayer" class
model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
_

または、カスタムオブジェクトスコープを使用できます。

_from keras.utils import CustomObjectScope

with CustomObjectScope({'AttentionLayer': AttentionLayer}):
    model = load_model('my_model.h5')
_

カスタムオブジェクトの処理は、load_model、model_from_json、model_from_yamlと同じように機能します。

_from keras.models import model_from_json
model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})
_

あなたの場合、model = load_model('my_model.h5', custom_objects={'CapsuleLayer': CapsuleLayer})が問題を解決するはずです。

9
benjaminplanche

完全を期すために、ベンジャミンプランシェの答えに少しだけ加えます。カスタムレイヤーAttentionLayerにその動作を構成する初期パラメーターがある場合は、クラスのget_configメソッドを実装する必要があります。そうしないと、ロードに失敗します。これを書いているのは、引数付きのカスタムレイヤーをロードする方法に多くの問題があったため、ここに残します。

たとえば、レイヤーのダミー実装:

class AttentionLayer(Layer):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def build(self, input_shape):
        return super().build(input_shape)

    def call(self, x):
        # Implementation about how to look with attention!
        return x

    def compute_output_shape(self, input_shape):
        return input_shape

これは、ベンジャミンプランシェの回答で詳述されているアプローチのいずれか、つまりcustom_objects={'AttentionLayer': AttentionLayer}を使用して読み込まれます。ただし、レイヤーに引数がある場合、読み込みは失敗します。

クラスのinitメソッドに2つのパラメーターがあるとします。

class AttentionLayer(Layer):
    def __init__(self, param1, param2, **kwargs):
        self.param1 = param1
        self.param2 = param2
        super().__init__(**kwargs)

次に、それをロードすると:

model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})

このエラーがスローされます:

Traceback (most recent call last):
  File "/path/to/file/cstm_layer.py", line 62, in <module>
    h = AttentionLayer()(x)
TypeError: __init__() missing 2 required positional arguments: 'param1' and 'param2'

これを解決するには、カスタムレイヤークラスにget_configメソッドを実装する必要があります。例:

class AttentionLayer(Layer):
    def __init__(self, param1, param2, **kwargs):
        self.param1 = param1
        self.param2 = param2
        super().__init__(**kwargs)

    # ...

    def get_config(self):
        # For serialization with 'custom_objects'
        config = super().get_config()
        config['idx_init'] = self.idx_init
        config['idx_end'] = self.idx_end
        return config

そのため、モデルを保存すると、保存ルーチンはget_configを呼び出し、カスタムレイヤーの内部状態、つまりself.paramsをシリアル化します。ロードすると、ローダーはカスタムレイヤーの内部状態を初期化する方法を認識します。

0
JVGD