| @@ -217,7 +217,7 @@ namespace Tensorflow | |||
| Tensor off_value = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| int axis = -1, | |||
| string name = null) => array_ops.one_hot(indices, depth, dtype: dtype, axis: axis, name: name); | |||
| string name = null) => array_ops.one_hot(indices, ops.convert_to_tensor(depth), dtype: dtype, axis: axis, name: name); | |||
| /// <summary> | |||
| /// Pads a tensor | |||
| @@ -21,6 +21,13 @@ namespace Tensorflow | |||
| { | |||
| public partial class tensorflow | |||
| { | |||
| public MathApi math { get; } = new MathApi(); | |||
| public class MathApi | |||
| { | |||
| public Tensor log(Tensor x, string name = null) | |||
| => gen_math_ops.log(x, name); | |||
| } | |||
| public Tensor abs(Tensor x, string name = null) | |||
| => math_ops.abs(x, name); | |||
| @@ -254,7 +261,7 @@ namespace Tensorflow | |||
| /// Any values less than <c>clip_value_min</c> are set to <c>clip_value_min</c>. Any values | |||
| /// greater than <c>clip_value_max</c> are set to <c>clip_value_max</c>. | |||
| /// </remarks> | |||
| public Tensor clip_by_value (Tensor t, Tensor clip_value_min, Tensor clip_value_max, string name = "ClipByValue") | |||
| public Tensor clip_by_value<T1, T2>(Tensor t, T1 clip_value_min, T2 clip_value_max, string name = "ClipByValue") | |||
| => clip_ops.clip_by_value(t, clip_value_min, clip_value_max, name); | |||
| public Tensor sub<Tx, Ty>(Tx a, Ty b, string name = null) | |||
| @@ -14,6 +14,7 @@ | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using System; | |||
| using Tensorflow.Operations; | |||
| using Tensorflow.Operations.Activation; | |||
| using static Tensorflow.Binding; | |||
| @@ -182,7 +183,13 @@ namespace Tensorflow | |||
| => nn_impl.sigmoid_cross_entropy_with_logits(labels: labels, logits: logits, name: name); | |||
| public Tensor softmax(Tensor logits, int axis = -1, string name = null) | |||
| => gen_nn_ops.softmax(logits, name); | |||
| { | |||
| if (axis == -1) | |||
| return gen_nn_ops.softmax(logits, name); | |||
| else | |||
| throw new NotImplementedException(""); | |||
| } | |||
| /// <summary> | |||
| /// Computes sparse softmax cross entropy between `logits` and `labels`. | |||
| @@ -18,7 +18,7 @@ namespace Tensorflow.Eager | |||
| public Tensor[] Outputs { get; set; } | |||
| public BindingArray SkipInputIndicesArray { get; set; } | |||
| public unsafe int[] SkipInputIndices => SkipInputIndicesArray.Data.Select(x => *(int*) x).ToArray(); | |||
| public BindingArray AttrsArray { get; set; } | |||
| public string[] AttrsArray { get; set; } | |||
| public EagerOperation() : base(IntPtr.Zero) | |||
| { | |||
| @@ -70,14 +70,11 @@ namespace Tensorflow.Eager | |||
| return value; | |||
| } | |||
| public bool get_attr_bool(string attr_name) | |||
| public bool get_attr_bool(string attr_name) | |||
| { | |||
| for (int i = 0; i < AttrsArray.Data.Length; i = i + 2) | |||
| { | |||
| // var a = *(char*)AttrsArray.Data[i]; | |||
| if (op_dict[Name].Attr[i].Name == attr_name) | |||
| return (int)AttrsArray.Data[i + 1] == 1; | |||
| } | |||
| for (int i = 0; i < AttrsArray.Length; i = i + 2) | |||
| if (AttrsArray[i] == attr_name) | |||
| return AttrsArray[i + 1] == "1"; | |||
| throw new ValueError($"Can't find attr: {attr_name}"); | |||
| } | |||
| @@ -2,6 +2,7 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.Threading; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow.Eager | |||
| @@ -49,6 +50,10 @@ namespace Tensorflow.Eager | |||
| print($"new TensorHandle {Id} {tfe_tensor_handle.ToString("x16")}"); | |||
| print($"new EagerTensor {Id} {EagerTensorHandle.ToString("x16")}");*/ | |||
| if (tfe_tensor_handle == IntPtr.Zero && _id == 0) | |||
| { | |||
| } | |||
| GarbageCollector.Increase(_handle, GCItemType.TensorHandle); | |||
| GarbageCollector.Increase(tfe_tensor_handle, GCItemType.LocalTensorHandle); | |||
| GarbageCollector.Increase(EagerTensorHandle, GCItemType.EagerTensorHandle); | |||
| @@ -56,6 +61,9 @@ namespace Tensorflow.Eager | |||
| return this; | |||
| } | |||
| public override IntPtr ToPointer() | |||
| => EagerTensorHandle; | |||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||
| { | |||
| GarbageCollector.Decrease(_handle); | |||
| @@ -13,7 +13,7 @@ namespace Tensorflow.Eager | |||
| public IntPtr EagerTensorHandle { get; set; } | |||
| public override string Device => c_api.StringPiece(c_api.TFE_TensorHandleDeviceName(tfe_tensor_handle, status)); | |||
| // public override int rank => c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status); | |||
| public override int rank => c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status); | |||
| public static int GetRank(IntPtr handle) | |||
| { | |||
| @@ -25,7 +25,7 @@ namespace Tensorflow | |||
| public delegate IntPtr gradient_function_callback(string op_name, | |||
| IntPtr op_inputs, | |||
| IntPtr op_outputs, | |||
| IntPtr attrs_handle, | |||
| string attrs_string, | |||
| IntPtr output_grads, | |||
| IntPtr skip_input_indices); | |||
| @@ -402,6 +402,7 @@ namespace Tensorflow | |||
| string name, | |||
| IntPtr[] inputs, | |||
| int input_size, | |||
| string attrs_string, | |||
| TFE_FastPathExecute_SetOpAttrs set_op_attrs, | |||
| IntPtr[] outputs, | |||
| int output_size); | |||
| @@ -31,6 +31,37 @@ namespace Tensorflow.Eager | |||
| } | |||
| } | |||
| public static string SetOpAttrs2(params object[] attrs) | |||
| { | |||
| string attr_string = string.Empty; | |||
| for(int i = 0; i < attrs.Length; i = i + 2) | |||
| { | |||
| object key = attrs[i]; | |||
| object value = attrs[i + 1]; | |||
| switch (value) | |||
| { | |||
| case TF_DataType dtype: | |||
| value = (int)dtype; | |||
| break; | |||
| case bool bVal: | |||
| value = bVal ? 1 : 0; | |||
| break; | |||
| case int[] shape: | |||
| value = shape.Length == 0 ? "null" : string.Join(" ", shape); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| attr_string += string.IsNullOrEmpty(attr_string) ? | |||
| $"{key},{value}" : | |||
| $",{key},{value}"; | |||
| } | |||
| return attr_string; | |||
| } | |||
| /// <summary> | |||
| /// This function will set the op attrs required. If an attr has the value of | |||
| /// None, then it will read the AttrDef to get the default value and set that | |||
| @@ -3,6 +3,7 @@ using NumSharp.Utilities; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using System.Runtime.InteropServices; | |||
| using System.Text; | |||
| using Tensorflow.Eager; | |||
| @@ -79,15 +80,26 @@ namespace Tensorflow.Gradients | |||
| _pop_tape(); | |||
| } | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var targets = EagerTensorPass.From(target); | |||
| var sources = EagerTensorPass.From(source); | |||
| Status status = c_api.TFE_TapeGradient(_tape, | |||
| new[] { (target as EagerTensor).EagerTensorHandle }, 1, | |||
| new[] { (source as EagerTensor).EagerTensorHandle }, 1, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| targets.Points, targets.Length, | |||
| sources.Points, sources.Length, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| public Tensor gradient(Tensor target, ResourceVariable source) | |||
| { | |||
| var results = gradient(target as EagerTensor, new[] { source }); | |||
| return results[0]; | |||
| } | |||
| public (Tensor, Tensor) gradient(Tensor target, (ResourceVariable, ResourceVariable) sources) | |||
| { | |||
| var results = gradient(target as EagerTensor, new[] { sources.Item1, sources.Item2 }); | |||
| @@ -103,14 +115,14 @@ namespace Tensorflow.Gradients | |||
| _pop_tape(); | |||
| } | |||
| var results = sources.Select(x => new EagerTensor()).ToArray(); | |||
| var results = EagerTensorPass.Create(sources.Length); | |||
| var target_inputs = EagerTensorPass.From(target); | |||
| var source_inputs = EagerTensorPass.From(sources.Select(x => x.Handle).ToArray()); | |||
| Status status = c_api.TFE_TapeGradient(_tape, | |||
| new IntPtr[] | |||
| { | |||
| target.EagerTensorHandle | |||
| }, 1, | |||
| sources.Select(x => (x.Handle as EagerTensor).EagerTensorHandle).ToArray(), sources.Length, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| target_inputs.Points, target_inputs.Length, | |||
| source_inputs.Points, source_inputs.Length, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| if (!_persistent) | |||
| @@ -120,13 +132,15 @@ namespace Tensorflow.Gradients | |||
| _tape = null; | |||
| } | |||
| return results.Select(x => x.Resolve()).ToArray(); | |||
| return results.Items.Select(x => x.Resolve()).ToArray(); | |||
| } | |||
| public void Dispose() | |||
| { | |||
| if (_recording) | |||
| _pop_tape(); | |||
| tf.tensorMgr.Reset(); | |||
| } | |||
| } | |||
| } | |||
| @@ -310,23 +310,26 @@ namespace Tensorflow.Gradients | |||
| var input_shape = op.inputs[0]._shape_tuple(); | |||
| var output_shape = op.outputs[0]._shape_tuple(); | |||
| Tensor result, factor_tensor; | |||
| if(input_shape != null && | |||
| output_shape != null) | |||
| { | |||
| var input_size = np.prod(input_shape); | |||
| var output_size = np.prod(output_shape); | |||
| var factor = (int)input_size / Math.Max((int)output_size, 1); | |||
| var factor_tensor = constant_op.constant((int)input_size, dtype: sum_grad.dtype); | |||
| return new Tensor[] { math_ops.truediv(sum_grad, math_ops.cast(factor_tensor, sum_grad.dtype)), null }; | |||
| factor_tensor = constant_op.constant(factor, dtype: sum_grad.dtype); | |||
| } | |||
| else | |||
| { | |||
| var input_shape_tensor = array_ops.shape(op.inputs[0]); | |||
| var output_shape_tensor = array_ops.shape(op.outputs[0]); | |||
| var factor = _safe_shape_div(math_ops.reduce_prod(input_shape_tensor), math_ops.reduce_prod(output_shape_tensor)); | |||
| return new Tensor[] { math_ops.truediv(sum_grad, math_ops.cast(factor, sum_grad.dtype)), null }; | |||
| throw new NotImplementedException(""); | |||
| factor_tensor = null; | |||
| } | |||
| result = math_ops.truediv(sum_grad, math_ops.cast(factor_tensor, sum_grad.dtype)); | |||
| return new Tensor[] { result, null }; | |||
| } | |||
| /// <summary> | |||
| @@ -513,20 +516,23 @@ namespace Tensorflow.Gradients | |||
| input_shape = array_ops.shape(op.inputs[0]); | |||
| return new Tensor[] { gen_array_ops.tile(grad, input_shape), null }; | |||
| } | |||
| else | |||
| else if (!input_0_shape.Contains(-1) && !tf.context.executing_eagerly()) | |||
| { | |||
| throw new NotImplementedException(""); | |||
| } | |||
| } | |||
| } | |||
| input_shape = array_ops.shape(op.inputs[0]); | |||
| ops.colocate_with(input_shape); | |||
| var output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]); | |||
| var tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims); | |||
| grad = gen_array_ops.reshape(grad, output_shape_kept_dims); | |||
| if (!op.get_attr<bool>("keep_dims")) | |||
| { | |||
| ops.colocate_with(input_shape); | |||
| var output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]); | |||
| // var tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims); | |||
| grad = gen_array_ops.reshape(grad, output_shape_kept_dims); | |||
| } | |||
| return new Tensor[] { gen_array_ops.tile(grad, tile_scaling), null }; | |||
| return new Tensor[] { gen_array_ops.broadcast_to(grad, input_shape), null }; | |||
| } | |||
| [RegisterGradient("RealDiv")] | |||
| @@ -17,6 +17,7 @@ | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics.CodeAnalysis; | |||
| using System.Linq; | |||
| using Tensorflow.Eager; | |||
| using Tensorflow.Operations; | |||
| using static Tensorflow.Binding; | |||
| @@ -81,6 +82,9 @@ namespace Tensorflow | |||
| /// </summary> | |||
| public _ControlDependenciesController control_dependencies(object[] control_inputs) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| return new _ControlDependenciesController(this, null); | |||
| if (control_inputs == null) | |||
| return new _ControlDependenciesController(this, null); | |||
| @@ -0,0 +1,34 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class NullContextmanager : ITensorFlowObject | |||
| { | |||
| public void __init__() | |||
| { | |||
| throw new NotImplementedException(); | |||
| } | |||
| public void __enter__() | |||
| { | |||
| throw new NotImplementedException(); | |||
| } | |||
| public void __del__() | |||
| { | |||
| throw new NotImplementedException(); | |||
| } | |||
| public void __exit__() | |||
| { | |||
| throw new NotImplementedException(); | |||
| } | |||
| public void Dispose() | |||
| { | |||
| throw new NotImplementedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -373,6 +373,19 @@ namespace Tensorflow.Operations | |||
| public static Tensor relu_grad(Tensor gradients, Tensor features, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(gradients, features); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ReluGrad", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("ReluGrad", name: name, args: new | |||
| { | |||
| gradients, | |||
| @@ -396,6 +409,19 @@ namespace Tensorflow.Operations | |||
| public static Tensor softmax(Tensor logits, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(logits); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Softmax", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Softmax", name: name, args: new | |||
| { | |||
| logits | |||
| @@ -473,7 +499,8 @@ namespace Tensorflow.Operations | |||
| "Relu", name, new IntPtr[] | |||
| { | |||
| features as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -492,7 +519,8 @@ namespace Tensorflow.Operations | |||
| "Tanh", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -349,7 +349,7 @@ namespace Tensorflow | |||
| return fill(shape_tensor, ones, name: name); | |||
| }); | |||
| public static Tensor one_hot(Tensor indices, int depth, | |||
| public static Tensor one_hot(Tensor indices, Tensor depth, | |||
| Tensor on_value = null, | |||
| Tensor off_value = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| @@ -25,7 +25,7 @@ namespace Tensorflow | |||
| { | |||
| public class clip_ops | |||
| { | |||
| public static Tensor clip_by_value(Tensor t, Tensor clip_value_min, Tensor 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 | |||
| { | |||
| @@ -21,6 +21,7 @@ using static Tensorflow.Binding; | |||
| using Tensorflow.Eager; | |||
| using System.Linq; | |||
| using static Tensorflow.Binding; | |||
| using System.Security.Cryptography.X509Certificates; | |||
| namespace Tensorflow | |||
| { | |||
| @@ -60,7 +61,8 @@ namespace Tensorflow | |||
| { | |||
| values as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -165,7 +167,8 @@ namespace Tensorflow | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Pack", name, | |||
| values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, | |||
| values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, | |||
| wrap_tfe_src.SetOpAttrs2("axis", axis), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "axis", axis), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| @@ -235,7 +238,8 @@ namespace Tensorflow | |||
| "Identity", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -278,15 +282,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(dims, value); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Fill", name, new IntPtr[] | |||
| { | |||
| dims as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| "Fill", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -311,7 +316,8 @@ namespace Tensorflow | |||
| { | |||
| s0 as EagerTensor, | |||
| s1 as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return (results[0].Resolve(), results[1].Resolve()); | |||
| @@ -338,7 +344,8 @@ namespace Tensorflow | |||
| { | |||
| tensor as EagerTensor, | |||
| shape as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -381,13 +388,30 @@ namespace Tensorflow | |||
| return _op.output; | |||
| } | |||
| public static Tensor one_hot(Tensor indices, int depth, | |||
| public static Tensor one_hot(Tensor indices, Tensor depth, | |||
| Tensor on_value = null, | |||
| Tensor off_value = null, | |||
| TF_DataType dtype = TF_DataType.DtInvalid, | |||
| int axis = -1, | |||
| string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(indices, depth, on_value, off_value); | |||
| var attrs = new object[] { "axis", axis }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "OneHot", name, | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("OneHot", name, new { indices, depth, on_value, off_value, axis }); | |||
| return _op.outputs[0]; | |||
| } | |||
| @@ -407,6 +431,21 @@ namespace Tensorflow | |||
| public static Tensor select<Tx, Ty>(Tensor condition, Tx t, Ty e, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(condition, t, e); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "SelectV2", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Select", name, new { condition, t, e }); | |||
| return _op.outputs[0]; | |||
| } | |||
| @@ -427,6 +466,7 @@ namespace Tensorflow | |||
| { | |||
| input as EagerTensor, | |||
| }, 1, | |||
| wrap_tfe_src.SetOpAttrs2("out_type", out_type), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "out_type", out_type), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| @@ -486,7 +526,8 @@ namespace Tensorflow | |||
| { | |||
| input as EagerTensor, | |||
| multiples as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -526,6 +567,14 @@ namespace Tensorflow | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var attrs = new object[] | |||
| { | |||
| "begin_mask", begin_mask, | |||
| "end_mask", end_mask, | |||
| "ellipsis_mask", ellipsis_mask, | |||
| "new_axis_mask", new_axis_mask, | |||
| "shrink_axis_mask", shrink_axis_mask | |||
| }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "StridedSlice", name, new IntPtr[] | |||
| { | |||
| @@ -534,12 +583,8 @@ namespace Tensorflow | |||
| end as EagerTensor, | |||
| strides as EagerTensor, | |||
| }, 4, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "begin_mask", begin_mask, | |||
| "end_mask", end_mask, | |||
| "ellipsis_mask", ellipsis_mask, | |||
| "new_axis_mask", new_axis_mask, | |||
| "shrink_axis_mask", shrink_axis_mask), | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -653,8 +698,8 @@ namespace Tensorflow | |||
| { | |||
| input as EagerTensor | |||
| }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "squeeze_dims", axis), | |||
| wrap_tfe_src.SetOpAttrs2("squeeze_dims", axis), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "squeeze_dims", axis), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -689,8 +734,22 @@ namespace Tensorflow | |||
| /// <param name="shape"></param> | |||
| /// <param name="name"></param> | |||
| /// <returns></returns> | |||
| public static Tensor broadcast_to(Tensor input, int[] shape, string name = null) | |||
| public static Tensor broadcast_to<T>(Tensor input, T shape, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(input, shape); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "BroadcastTo", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("BroadcastTo", name, args: new { input, shape, name }); | |||
| return _op.outputs[0]; | |||
| @@ -48,7 +48,7 @@ namespace Tensorflow | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AddN", name, | |||
| inputs.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), inputs.Length, | |||
| null, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -65,7 +65,7 @@ namespace Tensorflow | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AddN", name, | |||
| inputs, inputs.Length, | |||
| null, | |||
| null, null, | |||
| results, results.Length); | |||
| status.Check(true); | |||
| return results[0]; | |||
| @@ -80,7 +80,23 @@ namespace Tensorflow | |||
| /// <param name="name"></param> | |||
| /// <returns></returns> | |||
| public static Tensor arg_max(Tensor input, int dimension, TF_DataType output_type = TF_DataType.TF_INT64, string name = null) | |||
| => _op_def_lib._apply_op_helper("ArgMax", name, args: new { input, dimension, output_type }).outputs[0]; | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(input, dimension); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ArgMax", name, | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2("output_type", output_type), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "output_type", output_type), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| return _op_def_lib._apply_op_helper("ArgMax", name, args: new { input, dimension, output_type }).output; | |||
| } | |||
| /// <summary> | |||
| /// Returns the index with the smallest value across dimensions of a tensor. | |||
| @@ -152,6 +168,7 @@ namespace Tensorflow | |||
| input as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, | |||
| wrap_tfe_src.SetOpAttrs2("keep_dims", keep_dims), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| @@ -198,6 +215,7 @@ namespace Tensorflow | |||
| input as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, | |||
| wrap_tfe_src.SetOpAttrs2("keep_dims", keep_dims), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| @@ -247,7 +265,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -268,7 +287,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -290,7 +310,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -324,7 +345,8 @@ namespace Tensorflow | |||
| "Sin", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -358,7 +380,8 @@ namespace Tensorflow | |||
| "Sigmoid", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -451,7 +474,8 @@ namespace Tensorflow | |||
| "Tan", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -471,7 +495,8 @@ namespace Tensorflow | |||
| "Tanh", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -499,7 +524,8 @@ namespace Tensorflow | |||
| { | |||
| y as EagerTensor, | |||
| dy as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -550,6 +576,21 @@ namespace Tensorflow | |||
| public static Tensor greater_equal<Tx, Ty>(Tx x, Ty y, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x, y); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "GreaterEqual", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("GreaterEqual", name: name, args: new { x, y }); | |||
| return _op.outputs[0]; | |||
| @@ -559,14 +600,13 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x, y); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Less", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| "Less", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -578,6 +618,19 @@ namespace Tensorflow | |||
| public static Tensor less_equal<Tx, Ty>(Tx x, Ty y, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x, y); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "LessEqual", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("LessEqual", name: name, args: new { x, y }); | |||
| return _op.outputs[0]; | |||
| @@ -641,7 +694,8 @@ namespace Tensorflow | |||
| "Square", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -693,6 +747,21 @@ namespace Tensorflow | |||
| /// <returns> A `Tensor`. Has the same type as `x`.</returns> | |||
| public static Tensor log(Tensor x, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Log", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Log", name, args: new { x }); | |||
| return _op.outputs[0]; | |||
| @@ -703,12 +772,20 @@ namespace Tensorflow | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var attrs = new object[] | |||
| { | |||
| "DstT", DstT, | |||
| "Truncate", Truncate | |||
| }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Cast", name, | |||
| new IntPtr[] { x as EagerTensor }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "DstT", DstT, "Truncate", Truncate), | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -721,14 +798,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Neg", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| "Neg", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -746,7 +825,8 @@ namespace Tensorflow | |||
| "Sqrt", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, | |||
| }, 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -767,7 +847,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -788,7 +869,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -816,7 +898,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -845,7 +928,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -866,7 +950,8 @@ namespace Tensorflow | |||
| { | |||
| y as EagerTensor, | |||
| x as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -886,7 +971,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -907,7 +993,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor, | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -935,7 +1022,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -948,6 +1036,21 @@ namespace Tensorflow | |||
| public static Tensor reciprocal(Tensor x, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Reciprocal", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Reciprocal", name, args: new { x }); | |||
| return _op.outputs[0]; | |||
| @@ -963,7 +1066,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -984,7 +1088,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -1008,18 +1113,19 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(a, b); | |||
| var attrs = new object[] | |||
| { | |||
| "transpose_a", transpose_a, | |||
| "transpose_b", transpose_b | |||
| }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "MatMul", name, | |||
| new IntPtr[] | |||
| { | |||
| a as EagerTensor, | |||
| b as EagerTensor | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "transpose_a", transpose_a, | |||
| "transpose_b", transpose_b), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -1073,6 +1179,21 @@ namespace Tensorflow | |||
| /// <returns></returns> | |||
| public static Tensor maximum<T1, T2>(T1 x, T2 y, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x, y); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Maximum", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Maximum", name, args: new { x, y }); | |||
| return _op.outputs[0]; | |||
| @@ -1080,6 +1201,21 @@ namespace Tensorflow | |||
| public static Tensor minimum<T1, T2>(T1 x, T2 y, string name = null) | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(x, y); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Minimum", name, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Minimum", name, args: new { x, y }); | |||
| return _op.outputs[0]; | |||
| @@ -1123,7 +1259,8 @@ namespace Tensorflow | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, | |||
| }, 2, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -1138,17 +1275,18 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(input, axis); | |||
| var attrs = new object[] { "keep_dims", keep_dims }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sum", name, | |||
| new IntPtr[] | |||
| { | |||
| input as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -1199,7 +1337,8 @@ namespace Tensorflow | |||
| start as EagerTensor, | |||
| limit as EagerTensor, | |||
| delta as EagerTensor | |||
| }, 3, null, | |||
| }, 3, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -11,14 +11,15 @@ namespace Tensorflow | |||
| { | |||
| public static EagerTensor mul(IntPtr x, IntPtr y, string name = null) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Mul", name, new IntPtr[] | |||
| { | |||
| x, | |||
| y, | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| }, 2, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -42,17 +42,20 @@ namespace Tensorflow | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var attrs = new object[] | |||
| { | |||
| "seed", seed, | |||
| "seed2", seed2, | |||
| "dtype", dtype | |||
| }; | |||
| var inputs = EagerTensorPass.From(shape); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "RandomStandardNormal", name, new IntPtr[] | |||
| { | |||
| shape as EagerTensor, | |||
| }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "seed", seed, | |||
| "seed2", seed2, | |||
| "dtype", dtype), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| "RandomStandardNormal", name, | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -148,17 +151,20 @@ namespace Tensorflow | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(shape); | |||
| var attrs = new object[] | |||
| { | |||
| "seed", seed, | |||
| "seed2", seed2, | |||
| "dtype", dtype | |||
| }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "TruncatedNormal", name, new IntPtr[] | |||
| { | |||
| shape as EagerTensor, | |||
| }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "seed", seed, | |||
| "seed2", seed2, | |||
| "dtype", dtype), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| "TruncatedNormal", name, | |||
| inputs.Points, inputs.Length, | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -29,15 +29,13 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var inputs = EagerTensorPass.From(resource, value); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignSubVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -56,13 +54,11 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var inputs = EagerTensorPass.From(resource, value); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignAddVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| null, 0); | |||
| status.Check(true); | |||
| return null; | |||
| @@ -75,13 +71,11 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| var inputs = EagerTensorPass.From(resource, value); | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, | |||
| inputs.Points, inputs.Length, | |||
| null, null, | |||
| null, 0); | |||
| status.Check(true); | |||
| return null; | |||
| @@ -100,7 +94,8 @@ namespace Tensorflow | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "VarIsInitializedOp", name, | |||
| new IntPtr[] { resource as EagerTensor }, | |||
| 1, null, | |||
| 1, | |||
| null, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| @@ -125,15 +120,19 @@ namespace Tensorflow | |||
| { | |||
| if(tf.context.executing_eagerly()) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| var results = EagerTensorPass.Create(); | |||
| var attrs = new object[] | |||
| { | |||
| "container", container, | |||
| "shared_name", shared_name, | |||
| "dtype", dtype, | |||
| "shape", shape.dims | |||
| }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "VarHandleOp", name, null, 0, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "container", container, | |||
| "shared_name", shared_name, | |||
| "dtype", dtype, | |||
| "shape", shape.dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| wrap_tfe_src.SetOpAttrs2(attrs), | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| results.Points, results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| @@ -163,6 +162,7 @@ namespace Tensorflow | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ReadVariableOp", name, | |||
| new IntPtr[] { resource as EagerTensor }, 1, | |||
| wrap_tfe_src.SetOpAttrs2("dtype", dtype), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "dtype", dtype), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| @@ -348,6 +348,14 @@ namespace Tensorflow | |||
| /// <returns>A 1-D Tensor, the output shape as if keepdims were set to True.</returns> | |||
| public static Tensor reduced_shape(Tensor input_shape, Tensor axes) | |||
| { | |||
| if(tf.context.executing_eagerly()) | |||
| { | |||
| var input_shape_val = input_shape.numpy(); | |||
| var axes_val = (int)axes.numpy(); | |||
| input_shape_val[axes_val] = 1; | |||
| return tf.constant(input_shape_val); | |||
| } | |||
| input_shape = to_int32(input_shape); | |||
| axes = to_int32(axes); | |||
| @@ -522,7 +530,8 @@ namespace Tensorflow | |||
| public static Tensor reduce_sum(Tensor input_tensor, int axis, bool keepdims = false, string name = null) | |||
| { | |||
| var m = gen_math_ops._sum(input_tensor, axis, keep_dims: keepdims, name: name); | |||
| var dims = _ReductionDims(input_tensor, axis); | |||
| var m = gen_math_ops._sum(input_tensor, dims, keep_dims: keepdims, name: name); | |||
| return _may_reduce_to_scalar(keepdims, axis, m); | |||
| } | |||
| @@ -54,8 +54,11 @@ namespace Tensorflow | |||
| public static void Decrease(IntPtr handle) | |||
| { | |||
| if (handle != IntPtr.Zero && container.ContainsKey(handle)) | |||
| container[handle].RefCounter--; | |||
| lock (locker) | |||
| { | |||
| if (handle != IntPtr.Zero && container.ContainsKey(handle)) | |||
| container[handle].RefCounter--; | |||
| } | |||
| } | |||
| private static void Recycle() | |||
| @@ -64,7 +67,7 @@ namespace Tensorflow | |||
| lock (locker) | |||
| { | |||
| var items = container.Values | |||
| .Where(x => x.RefCounter <= 0 && (DateTime.Now - x.LastUpdateTime).TotalMilliseconds > 100) | |||
| .Where(x => x.RefCounter <= 0 && (DateTime.Now - x.LastUpdateTime).TotalMilliseconds > 300) | |||
| .ToArray(); | |||
| foreach (var item in items) | |||
| @@ -74,15 +77,15 @@ namespace Tensorflow | |||
| switch (item.ItemType) | |||
| { | |||
| case GCItemType.TensorHandle: | |||
| // print($"c_api.TF_DeleteTensor({item.Handle.ToString("x16")})"); | |||
| //print($"c_api.TF_DeleteTensor({item.Handle.ToString("x16")})"); | |||
| c_api.TF_DeleteTensor(item.Handle); | |||
| break; | |||
| case GCItemType.LocalTensorHandle: | |||
| // print($"c_api.TFE_DeleteTensorHandle({item.Handle.ToString("x16")})"); | |||
| //print($"c_api.TFE_DeleteTensorHandle({item.Handle.ToString("x16")})"); | |||
| c_api.TFE_DeleteTensorHandle(item.Handle); | |||
| break; | |||
| case GCItemType.EagerTensorHandle: | |||
| // print($"c_api.TFE_DeleteEagerTensor({item.Handle.ToString("x16")})"); | |||
| //print($"c_api.TFE_DeleteEagerTensor({item.Handle.ToString("x16")})"); | |||
| c_api.TFE_DeleteEagerTensor(item.Handle); | |||
| break; | |||
| default: | |||
| @@ -38,7 +38,8 @@ namespace Tensorflow | |||
| _TensorLike, | |||
| ITensorOrTensorArray, | |||
| IPackable<Tensor>, | |||
| ICanBeFlattened | |||
| ICanBeFlattened, | |||
| IPointerInputs | |||
| { | |||
| protected int _id; | |||
| private readonly Operation _op; | |||
| @@ -280,6 +281,10 @@ namespace Tensorflow | |||
| } else | |||
| throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); | |||
| } | |||
| public virtual IntPtr ToPointer() | |||
| => _handle; | |||
| public bool IsDisposed => _disposed; | |||
| // public int tensor_int_val { get; set; } | |||
| @@ -199,6 +199,7 @@ namespace Tensorflow | |||
| => type switch | |||
| { | |||
| TF_DataType.TF_STRING => "string", | |||
| TF_DataType.TF_UINT8 => "uint8", | |||
| TF_DataType.TF_INT32 => "int32", | |||
| TF_DataType.TF_FLOAT => "float32", | |||
| TF_DataType.TF_BOOL => "bool", | |||
| @@ -72,6 +72,7 @@ namespace Tensorflow | |||
| alpha, | |||
| delta | |||
| }, 3, | |||
| wrap_tfe_src.SetOpAttrs2("use_locking", use_locking), | |||
| op => wrap_tfe_src.SetOpAttrs(op, "use_locking", use_locking), | |||
| null, 0); | |||
| status.Check(true); | |||
| @@ -0,0 +1,22 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using Tensorflow.Eager; | |||
| namespace Tensorflow | |||
| { | |||
| public class EagerTensorPass : PointerInputs<EagerTensor> | |||
| { | |||
| public EagerTensorPass(params EagerTensor[] tensors) | |||
| { | |||
| data = tensors; | |||
| } | |||
| public static EagerTensorPass Create(int count = 1) | |||
| => new EagerTensorPass(Enumerable.Range(0, count).Select(x => new EagerTensor()).ToArray()); | |||
| public static EagerTensorPass From(params object[] objects) | |||
| => new EagerTensorPass(objects.Select(x => ops.convert_to_tensor(x) as EagerTensor).ToArray()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public interface IPointerInputs | |||
| { | |||
| public IntPtr ToPointer(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.Linq; | |||
| namespace Tensorflow | |||
| { | |||
| public abstract class PointerInputs<T> | |||
| where T : IPointerInputs, new() | |||
| { | |||
| protected T[] data; | |||
| public int Length | |||
| => data.Length; | |||
| public IntPtr[] Points | |||
| => data.Select(x => x.ToPointer()).ToArray(); | |||
| public PointerInputs(params T[] data) | |||
| => this.data = data; | |||
| public T this[int idx] | |||
| => data[idx]; | |||
| public T[] Items | |||
| => data; | |||
| public static implicit operator IntPtr[](PointerInputs<T> inputs) | |||
| => inputs.data.Select(x => x.ToPointer()).ToArray(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using Tensorflow.Eager; | |||
| namespace Tensorflow | |||
| { | |||
| public class TensorManager | |||
| { | |||
| Dictionary<IntPtr, EagerTensor> tensors; | |||
| public TensorManager() | |||
| { | |||
| tensors = new Dictionary<IntPtr, EagerTensor>(); | |||
| } | |||
| public EagerTensor GetTensor(IntPtr handle) | |||
| { | |||
| if (tensors.ContainsKey(handle)) | |||
| return tensors[handle]; | |||
| //return new EagerTensor(handle); | |||
| tensors[handle] = new EagerTensor(handle); | |||
| return tensors[handle]; | |||
| } | |||
| public void Reset() | |||
| { | |||
| tensors.Clear(); | |||
| } | |||
| } | |||
| } | |||
| @@ -54,7 +54,7 @@ namespace Tensorflow | |||
| public BaseResourceVariable(IntPtr handle, IntPtr tensor) | |||
| { | |||
| _handle = handle; | |||
| this.handle = new EagerTensor(tensor); | |||
| this.handle = tf.tensorMgr.GetTensor(tensor); | |||
| } | |||
| public void __init__(bool trainable = true, | |||
| @@ -15,6 +15,7 @@ | |||
| ******************************************************************************/ | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| @@ -96,15 +97,18 @@ namespace Tensorflow | |||
| get_default_graph()._name_stack = old_scope_name; | |||
| } | |||
| [DebuggerNonUserCode] | |||
| public void __exit__() | |||
| { | |||
| } | |||
| [DebuggerNonUserCode] | |||
| public void __init__() | |||
| { | |||
| } | |||
| [DebuggerNonUserCode] | |||
| public void __del__() | |||
| { | |||
| @@ -40,11 +40,12 @@ namespace Tensorflow | |||
| public TF_DataType @string = TF_DataType.TF_STRING; | |||
| public Context context = new Context(new ContextOptions(), new Status()); | |||
| public TensorManager tensorMgr; | |||
| public tensorflow() | |||
| { | |||
| _constructThreadingObjects(); | |||
| InitGradientEnvironment(); | |||
| tensorMgr = new TensorManager(); | |||
| } | |||
| private void InitGradientEnvironment() | |||
| @@ -64,16 +65,18 @@ namespace Tensorflow | |||
| ops.RegisterFromAssembly(); | |||
| // ops.RegisterFromAssemblyEager(); | |||
| c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, attrs_handle, output_grads, skip_input_indices) => | |||
| c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, attrs_string, output_grads, skip_input_indices) => | |||
| { | |||
| /*var input_tensors = new BindingArray(op_inputs); | |||
| var output_tensors = new BindingArray(op_outputs); | |||
| var output_grad_tensors = new BindingArray(output_grads);*/ | |||
| var input_tensors = new BindingTensorArray(op_inputs).Data.Select(x => new EagerTensor(x)).ToArray(); | |||
| var output_tensors = new BindingTensorArray(op_outputs).Data.Select(x => new EagerTensor(x)).ToArray(); | |||
| var output_grad_tensors = new BindingTensorArray(output_grads).Data.Select(x => new EagerTensor(x)).ToArray(); | |||
| var input_tensors = new BindingTensorArray(op_inputs) | |||
| .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); | |||
| var output_tensors = new BindingTensorArray(op_outputs) | |||
| .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); | |||
| var output_grad_tensors = new BindingTensorArray(output_grads) | |||
| .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); | |||
| var skip_input_indices_param = new BindingArray(skip_input_indices); | |||
| var attrs = new BindingArray(attrs_handle);//.Data.Select(x => *(int*)x).ToArray(); | |||
| var gradients = ops.gradientFunctions[op_name](new EagerOperation | |||
| { | |||
| @@ -85,7 +88,7 @@ namespace Tensorflow | |||
| Outputs = output_tensors, | |||
| // OutputHandles = output_tensors.Data, | |||
| SkipInputIndicesArray = skip_input_indices_param, | |||
| AttrsArray = attrs | |||
| AttrsArray = attrs_string.Split(',') | |||
| }, output_grad_tensors); | |||
| var gradients_handles = gradients.Select(x => x == null ? IntPtr.Zero : (x as EagerTensor).EagerTensorHandle).ToArray(); | |||