小規模ネットワークでは、活性化機能をシフトするためにバイアスが必要であることを理解しています。しかし、CNN、プーリング、ドロップアウト、およびその他の非線形アクティベーションの複数のレイヤーを持つディープネットワークの場合、バイアスは本当に違いを生み出していますか?畳み込みフィルターはローカル機能を学習しています与えられたconv出力チャネルに対して同じバイアスが使用されます。
これは this link のだましではありません。上記のリンクは、小さなニューラルネットワークにおけるバイアスの役割を説明するだけであり、複数のCNNレイヤー、ドロップアウト、プーリング、非線形活性化関数を含むディープネットワークにおけるバイアスの役割を説明するものではありません。
簡単な実験を実行したところ、変換層からバイアスを削除しても、最終的なテストの精度に違いはないことがわかりました。2つのモデルがトレーニングされており、テスト精度はほぼ同じです(偏りのないもので少し良いです。)
それらは歴史的な理由でのみ使用されていますか?
バイアスを使用しても精度が向上しない場合は、省略しないでください。学ぶべきパラメータが少ない。
私より深い知識を持っている人が、深いネットワークにおけるこれらのバイアスの重要性(もしあれば)を説明できれば幸いです。
これが完全なコードと実験結果です bias-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に固定されたニューロンからの入力によって引き起こされるため、デルタ値と学習率の積を差し引くことによって更新されます。
大規模なモデルでは、各ノードがそのすべての入力の平均アクティブ化からバイアスノードを作成できるため、バイアス入力を削除してもほとんど違いはありません。最初の層でこれが発生する能力は、入力分布によって異なります。たとえばMNISTの場合、入力の平均アクティブ化はほぼ一定です。 もちろん小さなネットワークではバイアス入力が必要ですが、大きなネットワークではそれを削除してもほとんど違いがありません。
大規模なネットワークでは違いはありませんが、それでもネットワークアーキテクチャに依存します。たとえばLSTMの場合:
LSTMのほとんどのアプリケーションは、多くの問題でうまく機能する小さなランダムな重みでLSTMを初期化するだけです。ただし、この初期化により、忘却ゲートは実質的に0.5に設定されます。これにより、タイムステップあたり0.5の係数を持つ消失勾配が導入され、長期的な依存関係が特に厳しい場合に問題が発生する可能性があります。この問題は、忘却ゲートバイアスを1または2などの大きな値に初期化するだけで対処されます。これにより、忘却ゲートが1に近い値に初期化され、勾配流が可能になります。
以下も参照してください。