【问题标题】:Tensorflow: CNN training converges at a vector of zerosTensorflow:CNN 训练收敛于零向量
【发布时间】:2018-03-28 07:39:21
【问题描述】:

我是深度学习的初学者,已经学习了一些关于 Udacity 的课程。最近我正在尝试构建一个深度网络来检测输入深度图像中的手关节,这似乎效果不佳。 (我的数据集是 ICVL 手部姿势数据集) The network structure is shown here.

①一批输入图片,240x320;

② 8 通道卷积层,5x5 内核;

③一个最大池化层,ksize = stride = 2;

④ 一个全连接层,weight.shape = [38400, 1024];

⑤一个全连接层,weight.shape = [1024, 48]。

经过几个 epoch 的训练,最后一层的输出收敛为一个 (0, 0, ..., 0) 向量。我选择均方误差作为损失函数,它的值一直保持在 40000 以上,并且似乎没有减少。

网络结构已经过于简单,无法再次简化,但问题依然存在。有人可以提供任何建议吗?

我的主要代码贴在下面:

image = tf.placeholder(tf.float32, [None, 240, 320, 1])
annotations = tf.placeholder(tf.float32, [None, 48])

W_convolution_layer1 = tf.Variable(tf.truncated_normal([5, 5, 1, 8], stddev=0.1))
b_convolution_layer1 = tf.Variable(tf.constant(0.1, shape=[8]))
h_convolution_layer1 = tf.nn.relu(
    tf.nn.conv2d(image, W_convolution_layer1, [1, 1, 1, 1], 'SAME') + b_convolution_layer1)
h_pooling_layer1 = tf.nn.max_pool(h_convolution_layer1, [1, 2, 2, 1], [1, 2, 2, 1], 'SAME')

W_fully_connected_layer1 = tf.Variable(tf.truncated_normal([120 * 160 * 8, 1024], stddev=0.1))
b_fully_connected_layer1 = tf.Variable(tf.constant(0.1, shape=[1024]))
h_pooling_flat = tf.reshape(h_pooling_layer1, [-1, 120 * 160 * 8])
h_fully_connected_layer1 = tf.nn.relu(
    tf.matmul(h_pooling_flat, W_fully_connected_layer1) + b_fully_connected_layer1)

W_fully_connected_layer2 = tf.Variable(tf.truncated_normal([1024, 48], stddev=0.1))
b_fully_connected_layer2 = tf.Variable(tf.constant(0.1, shape=[48]))
detection = tf.nn.relu(
    tf.matmul(h_fully_connected_layer1, W_fully_connected_layer2) + b_fully_connected_layer2)

mean_squared_error = tf.reduce_sum(tf.losses.mean_squared_error(annotations, detection))
training = tf.train.AdamOptimizer(1e-4).minimize(mean_squared_error)
# This data loader reads images and annotations and convert them into batches of numbers.
loader = ICVLDataLoader('../data/')

with tf.Session() as session:
    session.run(tf.global_variables_initializer())
    for i in range(1000):
        # batch_images: a list with shape = [BATCH_SIZE, 240, 320, 1]
        # batch_annotations: a list with shape = [BATCH_SIZE, 48]
        [batch_images, batch_annotations] = loader.get_batch(100).to_1d_list()
        [x_, t_, l_, p_] = session.run([x_image, training, mean_squared_error, detection],
                                       feed_dict={images: batch_images, annotations: batch_annotations})

它的运行方式类似于this

【问题讨论】:

  • 请出示您的代码。听起来像是某处实现中的错误。
  • 我重新编辑了问题并发布了我的代码。非常感谢。@xdurch0
  • 谢谢,这有帮助。还有一件事要澄清:目标是什么? IE。显然有 48 个目标值,但它们代表什么?这是分类问题吗?如果是这样,每个输入是否恰好属于一个类(即目标是一个热向量)或者单个输入的 48 个值中的多个值是否可以为 1?
  • 抱歉没有详细说明。这是一个检测问题,其中 48 个目标值代表深度图像中心的手部 16 个关键点的 (x, y, z) 坐标。我从来没有处理过检测问题,所以也许我犯了一些非常有趣的错误。@xdurch0

标签: python tensorflow computer-vision deep-learning


【解决方案1】:

主要问题可能是输出层中的relu 激活。您应该删除它,即让detection 只是矩阵乘法的结果。如果您想强制输出为正,请考虑使用指数函数之类的东西。

虽然relu 是一种流行的隐藏激活,但我发现将其用作输出激活有一个主要问题:众所周知,relu 将负输入映射到 0——然而,至关重要的是,梯度 也将为 0。这发生在输出层基本上意味着您的网络在产生输出

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2017-10-12
    • 2019-01-10
    • 2020-02-28
    相关资源
    最近更新 更多