You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:10:41