Tensorflow:CNN训练收敛于零矢量

时间:2018-03-28 07:39:22

标签: python tensorflow computer-vision deep-learning

我是深度学习的初学者,并参加了一些关于Udacity的课程。最近我试图在输入深度图像中构建一个检测手关节的深层网络,这似乎并不能很好地工作。 (我的数据集是ICVL手势数据集) The network structure is shown here.

①一批输入图像,240x320;

②具有5x5内核的8通道卷积层;

③最大合并层,ksize = stride = 2;

④完全连接的图层,weight.shape = [38400,1024];

⑤完全连接的图层,weight.shape = [1024,48]。

在几个训练时期之后,最后一层的输出收敛为(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一样运行。

1 个答案:

答案 0 :(得分:0)

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

虽然relu是一种流行的隐藏激活,但我发现使用它作为输出激活有一个主要问题:众所周知relu将负输入映射到0 - 但是,至关重要的是,< em> gradients 也将为0.输出层中发生的这种情况基本上意味着当网络产生输出时,你的网络无法从错误中吸取教训。 0(随机初始化可能会发生这种情况)。这可能会严重影响整个学习过程。