关联权重

当自编码器整齐地对称时,就像我们刚刚构建的那样,一种常用技术是将解码器层的权重与编码器层的权重相关联。 这样减少了模型中的权重数量,加快了训练速度,并限制了过度拟合的风险。

具体来说,如果自编码器总共具有N个层(不计入输入层),并且 W^{[L]} 表示第L层的连接权重(例如,层 1 是第一隐藏层,则层N / 2是编码 层,而层N是输出层),则解码器层权重可以简单地定义为:W^{[N-L + 1]}= W^{[L]T}(其中L = 1, 2, ..., N2)。

不幸的是,使用fully_connected()函数在 TensorFlow 中实现相关权重有点麻烦;手动定义层实际上更容易。 代码结尾明显更加冗长:

  1. activation = tf.nn.elu
  2. regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
  3. initializer = tf.contrib.layers.variance_scaling_initializer()
  4. X = tf.placeholder(tf.float32, shape=[None, n_inputs])
  5. weights1_init = initializer([n_inputs, n_hidden1])
  6. weights2_init = initializer([n_hidden1, n_hidden2])
  7. weights1 = tf.Variable(weights1_init, dtype=tf.float32, name="weights1")
  8. weights2 = tf.Variable(weights2_init, dtype=tf.float32, name="weights2")
  9. weights3 = tf.transpose(weights2, name="weights3") # tied weights
  10. weights4 = tf.transpose(weights1, name="weights4") # tied weights
  11. biases1 = tf.Variable(tf.zeros(n_hidden1), name="biases1")
  12. biases2 = tf.Variable(tf.zeros(n_hidden2), name="biases2")
  13. biases3 = tf.Variable(tf.zeros(n_hidden3), name="biases3")
  14. biases4 = tf.Variable(tf.zeros(n_outputs), name="biases4")
  15. hidden1 = activation(tf.matmul(X, weights1) + biases1)
  16. hidden2 = activation(tf.matmul(hidden1, weights2) + biases2)
  17. hidden3 = activation(tf.matmul(hidden2, weights3) + biases3)
  18. outputs = tf.matmul(hidden3, weights4) + biases4
  19. reconstruction_loss = tf.reduce_mean(tf.square(outputs - X))
  20. reg_loss = regularizer(weights1) + regularizer(weights2)
  21. loss = reconstruction_loss + reg_loss
  22. optimizer = tf.train.AdamOptimizer(learning_rate)
  23. training_op = optimizer.minimize(loss)
  24. init = tf.global_variables_initializer()

这段代码非常简单,但有几件重要的事情需要注意:

  • 首先,权重 3 和权重 4 不是变量,它们分别是权重 2 和权重 1 的转置(它们与它们“绑定”)。
  • 其次,由于它们不是变量,所以规范它们是没有用的:我们只调整权重 1 和权重 2。
  • 第三,偏置永远不会被束缚,并且永远不会正规化。