创建Keras自定义PINNNetwork模型第二个实例时触发TypeError错误
解决Keras自定义PINN模型二次实例化报错问题
问题描述
自定义了继承keras.Model的PINNNetwork类用于构建物理信息神经网络(PINN),首次实例化模型时一切正常,但第二次实例化时抛出如下错误:
TypeError: Functional.__init__() missing 2 required positional arguments: 'inputs' and 'outputs'
已知移除最后一次super().__init__调用可解决报错,但会导致模型图无法构建,无法使用summary()和plot_model()功能。需要找到既能解决报错又保留模型图功能的方案。
原模型代码:
import keras from keras.layers import Dense, Concatenate class PINNNetwork(keras.Model): def __init__(self, inputs=2, hidden_layers=[8,16,16,512], output=1, activation='tanh', w_initializer='he_normal', b_initializer='zeros', **kwargs ): super(PINNNetwork, self).__init__(**kwargs) self.model_input = None self.model_hidden = [] self.concat = [] self.model_output = None self.model_input = keras.Input(shape=(inputs,)) for layer_size in hidden_layers: self.model_hidden.append( Dense(layer_size, activation=activation, kernel_initializer=w_initializer, bias_initializer=b_initializer) ) self.concat.append(keras.layers.Concatenate()) self.model_output = Dense(output) self.inputs = self.model_input self.outputs = self.call(self.model_input) super(PINNNetwork, self).__init__( inputs = self.inputs, outputs = self.outputs, **kwargs ) def call(self, inputs, training=None, mask=None): Z = inputs for layer, concat in zip(self.model_hidden, self.concat): Z_ = layer(Z) Z = concat([Z_, Z]) return self.model_output(Z)
测试代码:
network = PINNNetwork() print("Network 1: ", network) network2 = PINNNetwork() print("Network 2: ", network2)
报错信息:
Network 1: <__main__.PINNNetwork object at 0x000001F6AE5C8AF0> --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[3], line 4 1 network = PINNNetwork() 2 print("Network 1: ", network) ----> 4 network2 = PINNNetwork() 5 print("Network 2: ", network2) Cell In[2], line 11, in PINNNetwork.__init__(self, inputs, hidden_layers, output, activation, w_initializer, b_initializer, **kwargs) 2 def __init__(self, 3 inputs=2, 4 hidden_layers=[8,16,16,512], (...) 8 **kwargs 9 ): ---> 11 super(PINNNetwork, self).__init__(**kwargs) 13 self.model_input = None 14 self.model_hidden = [] File ~\anaconda3\lib\site-packages\tensorflow\python\trackable\base.py:205, in no_automatic_dependency_tracking.<locals>._method_wrapper(self, *args, **kwargs) 203 self._self_setattr_tracking = False # pylint: disable=protected-access 204 try: ---> 205 result = method(self, *args, **kwargs) 206 finally: 207 self._self_setattr_tracking = previous_value # pylint: disable=protected-access TypeError: Functional.__init__() missing 2 required positional arguments: 'inputs' and 'outputs'
错误原因
第一次实例化时,首次调用super().__init__(**kwargs)会将模型初始化为普通的keras.Model实例;之后第二次调用super().__init__(inputs=..., outputs=...)会将其转换为Functional模型。但Keras内部的元类机制会修改类的继承关系,第二次实例化时,首次调用super().__init__(**kwargs)会直接尝试初始化Functional模型,而此时还未传入inputs和outputs参数,因此触发报错。
解决方案
核心是仅调用一次父类构造函数,在构建好模型的输入输出后,直接以Functional模型的方式初始化父类。修正后的代码如下:
import keras from keras.layers import Dense, Concatenate class PINNNetwork(keras.Model): def __init__(self, inputs=2, hidden_layers=[8,16,16,512], output=1, activation='tanh', w_initializer='he_normal', b_initializer='zeros', **kwargs ): # 移除第一次super调用,先构建模型结构 self.model_input = keras.Input(shape=(inputs,)) self.model_hidden = [] self.concat = [] for layer_size in hidden_layers: self.model_hidden.append( Dense(layer_size, activation=activation, kernel_initializer=w_initializer, bias_initializer=b_initializer) ) self.concat.append(Concatenate()) self.model_output = Dense(output) # 构建模型输出 self.outputs = self.call(self.model_input) # 仅调用一次父类构造函数,传入inputs和outputs super().__init__( inputs=self.model_input, outputs=self.outputs, **kwargs ) def call(self, inputs, training=None, mask=None): Z = inputs for layer, concat in zip(self.model_hidden, self.concat): Z_ = layer(Z) Z = concat([Z_, Z]) return self.model_output(Z)
验证效果
运行测试代码,两次实例化均正常,且可正常使用模型结构相关功能:
network = PINNNetwork() print("Network 1: ", network) network.summary() # 正常输出模型结构 network2 = PINNNetwork() print("Network 2: ", network2) network2.summary() # 正常输出模型结构
内容的提问来源于stack exchange,提问作者William Hideki Nakata
相关产品推荐
相关产品推荐

