Tensorflow Keras:一层中的多激活函数

vfhzx4xs  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(178)

我试图建立一个自定义keras.layer.layer可以与keras.models.sequential一起工作,但在一个层中有多个激活函数。
我尝试使用多个密集层来构建这个,每个层在不同数量的单元上使用不同的激活函数。例如,如果我想构建一个有8个单元的层,并在其中一半上使用“relu”,在另一半上使用“linear”,我的想法是简单地合并两个Dense层的输出。
下面是我正在创建的类:

class Multi_Activation_Layer(tf.keras.layers.Layer):

    def __init__(self, units, activations = None, **kwargs):
        self.units = units
        self.activations = activations
        num_fns = len(self.activations)
        remainder = units % num_fns
        adj_units = units - remainder
        units_per_fn = adj_units / num_fns
        self.activations_dict = {activations[-1]: {"Units": units_per_fn + remainder}}

        for fn in self.activations[:-1]:
            self.activations_dict[fn] = {"Units": units_per_fn}

        super(Multi_Activation_Layer, self).__init__(**kwargs)

    def build(self, input_shape):
        
        for activation, dict in self.activations_dict.items():
            dense = tf.keras.layers.Dense(units = dict["Units"], activation = activation)
            dense.build(input_shape)
            self.activations_dict[activation][f"Dense"] = dense

    def call(self, input_data):
        output_data_list = []

        for dict in self.activations_dict.values():
            output = dict["Dense"].call(input_data)
            output_data_list.append(output)

        output_data = tf.concat(output_data_list, axis = 0)
        return output_data
    
    def compute_output_shape(self, input_shape): 
        return (input_shape[0], self.units)

然后我将其添加到一个非常简单的Sequential模型中:

model = tf.keras.models.Sequential([
    Multi_Activation_Layer(8, activations = ["relu", "linear"]),
    tf.keras.layers.Dense(1, activation = "linear")
])

loss_fn = tf.keras.losses.MeanAbsolutePercentageError()

adm_opt = tf.keras.optimizers.Adam(learning_rate = 0.001)

model.compile(
    optimizer = adm_opt,
    loss = loss_fn,
    metrics = [tf.keras.metrics.MeanSquaredError(name = "mse"), tf.keras.metrics.MeanAbsoluteError(name = "mae")]
)

最后,我尝试了一下我的模型:

model.fit(Xt_train, y_train, epochs = 50)

然而,我得到了一个错误,我无法解决:

TypeError                                 Traceback (most recent call last)
c:\Users\XXXXXXX\Documents\XXXXXX\XXXXXXX\XXXXXX\XXXXXXX\XXXXXXX\XXXXXXX Data Preparation.ipynb Cell 225 in ()
----> 1 model.fit(Xt_train, y_train, epochs = 50)

File ~\AppData\Roaming\Python\Python39\site-packages\keras\src\utils\traceback_utils.py:70, in filter_traceback..error_handler(*args, **kwargs)
     67     filtered_tb = _process_traceback_frames(e.__traceback__)
     68     # To get the full stack trace, call:
     69     # `tf.debugging.disable_traceback_filtering()`
---> 70     raise e.with_traceback(filtered_tb) from None
     71 finally:
     72     del filtered_tb

File ~\AppData\Local\Temp\__autograph_generated_fileheb_wsb5.py:15, in outer_factory..inner_factory..tf__train_function(iterator)
     13 try:
     14     do_return = True
---> 15     retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope)
     16 except:
     17     do_return = False

File ~\AppData\Local\Temp\__autograph_generated_filedzpps6u7.py:27, in outer_factory..inner_factory..tf__call(self, input_data)
     25 dict = ag__.Undefined('dict')
     26 ag__.for_stmt(ag__.converted_call(ag__.ld(self).activations_dict.values, (), None, fscope), None, loop_body, get_state, set_state, ('dict',), {'iterate_names': 'dict'})
---> 27 output_data = ag__.converted_call(ag__.ld(tf).concat, (ag__.ld(output_data_list),), dict(axis=1), fscope)
     28 try:
     29     do_return = True

TypeError: in user code:

    File "C:\Users\XXXXXX\AppData\Roaming\Python\Python39\site-packages\keras\src\engine\training.py", line 1338, in train_function  *
        return step_function(self, iterator)
    File "C:\Users\XXXXXXX\AppData\Roaming\Python\Python39\site-packages\keras\src\engine\training.py", line 1322, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "C:\Users\XXXXXX\AppData\Roaming\Python\Python39\site-packages\keras\src\engine\training.py", line 1303, in run_step  **
        outputs = model.train_step(data)
    File "C:\Users\XXXXXXX\AppData\Roaming\Python\Python39\site-packages\keras\src\engine\training.py", line 1080, in train_step
        y_pred = self(x, training=True)
    File "C:\Users\XXXXXXXX\AppData\Roaming\Python\Python39\site-packages\keras\src\utils\traceback_utils.py", line 70, in error_handler
        raise e.with_traceback(filtered_tb) from None
    File "C:\Users\XXXXXXXX\AppData\Local\Temp\__autograph_generated_filedzpps6u7.py", line 27, in tf__call
        output_data = ag__.converted_call(ag__.ld(tf).concat, (ag__.ld(output_data_list),), dict(axis=1), fscope)

    TypeError: Exception encountered when calling layer 'multi__activation__layer_1' (type Multi_Activation_Layer).
    
    in user code:
    
        File "C:\Users\XXXXXXX\AppData\Local\Temp\ipykernel_19304\3036281980.py", line 42, in call  *
            output_data = tf.concat(output_data_list, axis = 1)
    
        TypeError: '_DictWrapper' object is not callable
    
    
    Call arguments received by layer 'multi__activation__layer_1' (type Multi_Activation_Layer):
      • input_data=tf.Tensor(shape=(None, 37), dtype=float32)

有人能帮忙吗?

dgjrabp2

dgjrabp21#

感谢Dr.史努比解决了这个问题。这个问题只是因为我使用了“dict”作为变量名。“axis = 1”是正确的,因为我尝试了“axis = 0”,这导致了形状错误。固定代码见下文:

class Multi_Activation_Layer(tf.keras.layers.Layer):

def __init__(self, units: int, activations: list = None, **kwargs):
    self.units = units
    self.activations = activations
    num_fns = len(self.activations)
    remainder = units % num_fns
    adj_units = units - remainder
    units_per_fn = adj_units / num_fns
    self.activations_data = {activations[-1]: {"Units": units_per_fn + remainder}}

    for fn in self.activations[:-1]:
        self.activations_data[fn] = {"Units": units_per_fn}

    super(Multi_Activation_Layer, self).__init__(**kwargs)

def build(self, input_shape):
    
    for activation, data in self.activations_data.items():
        dense = tf.keras.layers.Dense(units = data["Units"], activation = activation)
        dense.build(input_shape)
        self.activations_data[activation]["Dense"] = dense

def call(self, input_data):
    output_data_list = []

    for data in self.activations_data.values():
        output = data["Dense"].call(input_data)
        output_data_list.append(output)

    output_data = tf.concat(output_data_list, axis = 1)
    return output_data

def compute_output_shape(self, input_shape): 
    return (input_shape[0], self.units)

这个类将使用tensorflow.keras.models.Sequential()

相关问题