我可以使用 `tf.nn.dropout` 来实现 DropConnect 吗?

8

我认为我掌握了DropOut的基础知识以及在实现中使用TensorFlow API的方法(链接)。但是在tf.nn.dropout中与dropout概率相关联的归一化似乎不是DropConnect的一部分。这是正确的吗?如果是,那么归一化是否会造成任何“损害”,或者我是否可以简单地将tf.nn.dropout应用于我的权重以实现DropConnect?

1个回答

10

答案

是的,您可以使用tf.nn.dropout来执行DropConnect,只需使用tf.nn.dropout来包装您的权重矩阵,而不是后矩阵乘法。然后,您可以通过乘以dropout来撤消权重更改。

dropConnect = tf.nn.dropout( m1, keep_prob ) * keep_prob

示例代码

这是一个使用drop connect计算XOR函数的代码示例。我还注释掉了执行dropout的代码,您可以用它来比较输出结果。

### imports
import tensorflow as tf

### constant data
x  = [[0.,0.],[1.,1.],[1.,0.],[0.,1.]]
y_ = [[1.,0.],[1.,0.],[0.,1.],[0.,1.]]

### induction

# Layer 0 = the x2 inputs
x0 = tf.constant( x  , dtype=tf.float32 )
y0 = tf.constant( y_ , dtype=tf.float32 )

keep_prob = tf.placeholder( dtype=tf.float32 )

# Layer 1 = the 2x12 hidden sigmoid
m1 = tf.Variable( tf.random_uniform( [2,12] , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
b1 = tf.Variable( tf.random_uniform( [12]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))


########## DROP CONNECT
# - use this to preform "DropConnect" flavor of dropout
dropConnect = tf.nn.dropout( m1, keep_prob ) * keep_prob
h1 = tf.sigmoid( tf.matmul( x0, dropConnect ) + b1 ) 

########## DROP OUT
# - uncomment this to use "regular" dropout
#h1 = tf.nn.dropout( tf.sigmoid( tf.matmul( x0,m1 ) + b1 ) , keep_prob )


# Layer 2 = the 12x2 softmax output
m2 = tf.Variable( tf.random_uniform( [12,2] , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
b2 = tf.Variable( tf.random_uniform( [2]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
y_out = tf.nn.softmax( tf.matmul( h1,m2 ) + b2 )


# loss : sum of the squares of y0 - y_out
loss = tf.reduce_sum( tf.square( y0 - y_out ) )

# training step : discovered learning rate of 1e-2 through experimentation
train = tf.train.AdamOptimizer(1e-2).minimize(loss)

### training
# run 5000 times using all the X and Y
# print out the loss and any other interesting info
with tf.Session() as sess:
  sess.run( tf.initialize_all_variables() )
  print "\nloss"
  for step in range(5000) :
    sess.run(train,feed_dict={keep_prob:0.5})
    if (step + 1) % 100 == 0 :
      print sess.run(loss,feed_dict={keep_prob:1.})


  results = sess.run([m1,b1,m2,b2,y_out,loss],feed_dict={keep_prob:1.})
  labels  = "m1,b1,m2,b2,y_out,loss".split(",")
  for label,result in zip(*(labels,results)) :
    print ""
    print label
    print result

print ""

输出

这两种变体都能够将输入正确地分离成正确的输出。

y_out
[[  7.05891490e-01   2.94108540e-01]
 [  9.99605477e-01   3.94574134e-04]
 [  4.99370173e-02   9.50062990e-01]
 [  4.39682379e-02   9.56031740e-01]]

在这里,您可以看到dropConnect输出的结果:正确分类为真、真、假、假


对于卷积层:我假设DropConnect应用于核权重,以取代在池化之前/之后应用Dropout(我从未清楚哪个是正确的)。这样理解正确吗? - orome
1
是的,您可以使用它来dropconnect任何权重。诀窍是包装权重而不是后处理。对于卷积,您将拥有一个与上述代码类似的权重矩阵,并且您可以以完全相同的方式进行包装。干杯。 - Anton Codes
就池化而言,在池化之后应用dropout在概念上是不同的。从概念上讲,我认为在池化上使用dropout更类似于“子集中的最佳”而不是“集合中的最佳”。 - Anton Codes
1
我希望在这个问题上能够得到一些更好的答案(或意见)。相关问题链接 - orome
1
《使用DropConnect正则化神经网络》一文中提到:“此外,在训练期间,偏置也被屏蔽了。”这是否意味着上面的代码应该对b1应用tf.nn.dropout(b1, keep_prob)*keep_prob - bytesinflight
1
哦,这是一个有趣的问题。值得一试,或者至少进行思想实验。作为一个思想实验,我会说偏差作用于“白平衡”嵌入空间,而dropConnect则使层与层之间的连接具有冗余性,因此我的直觉会说在偏差上使用dropConnect是错误的。但是,这值得一试。我没有看到那篇论文中有任何经验性的测试,测试有无偏差。更像是他们在说他们所做的事情 - 只是让你知道。 - Anton Codes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接