| @@ -90,7 +90,7 @@ namespace Tensorflow.Gradients | |||||
| in_gradients = trace.backward_function(out_gradients.ToArray(), unneeded_gradients.ToArray()); | in_gradients = trace.backward_function(out_gradients.ToArray(), unneeded_gradients.ToArray()); | ||||
| if (in_gradients.Count() != trace.input_tensor_id.Count()) | |||||
| if (in_gradients.Length != trace.input_tensor_id.Length && in_gradients.Length + unneeded_gradients.Count != trace.input_tensor_id.Length) | |||||
| throw new RuntimeError($"Recorded operation '{trace.op_type}' returned too few gradients. Expected {trace.input_tensor_id.Length} but received {in_gradients.Count()}"); | throw new RuntimeError($"Recorded operation '{trace.op_type}' returned too few gradients. Expected {trace.input_tensor_id.Length} but received {in_gradients.Count()}"); | ||||
| if (!_persistent) | if (!_persistent) | ||||
| { | { | ||||
| @@ -103,9 +103,11 @@ namespace Tensorflow.Gradients | |||||
| in_gradients = new Tensor[trace.input_tensor_id.Length]; | in_gradients = new Tensor[trace.input_tensor_id.Length]; | ||||
| } | } | ||||
| for (int i = 0; i < in_gradients.Length; ++i) | |||||
| bool skip_unneeded_id = trace.input_tensor_id.Length > in_gradients.Length; | |||||
| for (int i = 0, k = 0; i < in_gradients.Length && k < trace.input_tensor_id.Count(); ++i, ++k) | |||||
| { | { | ||||
| var id = trace.input_tensor_id[i]; | |||||
| if (skip_unneeded_id && unneeded_gradients.Contains(k)) ++k; | |||||
| var id = trace.input_tensor_id[k]; | |||||
| if (in_gradients[i] != null) | if (in_gradients[i] != null) | ||||
| { | { | ||||
| var unaggregated_grads = gradients[id]; | var unaggregated_grads = gradients[id]; | ||||
| @@ -639,6 +639,20 @@ namespace Tensorflow.Gradients | |||||
| }); | }); | ||||
| } | } | ||||
| [RegisterGradient("Rsqrt")] | |||||
| public static Tensor[] _RsqrtGrad(Operation op, Tensor[] grads) | |||||
| { | |||||
| var grad = grads[0]; | |||||
| var y = op.outputs[0]; | |||||
| return tf_with(ops.control_dependencies(grads), delegate | |||||
| { | |||||
| y = math_ops.conj(y); | |||||
| var factor = constant_op.constant(-0.5f, dtype: y.dtype); | |||||
| return new Tensor[] { grad * (factor * math_ops.square(y) * y) }; | |||||
| }); | |||||
| } | |||||
| [RegisterGradient("Asin")] | [RegisterGradient("Asin")] | ||||
| public static Tensor[] _ASinGrad(Operation op, Tensor[] grads) | public static Tensor[] _ASinGrad(Operation op, Tensor[] grads) | ||||
| { | { | ||||
| @@ -55,6 +55,20 @@ namespace Tensorflow.Keras.Layers | |||||
| IRegularizer bias_regularizer = null, | IRegularizer bias_regularizer = null, | ||||
| IRegularizer activity_regularizer = null); | IRegularizer activity_regularizer = null); | ||||
| public ILayer Conv2DTranspose(int filters, | |||||
| Shape kernel_size = null, | |||||
| Shape strides = null, | |||||
| string output_padding = "valid", | |||||
| string data_format = null, | |||||
| Shape dilation_rate = null, | |||||
| string activation = null, | |||||
| bool use_bias = true, | |||||
| string kernel_initializer = null, | |||||
| string bias_initializer = null, | |||||
| string kernel_regularizer = null, | |||||
| string bias_regularizer = null, | |||||
| string activity_regularizer = null); | |||||
| public ILayer Conv2D(int filters, | public ILayer Conv2D(int filters, | ||||
| Shape kernel_size = null, | Shape kernel_size = null, | ||||
| Shape strides = null, | Shape strides = null, | ||||