我已经在tensorflow中编写了一个卷积网络,其中relu作为激活函数,但它没有学习(对于eval和train数据集,丢失是恒定的)。 对于不同的激活功能,一切正常。
以下是创建nn的代码:
def _create_nn(self):
current = tf.layers.conv2d(self.input, 20, 3, activation=self.activation)
current = tf.layers.max_pooling2d(current, 2, 2)
current = tf.layers.conv2d(current, 24, 3, activation=self.activation)
current = tf.layers.conv2d(current, 24, 3, activation=self.activation)
current = tf.layers.max_pooling2d(current, 2, 2)
self.descriptor = current = tf.layers.conv2d(current, 32, 5, activation=self.activation)
if not self.drop_conv:
current = tf.layers.conv2d(current, self.layer_7_filters_n, 3, activation=self.activation)
if self.add_conv:
current = tf.layers.conv2d(current, 48, 2, activation=self.activation)
self.descriptor = current
last_conv_output_shape = current.get_shape().as_list()
self.descr_size = last_conv_output_shape[1] * last_conv_output_shape[2] * last_conv_output_shape[3]
current = tf.layers.dense(tf.reshape(current, [-1, self.descr_size]), 100, activation=self.activation)
current = tf.layers.dense(current, 50, activation=self.last_activation)
return current
self.activiation设置为tf.nn.relu,self.last_activiation设置为tf.nn.softmax
在这里创建了损失函数和优化器:
self._nn = self._create_nn()
self._loss_function = tf.reduce_sum(tf.squared_difference(self._nn, self.Y), 1)
optimizer = tf.train.AdamOptimizer()
self._train_op = optimizer.minimize(self._loss_function)
我尝试通过将tf.random_normal_initializer(0.1, 0.1)
作为初始化程序来更改变量初始化,但是它不会导致损失函数的任何更改。
我很感激能帮助这个神经网络与ReLu一起工作。
编辑:Leaky ReLu有同样的问题
编辑:我设法复制相同错误的小例子:
x = tf.constant([[3., 211., 123., 78.]])
v = tf.Variable([0.5, 0.5, 0.5, 0.5])
h_d = tf.layers.Dense(4, activation=tf.nn.leaky_relu)
h = h_d(x)
y_d = tf.layers.Dense(4, activation=tf.nn.softmax)
y = y_d(h)
d = tf.constant([[.5, .5, 0, 0]])
h_d和y_d内核和偏差的梯度(用tf.gradients计算)等于或接近0
答案 0 :(得分:1)
在一个非常不可能的情况下,某些层中的所有激活对所有样本都是负的。它们被ReLU设置为零,并且没有学习进度,因为ReLU的负部分的梯度为零。
使这更可能的事情是一个小数据集,输入功能的奇怪缩放,不适当的权重初始化和/或中间层中的少数通道。
此处您使用random_normal_initializer
与mean=0.1
,因此您的输入可能都是负数,因此会映射到负值。尝试mean=0
,或重新调整输入要素。
您也可以尝试Leaky ReLU。也许学习率太小或太大。
答案 1 :(得分:0)
看起来问题在于输入数据的规模。当值在0到255之间时,在下一层中或多或少地保持比例,给予最后一层的预激活输出具有足够大的差异以将softmax梯度减小到(几乎)0。 它只能通过类似relu的激活函数来观察,因为其他的,比如sigmoid或softsign,保持网络中的值范围更小,数量级为1或几十或几百。
这里的解决方案是将输入乘以将其重新调整为0-1,如果是1/255的字节。