@@ -36,56 +36,54 @@ public class control_flow_grad
3636 /// </summary>
3737 /// <returns></returns>
3838 [ RegisterGradient ( "Switch" ) ]
39- public Tensor [ ] _SwitchGrad ( Operation op , Tensor [ ] grads )
39+ public static Tensor [ ] _SwitchGrad ( Operation op , Tensor [ ] grads )
4040 {
41+ var grad = grads [ 0 ] ;
42+ var graph = ops . get_default_graph ( ) ;
43+ var op_ctxt = op . _get_control_flow_context ( ) ;
44+ var grad_ctxt = graph . _get_control_flow_context ( ) ;
45+ switch ( op_ctxt )
46+ {
47+ case WhileContext cwhile :
48+ throw new NotImplementedException ( "_SwitchGrad WhileContext" ) ;
49+ case CondContext ccond :
50+ {
51+ var zero_grad = grads [ 1 - op_ctxt . branch ] ;
52+ // At this point, we have created zero_grad guarded by the right switch.
53+ // Unfortunately, we may still get None here for not trainable data types.
54+ if ( zero_grad == null )
55+ {
56+ throw new NotImplementedException ( "_SwitchGrad CondContext zero_grad" ) ;
57+ }
58+
59+ return new Tensor [ ]
60+ {
61+ merge ( grads , name : "cond_grad" ) [ 0 ] ,
62+ null
63+ } ;
64+ }
65+ default :
66+ throw new NotImplementedException ( "_SwitchGrad WhileContext" ) ;
67+ }
4168 throw new NotImplementedException ( "_SwitchGrad" ) ;
42- //graph = ops.get_default_graph()
43- //# pylint: disable=protected-access
44- //op_ctxt = op._get_control_flow_context()
45- //grad_ctxt = graph._get_control_flow_context()
46- //# pylint: enable=protected-access
47- //if isinstance(op_ctxt, WhileContext):
48- // merge_grad = grad_ctxt.grad_state.switch_map.get(op)
49- // if merge_grad is not None:
50- // # This is the second time this Switch is visited. It comes from
51- // # the non-exit branch of the Switch, so update the second input
52- // # to the Merge.
53- // # TODO(yuanbyu): Perform shape inference with this new input.
54- // if grad[1] is not None:
55- // # pylint: disable=protected-access
56- // control_flow_ops._AddNextAndBackEdge(merge_grad, grad[1],
57- // enforce_shape_invariant=False)
58- // # pylint: enable=protected-access
59- // return None, None
60- // elif grad[0] is not None:
61- // # This is the first time this Switch is visited. It comes from
62- // # the Exit branch, which is grad[0]. grad[1] is empty at this point.
63- // # Use grad[0] for both inputs to merge for now, but update the second
64- // # input of merge when we see this Switch the second time.
65- // merge_grad = merge([grad[0], grad[0]], name="b_switch")[0]
66- // grad_ctxt.grad_state.switch_map[op] = merge_grad
67- // return merge_grad, None
68- // else:
69- // # This is the first time this Switch is visited. It comes from the
70- // # Identity branch. Such a Switch has `None` gradient for the Exit branch,
71- // # meaning the output is not differentiable.
72- // return None, None
73- //elif isinstance(op_ctxt, CondContext):
74- // zero_grad = grad[1 - op_ctxt.branch]
75- // # At this point, we have created zero_grad guarded by the right switch.
76- // # Unfortunately, we may still get None here for not trainable data types.
77- // if zero_grad is None:
78- // # For resource variables we get None always on the other branch, so bypass
79- // # this.
80- // if op.inputs[0].dtype == dtypes.resource:
81- // return merge(
82- // [grad[op_ctxt.branch]] * 2, name="cond_resource_grad")[0], None
83- // return None, None
84- // return merge(grad, name="cond_grad")[0], None
85- //else:
86- // false_grad = switch(grad[0], op.inputs[1])[0]
87- // true_grad = switch(grad[1], op.inputs[1])[1]
88- // return merge([false_grad, true_grad])[0], None
69+ }
70+
71+ /// <summary>
72+ /// Returns the value of an available element of `inputs`.
73+ /// </summary>
74+ /// <param name="inputs"></param>
75+ /// <param name="name"></param>
76+ /// <returns></returns>
77+ internal static Tensor [ ] merge ( Tensor [ ] inputs , string name = null )
78+ {
79+ return tf_with ( ops . name_scope ( name , "Merge" , inputs ) , scope =>
80+ {
81+ name = scope ;
82+ if ( inputs . Count ( x => x . dtype . is_ref_dtype ( ) ) == inputs . Length )
83+ return gen_control_flow_ops . ref_merge ( inputs , name : name ) ;
84+ else
85+ return gen_control_flow_ops . merge ( inputs , name : name ) ;
86+ } ) ;
8987 }
9088
9189 /// <summary>
0 commit comments