Skip to content

Commit 58d714b

Browse files
committed
add _ResizeNearestNeighborGrad and _SwitchGrad
1 parent 9e414f4 commit 58d714b

10 files changed

Lines changed: 152 additions & 56 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public Saver import_meta_graph(string meta_graph_or_file,
5454
clear_devices,
5555
import_scope).Item1;
5656

57-
public (MetaGraphDef, Dictionary<string, RefVariable>) export_meta_graph(string filename = "",
57+
public (MetaGraphDef, Dictionary<string, VariableV1>) export_meta_graph(string filename = "",
5858
bool as_text = false,
5959
bool clear_devices = false,
6060
bool clear_extraneous_savers = false,

src/TensorFlowNET.Core/Framework/meta_graph.py.cs renamed to src/TensorFlowNET.Core/Framework/meta_graph.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public static (Dictionary<string, VariableV1>, ITensorOrOperation[]) import_scop
167167
/// <param name="strip_default_attrs"></param>
168168
/// <param name="meta_info_def"></param>
169169
/// <returns></returns>
170-
public static (MetaGraphDef, Dictionary<string, RefVariable>) export_scoped_meta_graph(string filename = "",
170+
public static (MetaGraphDef, Dictionary<string, VariableV1>) export_scoped_meta_graph(string filename = "",
171171
GraphDef graph_def = null,
172172
bool as_text = false,
173173
string unbound_inputs_col_name = "unbound_inputs",
@@ -179,8 +179,8 @@ public static (MetaGraphDef, Dictionary<string, RefVariable>) export_scoped_meta
179179
{
180180
var graph = ops.get_default_graph();
181181

182-
var var_list = new Dictionary<string, RefVariable>();
183-
var variables = graph.get_collection<RefVariable>(tf.GraphKeys.GLOBAL_VARIABLES);
182+
var var_list = new Dictionary<string, VariableV1>();
183+
var variables = graph.get_collection<VariableV1>(tf.GraphKeys.GLOBAL_VARIABLES);
184184

185185
if (variables != null)
186186
{

src/TensorFlowNET.Core/Gradients/array_grad.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,26 @@ public static Tensor[] _ReshapeGrad(Operation op, Tensor[] grads)
190190
return new Tensor[] { array_ops.reshape(grads[0], array_ops.shape(op.inputs[0])), null };
191191
}
192192

193+
[RegisterGradient("Pad")]
194+
public static Tensor[] _PadGrad(Operation op, Tensor[] grads)
195+
{
196+
var grad = grads[0];
197+
var x = op.inputs[0];
198+
var a = op.inputs[1];
199+
var pad_before = array_ops.slice(a, new[] { 0, 0 },
200+
new[] { array_ops.stack(new object[] { array_ops.rank(x), 1 }) });
201+
202+
// Make it a 1-D tensor.
203+
var begin = array_ops.reshape(pad_before, new[] { -1 });
204+
var sizes = array_ops.shape(x);
205+
var x_grad = array_ops.slice(grad, new[] { begin }, new[] { sizes });
206+
207+
if (len(op.inputs) == 3)
208+
return new Tensor[] { x_grad, null, null };
209+
else
210+
return new Tensor[] { x_grad, null };
211+
}
212+
193213
[RegisterGradient("Squeeze")]
194214
public static Tensor[] _SqueezeGrad(Operation op, Tensor[] grads)
195215
{

src/TensorFlowNET.Core/Gradients/control_flow_grad.cs

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

src/TensorFlowNET.Core/Gradients/gradients_util.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public static Tensor[] _GradientsHelper(Tensor[] ys,
108108
{
109109
// generate gradient subgraph for op.
110110
var op = queue.Dequeue();
111-
if(tf.get_default_graph()._nodes_by_name.Count > 18577)
111+
if(tf.get_default_graph()._nodes_by_name.Count >= 20611)
112112
{
113113

114114
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
using System.Collections.Generic;
19+
using System.Linq;
20+
using System.Text;
21+
using Tensorflow.Framework;
22+
using static Tensorflow.Binding;
23+
24+
namespace Tensorflow.Gradients
25+
{
26+
[RegisterGradient("image_grad")]
27+
public class image_grad
28+
{
29+
[RegisterGradient("ResizeNearestNeighbor")]
30+
public static Tensor[] _ResizeNearestNeighborGrad(Operation op, Tensor[] grads)
31+
{
32+
var grad = grads[0];
33+
var image = op.inputs[0];
34+
var shape = new TensorShape(image.shape.Skip(1).Take(2).ToArray());
35+
Tensor image_shape = null;
36+
if (shape.is_fully_defined())
37+
throw new NotImplementedException("_ResizeNearestNeighborGrad shape.is_fully_defined");
38+
else
39+
image_shape = array_ops.shape(image)["1:3"];
40+
41+
grad = gen_image_ops.resize_nearest_neighbor_grad(
42+
grad,
43+
image_shape,
44+
align_corners: op.get_attr<bool>("align_corners"),
45+
half_pixel_centers: op.get_attr<bool>("half_pixel_centers"));
46+
47+
return new Tensor[]
48+
{
49+
grad,
50+
null
51+
};
52+
}
53+
}
54+
}

src/TensorFlowNET.Core/Graphs/Graph.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,9 @@ public List<T> get_collection<T>(string name, string scope = null)
440440
case List<VariableV1> list:
441441
t = list.Select(x => (T)(object)x).ToList();
442442
break;
443+
case List<ResourceVariable> list:
444+
t = list.Select(x => (T)(object)x).ToList();
445+
break;
443446
case List<RefVariable> list:
444447
t = list.Select(x => (T)(object)x).ToList();
445448
break;

src/TensorFlowNET.Core/Operations/control_flow_ops.py.cs renamed to src/TensorFlowNET.Core/Operations/control_flow_ops.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ public static Tensor merge(Tensor[] inputs, string name = null)
518518
inputs = inputs.Select(inp =>
519519
ops.internal_convert_to_tensor_or_indexed_slices(inp, as_ref: true))
520520
.ToArray();
521-
return gen_control_flow_ops.merge(inputs, name).Item1;
521+
return gen_control_flow_ops.merge(inputs, name)[0];
522522
});
523523
}
524524

src/TensorFlowNET.Core/Operations/gen_control_flow_ops.py.cs renamed to src/TensorFlowNET.Core/Operations/gen_control_flow_ops.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,18 @@ public static Tensor[] @switch(Tensor data, Tensor pred, string name = null)
148148
return new []{_op.outputs[0], _op.outputs[1]};
149149
}
150150

151-
public static (Tensor, Tensor) merge(Tensor[] inputs, string name = null)
151+
public static Tensor[] ref_merge(Tensor[] inputs, string name = null)
152+
{
153+
var _op = _op_def_lib._apply_op_helper("RefMerge", name, new { inputs });
154+
155+
return _op.outputs;
156+
}
157+
158+
public static Tensor[] merge(Tensor[] inputs, string name = null)
152159
{
153160
var _op = _op_def_lib._apply_op_helper("Merge", name, new { inputs });
154161

155-
return (_op.outputs[0], _op.outputs[1]);
162+
return _op.outputs;
156163
}
157164
}
158165
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,19 @@ public static Tensor resize_nearest_neighbor<Tsize>(Tensor images, Tsize size, b
183183

184184
return op.output;
185185
}
186+
187+
public static Tensor resize_nearest_neighbor_grad<Tsize>(Tensor grads, Tsize size, bool align_corners = false,
188+
bool half_pixel_centers = false, string name = null)
189+
{
190+
var op = _op_def_lib._apply_op_helper("ResizeNearestNeighborGrad", name: name, args: new
191+
{
192+
grads,
193+
size,
194+
align_corners,
195+
half_pixel_centers
196+
});
197+
198+
return op.output;
199+
}
186200
}
187201
}

0 commit comments

Comments
 (0)