title: How to compute final gradients from multiple intermediate gradients in Neural Network manually by TensorFlow?
body: <p>I want to compute gradient 'dL/dWfe' by combining three intermediate gradients, which are <code>dL/dSumwiEi</code>, <code>dSumwiEi/dEi</code>, and <code>dEi/dWfe</code>. But when I use tf.gradients to retrieve their gradients, I saw their shapes are not compatible. How can I connect these three gradients to do proper gradient descent for the weights in network <code>Wfe</code>.
  <a href="https://i.stack.imgur.com/sn4Rn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sn4Rn.png" alt="enter image description here"></a></p>
  
  <p>My code is as follows,</p>
  
  <pre><code>import tensorflow as tf
  from keras.layers import Input, Conv2D, AveragePooling2D, GlobalMaxPooling2D, UpSampling2D, \
      Dense, MaxPooling2D, Dropout, Flatten, Lambda, GlobalAveragePooling2D, Concatenate, Average, Deconvolution2D, Activation, Add,ZeroPadding2D, Softmax
  from keras.models import Model, Sequential
  from ats.utils.layers import L2Normalize, SampleSoftmax, ResizeImages, \
      TotalReshape, ActivityRegularizer
  from ats.core.expectation import expected
  #tf.enable_eager_execution()
  
  n_patches = 10
  input_frame = tf.constant(value=1, shape=(1, 100, 100, 3), dtype=tf.float32)
  input_patches = tf.constant(value=1, shape=(1, n_patches, 100, 100, 3), dtype=tf.float32)
  sampled_attention = tf.constant(value=1, shape=(1, n_patches), dtype=tf.float32)
  weighted_expectations_whole_image = tf.constant(value=1, shape=(1, 48), dtype=tf.float32)
  y = tf.constant(value=1, shape=(1, 1), dtype=tf.int32)
  
  with tf.variable_scope('Attention'):
      attention_sub1 = Sequential([
          Conv2D(8, kernel_size=3, activation="relu", padding="same"),
          Conv2D(8, kernel_size=3, activation="relu", padding="same"),
      ], name='Attention_sub1')
      attention = Sequential([
          attention_sub1,
          Conv2D(1, kernel_size=3, activation="relu", padding="same"),
          SampleSoftmax(squeeze_channels=True, smooth=1e-5)
      ], name='Attention_sub2')
  
  with tf.variable_scope('Weights_predictor'):
      weights_predictor = Sequential([
          attention_sub1,
          Conv2D(1, kernel_size=3, activation="relu", padding="same"),
          GlobalMaxPooling2D(),
          Dense(128, activation='relu'),
          Dense(1, activation='sigmoid')
      ], name='Weights_predictor')
  
  with tf.variable_scope('Feature_extractor'):
      feature = Sequential([
          Conv2D(36, kernel_size=4, activation="relu"),
          MaxPooling2D(pool_size=(2, 2)),
          Conv2D(48, kernel_size=3, activation="relu"),
          MaxPooling2D(pool_size=(2, 2)),
          GlobalAveragePooling2D(),
          L2Normalize()  # Ensure the attention produces minimal variance estimator (L2 norm close to 1)
      ], name='Feature_extractor')
  
  with tf.variable_scope('Classifier'):
      classifier = Sequential([
          Dense(512, activation="relu"),
          Dropout(rate=0.5),
          Dense(512, activation="relu"),
          Dropout(rate=0.5),
          Dense(2, activation="softmax")
      ], name='Classifier')
  
  feature_model = feature
  expectations_model = expected
  classifier_model = classifier
  attention_map_model = attention
  weights_model = weights_predictor
  
  with tf.GradientTape(persistent=True) as t:
      attention_map = attention_map_model(input_frame)
      weights_predicted = weights_model(input_frame)
  
      patches = tf.squeeze(input_patches, axis=0)
  
      features = feature_model(patches)
      features = tf.expand_dims(features, axis=0)
      expectation_one_frame = expected(sampled_attention, features, replace=False)
      estimation_for_whole_image = weighted_expectations_whole_image
      prediction = classifier_model(estimation_for_whole_image)
  
      loss = tf.losses.sparse_softmax_cross_entropy(logits=prediction, labels=y)
  
  t_vars = tf.trainable_variables()
  a_vars = [var for var in t_vars if 'Attention' in var.name]
  w_vars = [var for var in t_vars if 'Weights_predictor' in var.name]
  f_vars = [var for var in t_vars if 'Feature_extractor' in var.name]
  c_vars = [var for var in t_vars if 'Classifier' in var.name]
  
  
  dAi_dW_att = tf.gradients(attention_map, a_vars)
  dwi_dWweightsPredictor = tf.gradients(weights_predicted, w_vars)
  dSumwiEi_dEi = weights_predicted # newly input value
  
  # After sampling patches
  dEi_dWfe = tf.gradients(expectation_one_frame, f_vars)
  dEi_dAi = tf.gradients(expectation_one_frame, sampled_attention)
  dSumwiEi_wi = expectation_one_frame
  
  # After compute the final predictions
  dL_dWclassifier = tf.gradients(loss, c_vars)
  dL_dSumwiEi = tf.gradients(loss, estimation_for_whole_image)
  
  
  # lets do backprop by hand orz
  print("dL/dSumwiEi: ", dL_dSumwiEi)
  print("dSumwiEi/dEi: ", dSumwiEi_dEi)
  print("dEi/dWfe: ", dEi_dWfe)
  
  #print(dEi_dAi)
  #dL_dWfe = dL_dSumwiEi[0] * dSumwiEi_dEi * dEi_dAi * dAi_dW_att
  
  sess = tf.Session()
  init = tf.global_variables_initializer()
  sess.run(init)
  </code></pre>