Tensorflow tf.math.tanh可正确缩放网络输出,无需大批量处理

tsm1rwdh  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(160)

我正在尝试实现this paper中的网络。
此摘录有描述图像并附有说明。

输入是353个浮点数的要素,标签是缩放到-1, 1的浮点数(-1500,1500)。
输出也应该在-1, 1之间缩放。我使用tf.math.tanh()来做这件事。
然而,我得到的输出只有-11,而没有中间的输出。原因是当打印倒数第二层的输出时,我得到了一个数组的数组,例如:

[[-5670.9859206034189]
 [-3783.2489875296314]
 [6674.3844754595357]
 [-1985.6217861227797]
 [5615.7066561151887]]

据我所知,这会导致tf.math.tanh对数组中的每个单独的值执行。结果是1-1,这取决于输入是负还是正。
由于所有标签都在-15001500之间(包括-15001500),并且被规范化为-11,因此我可以选择将-15001500添加到每个值,并将其传递给tanh函数。即使它超出界限,因为它最大可能是1-1。然而,这种方法可能比不使用tanh而手动进行值的缩放要慢,但只是将该值除以x1M17 N1 x并将其限制在x1M18 N1 x和x1M19 N1 x。
另一种方法是将一个数组中的所有值相加,然后通过tanh函数运行该数组,但直觉上这是错误的。[200, 300, 400, 500]Tanh将把500缩放为1,而实际上,1500应等同于1-因此给出了错误的标签。这意味着tanh将在很大程度上取决于批量大小,例如,1000个样本可能比100个样本给予更好的结果。推断也会有同样的问题,并要求我总是使用大批量。
这个问题的正确解决方案是什么?
这是我的网络代码的一部分,为了简洁我省略了一些层。

class FullFullyConnectedOutputLayer(tf.keras.layers.Layer):
  def __init__(self):
    super(FullFullyConnectedOutputLayer, self).__init__()

  def build(self, input_shape):
    stddev = 2 / np.sqrt(input_shape[-1] + 1)
    self.w = tf.Variable(tf.random.truncated_normal((input_shape[-1], 1), dtype='float64'), trainable=True)

    b_init = tf.zeros_initializer()
    self.b = tf.Variable(initial_value=b_init(shape=(1), dtype='float64'), trainable=True)

  def call(self, input):
    return tf.matmul(input, self.w) + self.b

class FullNetwork(tf.keras.Model):
  def __init__(self, ):
    super(FullNetwork, self).__init__(name='')

    self.inputLayer = FullFeatureLayer()
    self.hiddenLayer1 = FullFeatureLayer()
    self.hiddenLayer2 = FullFullyConnectedFeatureLayer()
    self.outputLayer = FullFullyConnectedOutputLayer()

  def call(self, input):
    x = self.inputLayer(input)
    x = self.hiddenLayer1(x)
    x = self.hiddenLayer2(x)
    x = self.outputLayer(x)
    return tf.math.tanh(x)

tf.keras.backend.set_floatx('float64')

fullNetwork = FullNetwork()

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
fullNetwork.compile(optimizer, loss=tf.keras.losses.MeanAbsoluteError(), metrics=["accuracy"])

#epoch is 1 for debugging, batch_size is yet to be determined but probably 1000
fullNetwork.fit(feature_array[:10], score_array[:10], epochs=1, batch_size=5)
e4yzc0pl

e4yzc0pl1#

当使用层时,每一层都是前一层输入的矩阵乘以权重,所以你可以得到很大的值,即使你有“好”的权重。
当tanh得到偶数〉10的输入时,因为它是基于指数的,所以它很容易对每个大的值(通常范围为-2到2)返回1。
它只能得到很小的值。
所以,如果速率之和小于1,并且每个输入节点也小于1,你就不能得到一个大于1的和值,这就是我的建议。你可以做几件事:
1.使用sofmax作为激活函数
1.按maxscale缩放输入值(将输入范围缩放到输出范围)。
1.您可以检查范围总和-也可以将其除以您检查的总和。
1.最好的,我建议的,是在输入上做softmax(这是第一个输入变换),xavier的尺度为-2..2,这样你就可以确保输出为-2..2,这是tanh的最佳值。tanh在这个范围内有点线性,所以下一层也将保持小范围(保持“1”的和最大)。
任何一层,除了最后一层--使用tanh。最后一层使用softmax(这是最好的方法)。softmax的派生有点复杂,所以你最好了解一下。
https://eli.thegreenplace.net/2016/the-softmax-function-and-its-derivative
重要的是,在计算输出后,不要再对它进行操作。当你需要传播回来时,这就中断了。
祝你好运

相关问题