如果我使用许多relu​​s的网络,为什么我的交叉熵损失功能会变得很大?

时间:2016-07-05 22:59:08

标签: python neural-network tensorflow softmax cross-entropy

我有这种损失功能:

            loss_main = tf.reduce_mean(
                tf.nn.softmax_cross_entropy_with_logits(train_logits, train['labels']),
                name='loss_main',
            )

train_logits是根据以下构建的管道定义的:

    def build_logit_pipeline(data, include_dropout):
        # X --> *W1 --> +b1 --> relu --> *W2 --> +b2 ... --> softmax etc...
        pipeline = data

        for i in xrange(len(layer_sizes) - 1):
            last = i == len(layer_sizes) - 2
            with tf.name_scope("linear%d" % i):
                pipeline = tf.matmul(pipeline, weights[i])
                pipeline = tf.add(pipeline, biases[i])

            if not last:
                # insert relu after every one before the last
                with tf.name_scope("relu%d" % i):
                    pipeline = getattr(tf.nn, arg('act-func'))(pipeline)
                    if include_dropout and not arg('no-dropout'):
                        pipeline = tf.nn.dropout(pipeline, 0.5, name='dropout')

        return pipeline

layer_sizesweightsbiases的构造如下:

    def make_weight(from_, to, name=None):
        return tf.Variable(tf.truncated_normal([from_, to], stddev=0.5), name=name)

    def make_bias(to, name=None):
        return tf.Variable(tf.truncated_normal([to], stddev=0.5), name=name)

    layer_sizes = [dataset.image_size**2] + arg('layers') + [dataset.num_classes]
    with tf.name_scope("parameters"):
        with tf.name_scope("weights"):
            weights = [make_weight(layer_sizes[i], layer_sizes[i+1], name="weights_%d" % i)
                       for i in xrange(len(layer_sizes) - 1)]

        with tf.name_scope("biases"):
            biases = [make_bias(layer_sizes[i + 1], name="biases_%d" % i)
                      for i in xrange(len(layer_sizes) - 1)]

如果arg('act-func')是relu,那么如果我建立一个长链的relus - 就像arg('layers')[750, 750, 750, 750, 750, 750]那样 - 那么我的损失函数是巨大的:

Global step: 0
Batch loss function: 28593700.000000

如果我有较短的relus链 - 比如说arg('layers')只有[750] - 那么损失函数会更小:

Global step: 0
Batch loss function: 96.377831

我的问题是:为什么损失功能如此显着不同?据我所知,logits的输出是softmax导致概率分布。然后,从该概率分布确定交叉熵到单热标签。为什么改变relus的数量我改变了这个功能?我认为每个网络在开始时都应该是同样错误的 - 关于随机 - 因此损失永远不会变得太大。

请注意,此损失函数包含任何l2损失,因此增加的权重和偏差数量不会解释此问题。

使用arg('act-func')代替tanh,这种损失的增加不会发生 - 它与我预期的大致相同。

1 个答案:

答案 0 :(得分:1)

首先检查softmax的输出。如果输出是这样的:

[[0., 1.],
 [0., 1.],
 [0., 1.],
 ...
 [0., 1.]]

但事实是这样的:

[[1., 0.],
 [1., 0.],
 [1., 0.],
 ...
 [1., 0.]]
然后交叉熵损失会非常大。根据交叉熵的公式:

-[ylog(a) + (1-y)log(1-a)]

y 是基本事实, a 是softmax的输出。

有时候,它是一些“巨大的”特征值,它没有被标准化,使得这些“错误”的softmax输出。根据softmax的定义:

exp(z_j)/sum(exp(z_i)) for i=1 to D

其中 D 是向量 z 的维度,如果有一些“巨大”组件, softmax的输出几乎为0或1。