本例中反向传播在哪里进行

Where is backpropagation performed in this example

我有一个DNN学习XOR的例子(右键在新标签页打开):https://colab.research.google.com/drive/1M5xFp4gaXPCbnejM8-5_yLp1B6UvwdL8

我对这两行感到困惑(与反向传播相关):

Grads = T.gradient(Loss,[W1,B1,W2,B2]);
Optim.apply_gradients(zip(Grads,[W1,B1,W2,B2]));

我猜后向循环在 T.gradient 因为那些是与损失相关的梯度值,但我仍然不清楚。问题是:

根据我的尝试,在打乱变量数组中的权重和偏差的顺序时,优化过程仍然有效。 但是反向传播需要从输出到输入的层顺序,我不明白

源代码:

#!pip install tensorflow==2.0.0rc2
%tensorflow_version 2.x
%reset -f

#libs
import tensorflow as tf;

#data
X = [[0,0],[0,1],[1,0],[1,1]];
Y = [[0],  [1],  [1],  [0]  ];
X = tf.convert_to_tensor(X,tf.float32);
Y = tf.convert_to_tensor(Y,tf.float32);

#model
W1 = tf.Variable(tf.random.uniform([2,20],-1,1));
B1 = tf.Variable(tf.random.uniform([  20],-1,1));

W2 = tf.Variable(tf.random.uniform([20,1],-1,1));
B2 = tf.Variable(tf.random.uniform([   1],-1,1));

@tf.function
def feedforward(X):
  H1  = tf.nn.leaky_relu(tf.matmul(X,W1) + B1);
  Out = tf.sigmoid(tf.matmul(H1,W2) + B2);
  return Out;
#end def

#train
Optim = tf.keras.optimizers.SGD(1e-1);
Steps = 1000;

for I in range(Steps):
  if I%(Steps/10)==0:
    Out  = feedforward(X);
    Loss = tf.reduce_sum(tf.square(Y-Out));
    print("Loss:",Loss.numpy());
  #end if

  with tf.GradientTape() as T:
    Out  = feedforward(X);
    Loss = tf.reduce_sum(tf.square(Y-Out));
  #end with

  #BACKPROPAGATION HERE?
  Grads = T.gradient(Loss,[W1,B1,W2,B2]);
  Optim.apply_gradients(zip(Grads,[W1,B1,W2,B2]));
#end for

Out  = feedforward(X);
Loss = tf.reduce_sum(tf.square(Y-Out));
print("Loss:",Loss.numpy(),"(Last)");

print("\nDone.");
#eof

让我们一步一个脚印。

第 1 步:计算梯度:

Grads = T.gradient(Loss,[W1,B1,W2,B2])

在这里,我们计算了关于所提供列表中变量的损失梯度。梯度列表根据变量的索引进行索引。这意味着 Grads[0] 将是相对于 W1 的梯度,依此类推。

第2步:接下来,我们执行更新。这是在以下时间完成的:

Optim.apply_gradients(zip(Grads,[W1,B1,W2,B2]))

这里用Grads[0]更新W1Grads[1]更新B1

请注意,梯度计算和更新步骤是分开执行的。所以只要变量在两个列表中出现的顺序相同,就不会有任何问题。

此外,GradientTape 必须与 Eager Execution 一起使用。

TensorFlow 2 在默认的 eager 模式下,甚至没有 @tf.function 装饰器来制作图形。 TensorFlow 在计算时仍然在跟踪张量之间的关系:https://stats.stackexchange.com/a/272000/142160

TensorFlow 在此处跟踪每个变量:

with tf.GradientTape() as T:
    Out  = feedforward(X);
    Loss = tf.reduce_sum(tf.square(Y-Out));

它是自动微分(有点Monte Carlo方法)而不是数学微分,因此,以下函数获得的所有梯度已经在其适当的深度反向传播(就像计算所有层的误差的反向循环):

Grads = T.gradient(Loss,[W1,B1,W2,B2]);

之后,优化器将应用梯度来改变权重和偏差:

Optim.apply_gradients(zip(Grads,[W1,B1,W2,B2]));