| @@ -27,6 +27,9 @@ namespace Tensorflow | |||||
| public void add_to_collections<T>(List<string> names, T value) | public void add_to_collections<T>(List<string> names, T value) | ||||
| => get_default_graph().add_to_collections(names, value); | => get_default_graph().add_to_collections(names, value); | ||||
| public (Tensors, Tensor) clip_by_global_norm(Tensor[] t_list, float clip_norm, Tensor use_norm = null, string name = null) | |||||
| => clip_ops.clip_by_global_norm(t_list, clip_norm, use_norm: use_norm, name: name); | |||||
| public Tensor assign(IVariableV1 @ref, object value, bool validate_shape = true, bool use_locking = true, string name = null) | public Tensor assign(IVariableV1 @ref, object value, bool validate_shape = true, bool use_locking = true, string name = null) | ||||
| => state_ops.assign(@ref, value, validate_shape, use_locking, name); | => state_ops.assign(@ref, value, validate_shape, use_locking, name); | ||||
| @@ -21,6 +21,27 @@ namespace Tensorflow | |||||
| { | { | ||||
| public class clip_ops | public class clip_ops | ||||
| { | { | ||||
| public static (Tensors, Tensor) clip_by_global_norm(Tensor[] t_list, float clip_norm, Tensor use_norm = null, string name = null) | |||||
| { | |||||
| use_norm = global_norm(t_list, name); | |||||
| return tf_with(ops.name_scope(name, "clip_by_global_norm", t_list), delegate | |||||
| { | |||||
| // Calculate L2-norm, clip elements by ratio of clip_norm to L2-norm | |||||
| var scale_for_finite = clip_norm * math_ops.minimum( | |||||
| 1.0f / use_norm, | |||||
| constant_op.constant(1.0, dtype: use_norm.dtype) / clip_norm); | |||||
| // If use_norm is any finite number, this is a no-op. For inf/-inf/NaN, | |||||
| // this will make scale NaN. | |||||
| var scale = scale_for_finite + (use_norm - use_norm); | |||||
| Tensors values_clipped = new Tensors(); | |||||
| foreach (var (i, v) in enumerate(t_list)) | |||||
| values_clipped.Add(array_ops.identity(v * scale, name: $"{name}_{i}")); | |||||
| return (values_clipped, use_norm); | |||||
| }); | |||||
| } | |||||
| public static Tensor clip_by_value<T1, T2>(Tensor t, T1 clip_value_min, T2 clip_value_max, string name = null) | public static Tensor clip_by_value<T1, T2>(Tensor t, T1 clip_value_min, T2 clip_value_max, string name = null) | ||||
| { | { | ||||
| return tf_with(ops.name_scope(name, "clip_by_value", new { t, clip_value_min, clip_value_max }), delegate | return tf_with(ops.name_scope(name, "clip_by_value", new { t, clip_value_min, clip_value_max }), delegate | ||||
| @@ -0,0 +1,21 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using static Tensorflow.Binding; | |||||
| using Tensorflow; | |||||
| namespace TensorFlowNET.UnitTest.ClipOps | |||||
| { | |||||
| [TestClass] | |||||
| public class ClipTest : EagerModeTestBase | |||||
| { | |||||
| [TestMethod] | |||||
| public void clip_by_global_norm() | |||||
| { | |||||
| var t_list = new Tensors(tf.constant(new float[] { 1, 2, 3, 4 }), tf.constant(new float[] { 5, 6, 7, 8 })); | |||||
| var clip_norm = .8f; | |||||
| var (res, norm) = tf.clip_by_global_norm(t_list, clip_norm); | |||||
| Equal(res[0].ToArray<float>(), new[] { 0.0560112074f, 0.112022415f, 0.16803363f, 0.22404483f }); | |||||
| Equal(res[1].ToArray<float>(), new[] { 0.28005603f, 0.336067259f, 0.392078459f, 0.448089659f }); | |||||
| Assert.AreEqual(norm.numpy(), 14.282857f); | |||||
| } | |||||
| } | |||||
| } | |||||