我正在尝试实现一个特定的自定义层。然而,当我运行它时,一切正常,没有任何错误,但在编译和拟合后却没有“训练”。也就是说,输出的结果和输入的相同…
class Reconfiguration_unit(K.layers.Layer): def __init__(self, *args, **kwargs): super(Reconfiguration_unit, self).__init__(*args, **kwargs) def build(self, input_shape): self.weight = self.add_weight(shape=[input_shape[1],input_shape[1]], initializer='zeros', trainable=True) self.bias = self.add_weight(shape=[input_shape[1],input_shape[1]], initializer='zeros', trainable=True) self.location = self.add_weight(shape=input_shape[1:], initializer='zeros', trainable=True) self.scale = self.add_weight(shape=input_shape[1:], initializer='zeros', trainable=True)def call(self, x): # 1. 平移和缩放数据 x_shift = x - self.location # 2. 分量重新缩放 x_mod = tf.math.multiply(x_shift,self.scale) # 3. 分量应用凹凸函数 x_in_abs = tf.math.abs(x_mod) Logic_x_leq1 = tf.math.sign(tf.keras.activations.relu(1-x_in_abs)) # 当|x|<=1时取值1,否则为0:由于|x|=1的概率为0,我们应该没问题 x_thresheld = Logic_x_leq1*tf.math.exp(-1/(1-tf.math.pow(x_in_abs,-1))) # 在阈值处计算凹凸函数,使用之前的逻辑 # 4+5. 在切线空间中应用平移并对角化 x_out = tf.linalg.diag(x_thresheld) + self.bias # 6. 在切线空间中乘以权重矩阵 x_out = tf.matmul(x_out,self.weight) # 7. 应用矩阵指数 x_out = tf.linalg.expm(x_out) # 8. 乘以(1)的输出 x_out = tf.linalg.matvec(x_out,x_shift) # 9. 重新居中转换后的数据 x_out = x_out + self.location # 返回输出 return x_out
回答:
你绝对不应该(我是说,绝对不应该...)将权重初始化为零!这种做法可以用于偏置,但绝不能用于权重。
看看可用的初始化器 - 我强烈建议使用GlorotUniform
(它之所以是Keras核心层的默认初始化器绝非偶然)或GlorotNormal
。
另外,location
和scale
参数的作用不太清楚 - 你可能也应该用非零值来初始化它们。