在张量流中,似乎整个反向传播算法是由优化程序在某个成本函数上的一次运行来执行的,该函数是某些MLP或CNN的输出。
我不完全了解张量流如何从成本中得知确实是某个NN的输出吗?可以为任何模型定义成本函数。我应该如何“告诉”某个成本函数是从NN派生的?
最佳答案
题
我应该如何“告诉”某个成本函数是从NN派生的?
(简短)答案
这可以通过简单地配置优化器以最小化(或最大化)张量来完成。例如,如果我有这样的损失函数
loss = tf.reduce_sum( tf.square( y0 - y_out ) )
其中y0是基本事实(或期望的输出),而y_out是计算出的输出,那么我可以通过这样定义训练函数来使损失最小化
train = tf.train.GradientDescentOptimizer(1.0).minimize(loss)
这告诉Tensorflow,当计算出train时,它是对损失应用梯度下降以使其最小化,并且使用y0和y_out计算出损失,因此梯度下降也会影响那些(如果它们是可训练的变量),依此类推。
变量y0,y_out,损失和训练不是标准的python变量,而是计算图的描述。在应用梯度下降时,Tensorflow使用有关该计算图的信息来展开它。
具体而言,它的工作方式超出了此答案的范围。 Here和here是获得更多详细信息的两个很好的起点。
代码示例
让我们来看一个代码示例。首先是代码。
### 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中进行自动微分
关于tensorflow - tensorflow 中的反向传播如何工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44210561/