Skip to content

Commit 75ae2e9

Browse files
committed
RegisterNoGradient, LookupError
1 parent 8b0e5cf commit 75ae2e9

14 files changed

Lines changed: 279 additions & 27 deletions

File tree

src/TensorFlowNET.Core/APIs/tf.math.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,17 +431,19 @@ public Tensor reduce_prod(Tensor input_tensor, int[] axis = null, bool keepdims
431431
/// <param name="input"></param>
432432
/// <param name="axis"></param>
433433
/// <returns></returns>
434-
public Tensor reduce_sum(Tensor input, int? axis = null, int? reduction_indices = null)
434+
public Tensor reduce_sum(Tensor input, int? axis = null, int? reduction_indices = null,
435+
bool keepdims = false, string name = null)
435436
{
436437
if(!axis.HasValue && reduction_indices.HasValue)
437438
return math_ops.reduce_sum(input, reduction_indices.Value);
438439
else if (axis.HasValue && !reduction_indices.HasValue)
439440
return math_ops.reduce_sum(input, axis.Value);
440-
return math_ops.reduce_sum(input);
441+
return math_ops.reduce_sum(input, keepdims: keepdims, name: name);
441442
}
442443

443-
public Tensor reduce_sum(Tensor input, int[] axis, int? reduction_indices = null)
444-
=> math_ops.reduce_sum(input, axis);
444+
public Tensor reduce_sum(Tensor input, int[] axis, int? reduction_indices = null,
445+
bool keepdims = false, string name = null)
446+
=> math_ops.reduce_sum(input, axis, keepdims: keepdims, name: name);
445447

446448
/// <summary>
447449
/// Computes the maximum of elements across dimensions of a tensor.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace Tensorflow
4+
{
5+
public class LookupError : TensorflowException
6+
{
7+
public LookupError() : base()
8+
{
9+
10+
}
11+
12+
public LookupError(string message) : base(message)
13+
{
14+
15+
}
16+
}
17+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*****************************************************************************
2+
Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
******************************************************************************/
16+
17+
using System;
18+
19+
namespace Tensorflow.Gradients
20+
{
21+
/// <summary>
22+
/// REGISTER_NO_GRADIENT_OP("");
23+
/// </summary>
24+
public class RegisterNoGradient : Attribute
25+
{
26+
public string Name { get; set; }
27+
28+
public RegisterNoGradient(string name)
29+
{
30+
Name = name;
31+
}
32+
}
33+
}

src/TensorFlowNET.Core/Gradients/gradients_util.cs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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
{

src/TensorFlowNET.Core/Gradients/math_grad.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,11 @@ public static Tensor[] _ExpGrad(Operation op, Tensor[] grads)
9696
});
9797
}
9898

99-
[RegisterGradient("GreaterEqual")]
100-
public static Tensor[] _GreaterEqualGrad(Operation op, Tensor[] grads)
101-
{
102-
var grad = grads[0];
103-
throw new NotImplementedException("_GreaterEqualGrad");
104-
}
99+
[RegisterNoGradient("GreaterEqual")]
100+
public static Tensor[] _GreaterEqualGrad(Operation op, Tensor[] grads) => null;
101+
102+
[RegisterNoGradient("ZerosLike")]
103+
public static Tensor[] _ZerosLike(Operation op, Tensor[] grads) => null;
105104

106105
[RegisterGradient("Identity")]
107106
public static Tensor[] _IdGrad(Operation op, Tensor[] grads)
@@ -415,7 +414,9 @@ public static Tensor[] _SumGrad(Operation op, Tensor[] grads)
415414
var rank = input_0_shape.Length;
416415
if (Enumerable.SequenceEqual(Enumerable.Range(0, rank), axes.Data<int>()))
417416
{
418-
grad = array_ops.reshape(grad, new int[] { 1 });
417+
var new_shape = range(rank).Select(x => 1).ToArray();
418+
grad = array_ops.reshape(grad, new_shape);
419+
// If shape is not fully defined (but rank is), we use Shape.
419420
if (!input_0_shape.Contains(-1))
420421
input_shape = constant_op.constant(input_0_shape);
421422
else

src/TensorFlowNET.Core/Gradients/ops.gradient_function_mapping.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ public static void RegisterGradientFunction(string name, Func<Operation, Tensor[
3939
gradientFunctions[name] = func;
4040
}
4141

42+
public static void RegisterNoGradientFunction(string name)
43+
{
44+
if (gradientFunctions == null)
45+
gradientFunctions = new Dictionary<string, Func<Operation, Tensor[], Tensor[]>>();
46+
47+
gradientFunctions[name] = null;
48+
}
49+
4250
public static Func<Operation, Tensor[], Tensor[]> get_gradient_function(Operation op)
4351
{
4452
if (op.inputs == null) return null;
@@ -68,11 +76,18 @@ public static Func<Operation, Tensor[], Tensor[]> get_gradient_function(Operatio
6876
args: new object[] { oper, out_grads }) as Tensor[]
6977
);
7078
}
79+
80+
// REGISTER_NO_GRADIENT_OP
81+
methods = g.GetMethods().Where(x => x.GetCustomAttribute<RegisterNoGradient>() != null)
82+
.ToArray();
83+
84+
foreach (var m in methods)
85+
RegisterNoGradientFunction(m.GetCustomAttribute<RegisterNoGradient>().Name);
7186
}
7287
}
7388

7489
if (!gradientFunctions.ContainsKey(op.type))
75-
throw new NotImplementedException($"can't get graident function through get_gradient_function {op.type}");
90+
throw new LookupError($"can't get graident function through get_gradient_function {op.type}");
7691

7792
return gradientFunctions[op.type];
7893
}

src/TensorFlowNET.Core/Operations/nn_impl.py.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ private static Tensor _count_nonzero(Tensor input_tensor, TF_DataType dtype = TF
154154

155155
public static Tensor sigmoid_cross_entropy_with_logits(Tensor labels, Tensor logits, string name = null)
156156
{
157-
return tf_with(ops.name_scope(name, "", new { }), scope =>
157+
return tf_with(ops.name_scope(name, "logistic_loss", new { logits, labels }), scope =>
158158
{
159159
name = scope;
160160
logits = ops.convert_to_tensor(logits, name: "logits");

src/TensorFlowNET.Core/TensorFlowNET.Core.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
Docs: https://tensorflownet.readthedocs.io</Description>
2020
<AssemblyVersion>0.11.4.0</AssemblyVersion>
2121
<PackageReleaseNotes>Changes since v0.10.0:
22-
1. Upgrade NumSharp to v0.20.
22+
1. Upgrade NumSharp to v0.20.3.
2323
2. Add DisposableObject class to manage object lifetime.
2424
3. Add tf.no_op, tf.nn.in_top_k, tf.GraphKeys and tf.trainable_variables.
2525
4. Change tensorflow to non-static class in order to execute some initialization process.
@@ -28,7 +28,8 @@ Docs: https://tensorflownet.readthedocs.io</Description>
2828
7. Add tf.image related APIs.
2929
8. Add tf.random_normal, tf.constant, tf.pad, tf.shape, tf.image.resize_nearest_neighbor.
3030
9. MultiThread is safe.
31-
10. Support n-dim indexing for tensor.</PackageReleaseNotes>
31+
10. Support n-dim indexing for tensor.
32+
11. Add RegisterNoGradient</PackageReleaseNotes>
3233
<LangVersion>7.3</LangVersion>
3334
<FileVersion>0.11.4.0</FileVersion>
3435
<PackageLicenseFile>LICENSE</PackageLicenseFile>
@@ -62,7 +63,7 @@ Docs: https://tensorflownet.readthedocs.io</Description>
6263

6364
<ItemGroup>
6465
<PackageReference Include="Google.Protobuf" Version="3.5.1" />
65-
<PackageReference Include="NumSharp" Version="0.20.2" />
66+
<PackageReference Include="NumSharp" Version="0.20.3" />
6667
</ItemGroup>
6768

6869
<ItemGroup>

src/TensorFlowNet.Benchmarks/TensorFlowBenchmark.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>netcoreapp2.2</TargetFramework>
5+
<TargetFramework>netcoreapp3.0</TargetFramework>
66
<NoWin32Manifest>true</NoWin32Manifest>
77
<AssemblyName>TensorFlowBenchmark</AssemblyName>
88
<RootNamespace>TensorFlowBenchmark</RootNamespace>

0 commit comments

Comments
 (0)