反向传播如何在张量流

时间:2017-05-26 21:50:49

标签: tensorflow

在张量流中,似乎整个反向传播算法是通过在特定成本函数上运行优化器来执行的,该函数是某些MLP或CNN的输出。

我不完全理解张量流如何从成本中知道它确实是某个NN的输出?可以为任何模型定义成本函数。我应该如何“告诉”某个成本函数来自NN?

2 个答案:

答案 0 :(得分:17)

问题

我应该如何“告诉”某个成本函数来自NN?

(短)回答

只需配置优化器以最小化(或最大化)张量即可完成此操作。例如,如果我有这样的损失函数

loss = tf.reduce_sum( tf.square( y0 - y_out ) )

其中y0是基础事实(或期望的输出),y_out是计算出的输出,然后我可以通过定义我的训练函数来最小化损失

train = tf.train.GradientDescentOptimizer(1.0).minimize(loss)

这告诉Tensorflow,当计算训练时,应用渐变下降来减少它,并使用y0和y_out计算损失,因此梯度下降也会影响那些(如果它们是可训练的变量),等等。

变量 y0 y_out 损失列车不是标准的python变量,而是描述计算图。 Tensorflow使用有关该计算图的信息在应用梯度下降时展开它。

具体如何做到这一点超出了这个答案的范围。 Herehere是有关更多细节的更多信息的两个良好起点。

代码示例

让我们来看一个代码示例。首先是代码。

### imports
import tensorflow as tf

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

### induction
# 1x2 input -> 2x3 hidden sigmoid -> 3x1 sigmoid output

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

# Layer 1 = the 2x3 hidden sigmoid
m1 = tf.Variable( tf.random_uniform( [2,3] , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
b1 = tf.Variable( tf.random_uniform( [3]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
h1 = tf.sigmoid( tf.matmul( x0,m1 ) + b1 )

# Layer 2 = the 3x1 sigmoid output
m2 = tf.Variable( tf.random_uniform( [3,1] , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
b2 = tf.Variable( tf.random_uniform( [1]   , minval=0.1 , maxval=0.9 , dtype=tf.float32  ))
y_out = tf.sigmoid( tf.matmul( h1,m2 ) + b2 )


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

# training step : gradient decent (1.0) to minimize loss
train = tf.train.GradientDescentOptimizer(1.0).minimize(loss)


### training
# run 500 times using all the X and Y
# print out the loss and any other interesting info
with tf.Session() as sess:
  sess.run( tf.global_variables_initializer() )
  for step in range(500) :
    sess.run(train)

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

print ""

让我们来看看,但是以

开头的相反顺序
sess.run(train)

这告诉tensorflow查找 train 定义的图节点并计算它。 训练定义为

train = tf.train.GradientDescentOptimizer(1.0).minimize(loss)

要计算此张量流,必须为损失计算自动微分,这意味着走图。 损失定义为

loss = tf.reduce_sum( tf.square( y0 - y_out ) )

真正的张量流应用自动微分首先展开 tf.reduce_sum ,然后 tf.square ,然后 y0 - y_out ,这导致必须走y0和y_out的图表。

y0 = tf.constant( y_ , dtype=tf.float32 )

y0 是一个常量,不会更新。

y_out = tf.sigmoid( tf.matmul( h1,m2 ) + b2 )
处理

y_out 类似于丢失,首先处理 tf.sigmoid 等等...

总而言之,每个操作(例如tf.sigmoid,tf.square)不仅定义了正向操作(应用sigmoid或square),还定义了自动区分所需的信息。这与标准的python数学不同,例如

x = 7 + 9

上面的等式除了如何更新x之外什么也没有编码,其中为

z = y0 - y_out

对从y0减去y_out的图形进行编码并存储正向操作,并且足以在 z中自动区分

答案 1 :(得分:0)

backpropagation是由Rumelhart和Hinton等人创建的,并于1986年出版了on Nature

6.5: Back-Propagation and Other DifferentiationAlgorithmsdeeplearning book部分所述,通过计算图进行反向传播梯度的方法有两种:符号对数字微分和符号对符号导数。如本文所述,与Tensorflow最为相关的是A Tour of TensorFlow,后者可以使用此图进行说明:

enter image description here

来源:A Tour of TensorFlow的第二部分D部分

在上面的图7的左侧,w代表Tensorflow中的权重(或变量),并且x和y是两个中间操作(或节点w,x,y和z都是操作)以获取标量损失z。

Tensorflow将在每个节点上添加一个节点(如果我们在某个检查点打印变量的名称,我们可以看到这些节点的一些其他变量,如果将模型冻结到协议缓冲区文件中以进行部署,这些变量将被消除)在右边的图表(b)中可以看到的梯度图:dz / dy,dy / dx,dx / dw。

在遍历每个节点的反向传播期间,我们将其梯度与上一个节点的梯度相乘,最后得到整体目标导数dz / dw = dz / dy * dy / dx * dx / dw的符号句柄,它完全适用链式规则。一旦解决了梯度,w就能以学习率更新自己。

有关更多详细信息,请阅读本文:TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems