我想编写一个自定义层,将密集层和一些指定函数应用于该计算的输出.我想指定应用于列表中各个输出的函数,这样我就可以轻松地更改它们.

我试图在tf.while_loop中应用函数,但我不知道如何访问和写入dense_output_nodes的各个元素.

dense_output_nodes[i] = ...不能像它告诉我的那样起作用

TypeError:"Tensor"对象不支持项分配

所以我之前try 过tf.unstack,这是下面的代码,但是现在当用hidden_1 = ArithmeticLayer(unit_types=['id', 'sin', 'cos'])(inputs)创建图层时,我得到了一个错误:

类型错误:列表索引必须是整数或切片,而不是张量

因为显然TensorFlow将itf.constant转换为tf.Tensor.

到现在为止,我真的很难找到解决这个问题的方法.有什么办法可以让它发挥作用吗?

class ArithmeticLayer(layers.Layer):
    # u = number of units
    
    def __init__(self, name=None, regularizer=None, unit_types=['id', 'sin', 'cos']):
        self.regularizer=regularizer
        super().__init__(name=name)
        self.u = len(unit_types)
        self.u_types = unit_types

    def build(self, input_shape):
        self.w = self.add_weight(shape=(input_shape[-1], self.u),
                                 initializer='random_normal',
                                 regularizer=self.regularizer,
                                 trainable=True)
        self.b = self.add_weight(shape=(self.u,),
                                 initializer='random_normal',
                                 regularizer=self.regularizer,
                                 trainable=True)


    def call(self, inputs):
        # get the output nodes of the dense layer as a list
        dense_output_nodes = tf.matmul(inputs, self.w) + self.b
        dense_output_list = tf.unstack(dense_output_nodes, axis=1)
        
        # apply the function units
        i = tf.constant(0)
        def c(i):
            return tf.less(i, self.u)
        def b(i):
            dense_output_list[i] = tf.cond(self.u_types[i] == 'sin',
                                            lambda: tf.math.sin(dense_output_list[i]),
                                            lambda: dense_output_list[i]
                                           )
            dense_output_list[i] = tf.cond(self.u_types[i] == 'cos',
                                            lambda: tf.math.cos(dense_output_list[i]),
                                            lambda: dense_output_list[i]
                                           )
            return (tf.add(i, 1), )
        [i] = tf.while_loop(c, b, [i])
        
        final_output_nodes = tf.stack(dense_output_list, axis=1)
        return final_output_nodes

谢谢你的建议!

推荐答案

如果您想在批处理的样本中按列应用某些函数,那么使用tf.tensor_scatter_nd_update应该可以做到这一点.下面是一个在Eager 执行和图形模式下工作的示例:

import tensorflow as tf

class ArithmeticLayer(tf.keras.layers.Layer):
    # u = number of units
    
    def __init__(self, name=None, regularizer=None, unit_types=['id', 'sin', 'cos']):
        self.regularizer=regularizer
        super().__init__(name=name)
        self.u_types = tf.constant(unit_types)
        self.u_shape = tf.shape(self.u_types)

    def build(self, input_shape):
        self.w = self.add_weight(shape=(input_shape[-1], self.u_shape[0]),
                                 initializer='random_normal',
                                 regularizer=self.regularizer,
                                 trainable=True)
        self.b = self.add_weight(shape=(self.u_shape[0],),
                                 initializer='random_normal',
                                 regularizer=self.regularizer,
                                 trainable=True)

    def call(self, inputs):
        dense_output_nodes = tf.matmul(inputs, self.w) + self.b
        d_shape = tf.shape(dense_output_nodes)
        i = tf.constant(0)
        c = lambda i, d: tf.less(i, self.u_shape[0])

        def b(i, d):
          d = tf.cond(unit_types[i] == 'sin', 
                lambda: tf.tensor_scatter_nd_update(d, tf.stack([tf.range(d_shape[0]), tf.repeat([i], d_shape[0])], axis=1), tf.math.sin(d[:, i])), 
                lambda: d)
          d = tf.cond(unit_types[i] == 'cos', 
                lambda: tf.tensor_scatter_nd_update(d, tf.stack([tf.range(d_shape[0]), tf.repeat([i], d_shape[0])], axis=1), tf.math.cos(d[:, i])), 
                lambda: d)
          return tf.add(i, 1), d
        _, dense_output_nodes = tf.while_loop(c, b, loop_vars=[i, dense_output_nodes])

        return dense_output_nodes
x = tf.random.normal((4, 3))
inputs = tf.keras.layers.Input((3,))
arithmetic = ArithmeticLayer()
outputs = arithmetic(inputs)
model = tf.keras.Model(inputs, outputs)
model.compile(optimizer='adam', loss='mse')
model.fit(x, tf.random.normal((4, 3)), batch_size=2)
2/2 [==============================] - 3s 11ms/step - loss: 1.4259
<keras.callbacks.History at 0x7fe50728c850>

Python相关问答推荐

Python:MultiIndex Dataframe到类似json的字典列表

在Python中,什么表达相当于0x1.0p-53?

"如果发生特定错误,返回值

Python:记录而不是在文件中写入询问在多文件项目中记录的最佳实践

为什么dict(id=1,**{id:2})有时会引发KeyMessage:id而不是TypMessage?

Google Drive API获取文件计量数据

如何根据情况丢弃大Pandas 的前n行,使大Pandas 的其余部分完好无损

Python中是否有方法从公共域检索搜索结果

将HTML输出转换为表格中的问题

Class_weight参数不影响RandomForestClassifier不平衡数据集中的结果

Pandas 填充条件是另一列

根据条件将新值添加到下面的行或下面新创建的行中

删除所有列值,但判断是否存在任何二元组

删除字符串中第一次出现单词后的所有内容

Pandas:将多级列名改为一级

利用Selenium和Beautiful Soup实现Web抓取JavaScript表

使用Python更新字典中的值

调用decorator返回原始函数的输出

什么是合并两个embrame的最佳方法,其中一个有日期范围,另一个有日期没有任何共享列?

如何获取Python synsets列表的第一个内容?