@@ -117,19 +117,44 @@ public static Tensor[] _GradientsHelper(Tensor[] ys,
117117 Tensor [ ] in_grads = null ;
118118 var is_partitioned_call = _IsPartitionedCall ( op ) ;
119119 var is_func_call = false ;
120- var has_out_grads = true ;
120+ var has_out_grads = out_grads . Exists ( x => x != null ) ;
121121 if ( has_out_grads && ! stop_ops . Contains ( op ) )
122122 {
123123 // A grad_fn must be defined, either as a function or as None
124124 // for ops that do not have gradients.
125- var grad_fn = ops . get_gradient_function ( op ) ;
126125
127- if ( is_func_call )
126+ Func < Operation , Tensor [ ] , Tensor [ ] > grad_fn = null ;
127+ try
128128 {
129+ grad_fn = ops . get_gradient_function ( op ) ;
130+ }
131+ catch ( LookupError )
132+ {
133+ if ( is_func_call )
134+ {
135+ if ( is_partitioned_call )
136+ {
129137
138+ }
139+ else
140+ {
141+
142+ }
143+ }
144+ else
145+ {
146+ throw new LookupError ( $ "No gradient defined for operation '{ op . name } ' (op type: { op . type } )") ;
147+ }
130148 }
131- else
149+
150+ // if (loop_state)
151+ //loop_state.EnterGradWhileContext(op, before: false);
152+
153+ if ( ( is_func_call || grad_fn != null ) && has_out_grads )
132154 {
155+ // NOTE: If _AggregatedGrads didn't compute a value for the i'th
156+ // output, it means that the cost does not depend on output[i],
157+ // therefore dC/doutput[i] is 0.
133158 foreach ( var ( i , out_grad ) in enumerate ( out_grads ) )
134159 {
135160 if ( out_grad == null )
@@ -143,20 +168,24 @@ public static Tensor[] _GradientsHelper(Tensor[] ys,
143168
144169 tf_with ( ops . name_scope ( op . name + "_grad" ) , scope1 =>
145170 {
146- string name1 = scope1 ;
147171 if ( grad_fn != null )
148172 {
149173 in_grads = _MaybeCompile ( grad_scope , op , out_grads . Select ( x => x [ 0 ] ) . ToArray ( ) , null , grad_fn ) ;
150- _VerifyGeneratedGradients ( in_grads , op ) ;
151174 }
152-
175+ _VerifyGeneratedGradients ( in_grads , op ) ;
153176 if ( gate_gradients && in_grads . Count ( x => x != null ) > 1 )
154177 {
155178 ops . _colocate_with_for_gradient ( null , gradient_uid , ignore_existing : true ) ;
156179 in_grads = control_flow_ops . tuple ( in_grads ) ;
157180 }
158181 } ) ;
159182 }
183+ else
184+ {
185+ // If no grad_fn is defined or none of out_grads is available,
186+ // just propagate a list of None backwards.
187+ in_grads = new Tensor [ _NonEagerInputs ( op , xs ) . Count ( ) ] ;
188+ }
160189 }
161190 else
162191 {
0 commit comments