卷积层中的偏差真的会对测试准确性产生影响吗?



我知道在小型网络中需要偏差来转移激活函数。但是,对于具有多层CNN,池化,dropout和其他非线性激活的深度网络,偏见真的会有所作为吗?卷积滤波器正在学习局部特征,对于给定的卷积输出通道,使用相同的偏差。

这不是此链接的欺骗。上面的链接仅解释了偏差在小型神经网络中的作用,并不试图解释偏差在包含多个CNN层,dropout,池化和非线性激活函数的深度网络中的作用。

我进行了一个简单的实验,结果表明,从卷积层中去除偏差对最终测试的准确性没有影响。有两个模型经过训练,测试准确性几乎相同(在一个没有偏差的模型中略好(。

  • model_with_bias,
  • model_without_bias( conv 层中未添加偏置(

它们是否仅出于历史原因而被使用?

如果使用偏差不能提高准确性,我们不应该省略它们吗?需要学习的参数更少。

如果有人比我有更深的了解,可以解释这些偏见在深度网络中的重要性(如果有的话(,我将不胜感激。

这是完整的代码和实验结果偏差-VS-no_bias实验

batch_size = 16
patch_size = 5
depth = 16
num_hidden = 64
graph = tf.Graph()
with graph.as_default():
# Input data.
tf_train_dataset = tf.placeholder(
tf.float32, shape=(batch_size, image_size, image_size, num_channels))
tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
tf_valid_dataset = tf.constant(valid_dataset)
tf_test_dataset = tf.constant(test_dataset)
# Variables.
layer1_weights = tf.Variable(tf.truncated_normal(
[patch_size, patch_size, num_channels, depth], stddev=0.1))
layer1_biases = tf.Variable(tf.zeros([depth]))
layer2_weights = tf.Variable(tf.truncated_normal(
[patch_size, patch_size, depth, depth], stddev=0.1))
layer2_biases = tf.Variable(tf.constant(1.0, shape=[depth]))
layer3_weights = tf.Variable(tf.truncated_normal(
[image_size // 4 * image_size // 4 * depth, num_hidden], stddev=0.1))
layer3_biases = tf.Variable(tf.constant(1.0, shape=[num_hidden]))
layer4_weights = tf.Variable(tf.truncated_normal(
[num_hidden, num_labels], stddev=0.1))
layer4_biases = tf.Variable(tf.constant(1.0, shape=[num_labels]))
# define a Model with bias .
def model_with_bias(data):
conv = tf.nn.conv2d(data, layer1_weights, [1, 2, 2, 1], padding='SAME')
hidden = tf.nn.relu(conv + layer1_biases)
conv = tf.nn.conv2d(hidden, layer2_weights, [1, 2, 2, 1], padding='SAME')
hidden = tf.nn.relu(conv + layer2_biases)
shape = hidden.get_shape().as_list()
reshape = tf.reshape(hidden, [shape[0], shape[1] * shape[2] * shape[3]])
hidden = tf.nn.relu(tf.matmul(reshape, layer3_weights) + layer3_biases)
return tf.matmul(hidden, layer4_weights) + layer4_biases
# define a Model without bias added in the convolutional layer.
def model_without_bias(data):
conv = tf.nn.conv2d(data, layer1_weights, [1, 2, 2, 1], padding='SAME')
hidden = tf.nn.relu(conv ) # layer1_ bias is not added 
conv = tf.nn.conv2d(hidden, layer2_weights, [1, 2, 2, 1], padding='SAME')
hidden = tf.nn.relu(conv) # + layer2_biases)
shape = hidden.get_shape().as_list()
reshape = tf.reshape(hidden, [shape[0], shape[1] * shape[2] * shape[3]])
# bias are added only in Fully connected layer(layer 3 and layer 4)
hidden = tf.nn.relu(tf.matmul(reshape, layer3_weights) + layer3_biases)
return tf.matmul(hidden, layer4_weights) + layer4_biases
# Training computation.
logits_with_bias = model_with_bias(tf_train_dataset)
loss_with_bias = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits_with_bias))
logits_without_bias = model_without_bias(tf_train_dataset)
loss_without_bias = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits_without_bias))
# Optimizer.
optimizer_with_bias = tf.train.GradientDescentOptimizer(0.05).minimize(loss_with_bias)
optimizer_without_bias = tf.train.GradientDescentOptimizer(0.05).minimize(loss_without_bias)
# Predictions for the training, validation, and test data.
train_prediction_with_bias = tf.nn.softmax(logits_with_bias)
valid_prediction_with_bias = tf.nn.softmax(model_with_bias(tf_valid_dataset))
test_prediction_with_bias = tf.nn.softmax(model_with_bias(tf_test_dataset))
# Predictions for without
train_prediction_without_bias = tf.nn.softmax(logits_without_bias)
valid_prediction_without_bias = tf.nn.softmax(model_without_bias(tf_valid_dataset))
test_prediction_without_bias = tf.nn.softmax(model_without_bias(tf_test_dataset))
num_steps = 1001
with tf.Session(graph=graph) as session:
tf.global_variables_initializer().run()
print('Initialized')
for step in range(num_steps):
offset = (step * batch_size) % (train_labels.shape[0] - batch_size)
batch_data = train_dataset[offset:(offset + batch_size), :, :, :]
batch_labels = train_labels[offset:(offset + batch_size), :]
feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}
session.run(optimizer_with_bias, feed_dict=feed_dict)
session.run(optimizer_without_bias, feed_dict = feed_dict)
print('Test accuracy(with bias): %.1f%%' % accuracy(test_prediction_with_bias.eval(), test_labels))
print('Test accuracy(without bias): %.1f%%' % accuracy(test_prediction_without_bias.eval(), test_labels))

输出:

初始 化

测试精度(带偏差(:90.5%

测试精度(无偏差(:90.6%

偏差通过学习算法与权重一起调整,例如 梯度下降。偏差与权重的不同之处在于它们是 独立于前几层的输出。概念上的偏见是 由固定激活为 1 的神经元的输入引起,因此 通过减去增量值的乘积和更新,并且 学习率。

在大型模型中,去除偏置输入几乎没有区别,因为每个节点都可以从其所有输入的平均激活中产生一个偏置节点,根据大数定律,这将大致是正态的。在第一层,发生这种情况的能力取决于您的输入分布。在小型网络上,当然需要偏置输入,但在大型网络上,删除它几乎没有区别

虽然在大型网络中没有区别,但它仍然取决于网络架构。例如在 LSTM 中:

LSTM 的大多数应用程序只是简单地初始化 LSTM 与小 随机权重,在许多问题上效果很好。但是这个 初始化有效地将遗忘门设置为 0.5。这 引入一个消失梯度,每个时间步的系数为 0.5, 每当长期依赖关系出现时,这可能会导致问题 特别严重。此问题可通过简单地初始化 忘记门偏向于较大的值,例如 1 或 2。通过这样做, 忘记门将被初始化为接近 1 的值, 启用梯度流。

另请参阅:

  • 神经网络中的偏差规则
  • 什么是神经网络中的偏差
  • 循环网络架构的实证探索

在大多数网络中,在conv层之后都有一个批处理范数层,该层具有偏差。因此,如果你有一个批处理范数层,则没有增益。看: 不能在卷积层中同时使用偏差和批量归一化

否则,从数学的角度来看,你正在学习不同的函数。然而,事实证明,特别是如果你有一个非常复杂的网络来处理一个简单的问题,你可能会在没有偏差的情况下实现几乎相同的目标,而不是有偏差,但最终使用更多的参数。根据我的经验,使用比所需多 2-4 个参数的因子很少会损害深度学习的性能 - 特别是如果你正则化。因此,很难注意到任何差异。但是,您可以尝试使用少量通道(我认为网络的深度不如卷积的通道数量重要(,看看偏差是否有所不同。我猜是这样。

最新更新