我正在尝试实现this paper中的网络。
此摘录有描述图像并附有说明。
输入是353个浮点数的要素,标签是缩放到-1, 1
的浮点数(-1500,1500)。
输出也应该在-1, 1
之间缩放。我使用tf.math.tanh()
来做这件事。
然而,我得到的输出只有-1
和1
,而没有中间的输出。原因是当打印倒数第二层的输出时,我得到了一个数组的数组,例如:
[[-5670.9859206034189]
[-3783.2489875296314]
[6674.3844754595357]
[-1985.6217861227797]
[5615.7066561151887]]
据我所知,这会导致tf.math.tanh
对数组中的每个单独的值执行。结果是1
或-1
,这取决于输入是负还是正。
由于所有标签都在-1500
和1500
之间(包括-1500
和1500
),并且被规范化为-1
和1
,因此我可以选择将-1500
和1500
添加到每个值,并将其传递给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)
1条答案
按热度按时间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
重要的是,在计算输出后,不要再对它进行操作。当你需要传播回来时,这就中断了。
祝你好运