implement: (1)tf.nn.moments (2)math_ops.reduce_mean (3)math_ops.squar…tags/v0.8.0
| @@ -1,208 +1,243 @@ | |||||
| using NumSharp.Core; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class array_ops | |||||
| { | |||||
| public static Tensor placeholder_with_default<T>(T input, int[] shape, string name = null) => gen_array_ops.placeholder_with_default(input, shape, name); | |||||
| public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null) | |||||
| { | |||||
| dtype = dtype.as_base_dtype(); | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "zeros", shape), scope => | |||||
| { | |||||
| name = scope; | |||||
| switch (dtype) | |||||
| { | |||||
| case TF_DataType.TF_BOOL: | |||||
| return _constant_if_small(false, shape, dtype, name); | |||||
| case TF_DataType.TF_DOUBLE: | |||||
| return _constant_if_small(0.0D, shape, dtype, name); | |||||
| case TF_DataType.TF_FLOAT: | |||||
| return _constant_if_small(0.0F, shape, dtype, name); | |||||
| case TF_DataType.TF_INT32: | |||||
| return _constant_if_small(0, shape, dtype, name); | |||||
| default: | |||||
| throw new TypeError("can't find type for zeros"); | |||||
| } | |||||
| }); | |||||
| } | |||||
| private static Tensor _constant_if_small<T>(T value, Shape shape, TF_DataType dtype, string name) | |||||
| { | |||||
| Tensor tShape = null; | |||||
| if (shape.Size < 1000) | |||||
| { | |||||
| return constant_op.constant(value, shape: shape, dtype: dtype, name: name); | |||||
| } | |||||
| else | |||||
| { | |||||
| tShape = constant_op._tensor_shape_tensor_conversion_function(shape.as_shape()); | |||||
| var c = constant_op.constant(0); | |||||
| return gen_array_ops.fill(tShape, c, name: name); | |||||
| } | |||||
| } | |||||
| public static Tensor expand_dims(Tensor input, int axis = -1, string name = null, int dim = -1) => expand_dims_v2(input, axis, name); | |||||
| private static Tensor expand_dims_v2(Tensor input, int axis, string name = null) => gen_array_ops.expand_dims(input, axis, name); | |||||
| public static Tensor rank(Tensor input, string name = null) | |||||
| { | |||||
| return math_ops.rank_internal(input, name, optimize: true); | |||||
| } | |||||
| /// <summary> | |||||
| /// Creates a tensor with all elements set to 1. | |||||
| /// </summary> | |||||
| /// <param name="tensor"></param> | |||||
| /// <param name="dtype"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="optimize"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor ones_like<T>(T tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool optimize = true) | |||||
| => ones_like_impl(tensor, dtype, name, optimize); | |||||
| private static Tensor ones_like_impl<T>(T tensor, TF_DataType dtype, string name, bool optimize = true) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "ones_like", new { tensor }), scope => | |||||
| { | |||||
| name = scope; | |||||
| var tensor1 = ops.convert_to_tensor(tensor, name: "tensor"); | |||||
| var ones_shape = shape_internal(tensor1, optimize: optimize); | |||||
| if (dtype == TF_DataType.DtInvalid) | |||||
| dtype = tensor1.dtype; | |||||
| var ret = ones(ones_shape, dtype: dtype, name: name); | |||||
| ret.shape = tensor1.shape; | |||||
| return ret; | |||||
| }); | |||||
| } | |||||
| public static Tensor ones(Tensor shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null) | |||||
| { | |||||
| dtype = dtype.as_base_dtype(); | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "ones", new { shape }), scope => | |||||
| { | |||||
| name = scope; | |||||
| var output = gen_array_ops.fill(shape, constant_op.constant(1.0f, dtype: dtype), name: name); | |||||
| return output; | |||||
| }); | |||||
| } | |||||
| public static Tensor where(Tensor condition, Tensor x = null, Tensor y = null, string name = null) | |||||
| { | |||||
| if( x == null && y == null) | |||||
| { | |||||
| throw new NotImplementedException("where"); | |||||
| } | |||||
| else if(x != null && y != null) | |||||
| { | |||||
| return gen_array_ops.select(condition, x, y, name); | |||||
| } | |||||
| else | |||||
| { | |||||
| throw new ValueError("x and y must both be non-None or both be None."); | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// Returns the shape of a tensor. | |||||
| /// </summary> | |||||
| /// <param name="input">A `Tensor` or `SparseTensor`.</param> | |||||
| /// <param name="name">A name for the operation (optional).</param> | |||||
| /// <param name="out_type"> | |||||
| /// (Optional) The specified output type of the operation | |||||
| /// (`int32` or `int64`). Defaults to `tf.int32`. | |||||
| /// </param> | |||||
| /// <returns>A `Tensor` of type `out_type`.</returns> | |||||
| public static Tensor shape(Tensor input, string name = null, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return shape_internal(input, name, optimize: true, out_type: out_type); | |||||
| } | |||||
| public static Tensor size(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return size_internal(input, name, optimize: optimize, out_type: out_type); | |||||
| } | |||||
| private static Tensor shape_internal(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "Shape", new { input }), scope => | |||||
| { | |||||
| name = scope; | |||||
| if (!tf.context.executing_eagerly()) | |||||
| { | |||||
| var input_tensor = ops.convert_to_tensor(input); | |||||
| var input_shape = tensor_util.to_shape(input_tensor.shape); | |||||
| if (optimize && input_tensor.NDims > -1 && input_shape.is_fully_defined()) | |||||
| { | |||||
| var nd = np.array(input_tensor.shape, out_type.as_numpy_datatype()); | |||||
| return constant_op.constant(nd, name: name); | |||||
| } | |||||
| } | |||||
| return gen_array_ops.shape(input, name: name, out_type: out_type); | |||||
| }); | |||||
| } | |||||
| private static Tensor size_internal(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "Size", new Tensor[] { input }), scope => | |||||
| { | |||||
| name = scope; | |||||
| if (!tf.context.executing_eagerly()) | |||||
| { | |||||
| var input_tensor = ops.convert_to_tensor(input); | |||||
| var input_shape = tensor_util.to_shape(input_tensor.shape); | |||||
| if (optimize) | |||||
| { | |||||
| if (input_shape.is_fully_defined()) | |||||
| { | |||||
| var nd = np.array(input_tensor.shape, out_type.as_numpy_datatype()); | |||||
| return constant_op.constant(nd, name: name); | |||||
| } | |||||
| } | |||||
| return gen_array_ops.size(input, name: name, out_type: out_type); | |||||
| } | |||||
| else | |||||
| { | |||||
| // result = gen_array_ops.shape(); | |||||
| throw new NotImplementedException("array_ops.size_internal"); | |||||
| } | |||||
| return null; | |||||
| }); | |||||
| } | |||||
| public static Tensor zeros_like(Tensor tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool optimize = true) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "zeros_like", new Tensor[] { tensor }), scope => | |||||
| { | |||||
| name = scope; | |||||
| tensor = ops.convert_to_tensor(tensor, name: "tensor"); | |||||
| // is_fully_defined return unexpected value. | |||||
| if (optimize && tensor_util.to_shape(tensor.shape).is_fully_defined() && dtype != TF_DataType.TF_VARIANT) | |||||
| { | |||||
| } | |||||
| if(dtype != TF_DataType.DtInvalid && dtype != tensor.dtype && dtype != TF_DataType.TF_VARIANT) | |||||
| { | |||||
| throw new NotImplementedException("zeros_like"); | |||||
| // return zeros(shape_internal(tensor, optimize: optimize), dtype: dtype, name: name); | |||||
| } | |||||
| else | |||||
| { | |||||
| return gen_array_ops.zeros_like(tensor, name: name); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| using NumSharp.Core; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class array_ops | |||||
| { | |||||
| public static Tensor placeholder_with_default<T>(T input, int[] shape, string name = null) => gen_array_ops.placeholder_with_default(input, shape, name); | |||||
| public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null) | |||||
| { | |||||
| dtype = dtype.as_base_dtype(); | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "zeros", shape), scope => | |||||
| { | |||||
| name = scope; | |||||
| switch (dtype) | |||||
| { | |||||
| case TF_DataType.TF_BOOL: | |||||
| return _constant_if_small(false, shape, dtype, name); | |||||
| case TF_DataType.TF_DOUBLE: | |||||
| return _constant_if_small(0.0D, shape, dtype, name); | |||||
| case TF_DataType.TF_FLOAT: | |||||
| return _constant_if_small(0.0F, shape, dtype, name); | |||||
| case TF_DataType.TF_INT32: | |||||
| return _constant_if_small(0, shape, dtype, name); | |||||
| default: | |||||
| throw new TypeError("can't find type for zeros"); | |||||
| } | |||||
| }); | |||||
| } | |||||
| private static Tensor _constant_if_small<T>(T value, Shape shape, TF_DataType dtype, string name) | |||||
| { | |||||
| Tensor tShape = null; | |||||
| if (shape.Size < 1000) | |||||
| { | |||||
| return constant_op.constant(value, shape: shape, dtype: dtype, name: name); | |||||
| } | |||||
| else | |||||
| { | |||||
| tShape = constant_op._tensor_shape_tensor_conversion_function(shape.as_shape()); | |||||
| var c = constant_op.constant(0); | |||||
| return gen_array_ops.fill(tShape, c, name: name); | |||||
| } | |||||
| } | |||||
| public static Tensor expand_dims(Tensor input, int axis = -1, string name = null, int dim = -1) => expand_dims_v2(input, axis, name); | |||||
| private static Tensor expand_dims_v2(Tensor input, int axis, string name = null) => gen_array_ops.expand_dims(input, axis, name); | |||||
| public static Tensor rank(Tensor input, string name = null) | |||||
| { | |||||
| return math_ops.rank_internal(input, name, optimize: true); | |||||
| } | |||||
| /// <summary> | |||||
| /// Creates a tensor with all elements set to 1. | |||||
| /// </summary> | |||||
| /// <param name="tensor"></param> | |||||
| /// <param name="dtype"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="optimize"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor ones_like<T>(T tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool optimize = true) | |||||
| => ones_like_impl(tensor, dtype, name, optimize); | |||||
| private static Tensor ones_like_impl<T>(T tensor, TF_DataType dtype, string name, bool optimize = true) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "ones_like", new { tensor }), scope => | |||||
| { | |||||
| name = scope; | |||||
| var tensor1 = ops.convert_to_tensor(tensor, name: "tensor"); | |||||
| var ones_shape = shape_internal(tensor1, optimize: optimize); | |||||
| if (dtype == TF_DataType.DtInvalid) | |||||
| dtype = tensor1.dtype; | |||||
| var ret = ones(ones_shape, dtype: dtype, name: name); | |||||
| ret.shape = tensor1.shape; | |||||
| return ret; | |||||
| }); | |||||
| } | |||||
| public static Tensor ones(Tensor shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null) | |||||
| { | |||||
| dtype = dtype.as_base_dtype(); | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "ones", new { shape }), scope => | |||||
| { | |||||
| name = scope; | |||||
| var output = gen_array_ops.fill(shape, constant_op.constant(1.0f, dtype: dtype), name: name); | |||||
| return output; | |||||
| }); | |||||
| } | |||||
| public static Tensor where(Tensor condition, Tensor x = null, Tensor y = null, string name = null) | |||||
| { | |||||
| if( x == null && y == null) | |||||
| { | |||||
| throw new NotImplementedException("where"); | |||||
| } | |||||
| else if(x != null && y != null) | |||||
| { | |||||
| return gen_array_ops.select(condition, x, y, name); | |||||
| } | |||||
| else | |||||
| { | |||||
| throw new ValueError("x and y must both be non-None or both be None."); | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// Returns the shape of a tensor. | |||||
| /// </summary> | |||||
| /// <param name="input">A `Tensor` or `SparseTensor`.</param> | |||||
| /// <param name="name">A name for the operation (optional).</param> | |||||
| /// <param name="out_type"> | |||||
| /// (Optional) The specified output type of the operation | |||||
| /// (`int32` or `int64`). Defaults to `tf.int32`. | |||||
| /// </param> | |||||
| /// <returns>A `Tensor` of type `out_type`.</returns> | |||||
| public static Tensor shape(Tensor input, string name = null, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return shape_internal(input, name, optimize: true, out_type: out_type); | |||||
| } | |||||
| public static Tensor size(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return size_internal(input, name, optimize: optimize, out_type: out_type); | |||||
| } | |||||
| private static Tensor shape_internal(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "Shape", new { input }), scope => | |||||
| { | |||||
| name = scope; | |||||
| if (!tf.context.executing_eagerly()) | |||||
| { | |||||
| var input_tensor = ops.convert_to_tensor(input); | |||||
| var input_shape = tensor_util.to_shape(input_tensor.shape); | |||||
| if (optimize && input_tensor.NDims > -1 && input_shape.is_fully_defined()) | |||||
| { | |||||
| var nd = np.array(input_tensor.shape, out_type.as_numpy_datatype()); | |||||
| return constant_op.constant(nd, name: name); | |||||
| } | |||||
| } | |||||
| return gen_array_ops.shape(input, name: name, out_type: out_type); | |||||
| }); | |||||
| } | |||||
| private static Tensor size_internal(Tensor input, string name = null, bool optimize = true, TF_DataType out_type = TF_DataType.TF_INT32) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "Size", new Tensor[] { input }), scope => | |||||
| { | |||||
| name = scope; | |||||
| if (!tf.context.executing_eagerly()) | |||||
| { | |||||
| var input_tensor = ops.convert_to_tensor(input); | |||||
| var input_shape = tensor_util.to_shape(input_tensor.shape); | |||||
| if (optimize) | |||||
| { | |||||
| if (input_shape.is_fully_defined()) | |||||
| { | |||||
| var nd = np.array(input_tensor.shape, out_type.as_numpy_datatype()); | |||||
| return constant_op.constant(nd, name: name); | |||||
| } | |||||
| } | |||||
| return gen_array_ops.size(input, name: name, out_type: out_type); | |||||
| } | |||||
| else | |||||
| { | |||||
| // result = gen_array_ops.shape(); | |||||
| throw new NotImplementedException("array_ops.size_internal"); | |||||
| } | |||||
| return null; | |||||
| }); | |||||
| } | |||||
| public static Tensor zeros_like(Tensor tensor, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool optimize = true) | |||||
| { | |||||
| return Python.with<ops.name_scope, Tensor>(new ops.name_scope(name, "zeros_like", new Tensor[] { tensor }), scope => | |||||
| { | |||||
| name = scope; | |||||
| tensor = ops.convert_to_tensor(tensor, name: "tensor"); | |||||
| // is_fully_defined return unexpected value. | |||||
| if (optimize && tensor_util.to_shape(tensor.shape).is_fully_defined() && dtype != TF_DataType.TF_VARIANT) | |||||
| { | |||||
| } | |||||
| if(dtype != TF_DataType.DtInvalid && dtype != tensor.dtype && dtype != TF_DataType.TF_VARIANT) | |||||
| { | |||||
| throw new NotImplementedException("zeros_like"); | |||||
| // return zeros(shape_internal(tensor, optimize: optimize), dtype: dtype, name: name); | |||||
| } | |||||
| else | |||||
| { | |||||
| return gen_array_ops.zeros_like(tensor, name: name); | |||||
| } | |||||
| }); | |||||
| } | |||||
| /// <summary> | |||||
| /// When building ops to compute gradients, this op prevents the contribution of | |||||
| /// its inputs to be taken into account.Normally, the gradient generator adds ops /// to a graph to compute the derivatives of a specified 'loss' by recursively /// finding out inputs that contributed to its computation.If you insert this op /// in the graph it inputs are masked from the gradient generator. They are not | |||||
| /// taken into account for computing gradients. | |||||
| /// </summary> | |||||
| /// <param name="input"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor stop_gradient(Tensor input, string name = null) | |||||
| { | |||||
| return gen_array_ops.stop_gradient(input, name); | |||||
| } | |||||
| /// <summary> | |||||
| /// Removes dimensions of size 1 from the shape of a tensor. | |||||
| /// Given a tensor `input`, this operation returns a tensor of the same type with | |||||
| /// all dimensions of size 1 removed.If you don't want to remove all size 1 | |||||
| /// dimensions, you can remove specific size 1 dimensions by specifying | |||||
| /// `axis`. | |||||
| /// </summary> | |||||
| /// <param name="input"> A `Tensor`. The `input` to squeeze.</param> | |||||
| /// <param name="axis"> An optional list of `ints`. Defaults to `[]`. | |||||
| /// If specified, only squeezes the dimensions listed.The dimension | |||||
| /// index starts at 0. It is an error to squeeze a dimension that is not 1. | |||||
| /// Must be in the range `[-rank(input), rank(input))`.</param> | |||||
| /// <param name="name"> A name for the operation (optional).</param> | |||||
| /// <param name="squeeze_dims" >Deprecated keyword argument that is now axis.</param> | |||||
| /// <returns>A `Tensor`. Has the same type as `input`. | |||||
| /// Contains the same data as `input`, but has one or more dimensions of | |||||
| /// size 1 removed.</returns> | |||||
| public static Tensor squeeze(Tensor input, int[] axis = null, string name = null, int[] squeeze_dims = null) | |||||
| { | |||||
| return gen_array_ops.squeeze(input, axis, name); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -155,5 +155,28 @@ namespace Tensorflow | |||||
| var _op = _op_def_lib._apply_op_helper("ZerosLike", name, new { x }); | var _op = _op_def_lib._apply_op_helper("ZerosLike", name, new { x }); | ||||
| return _op.outputs[0]; | return _op.outputs[0]; | ||||
| } | } | ||||
| public static Tensor stop_gradient(Tensor x, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("StopGradient", name, args: new { x }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Removes dimensions of size 1 from the shape of a tensor. | |||||
| /// Given a tensor `input`, this operation returns a tensor of the same type with | |||||
| /// all dimensions of size 1 removed.If you don't want to remove all size 1 | |||||
| /// dimensions, you can remove specific size 1 dimensions by specifying | |||||
| /// `axis`. | |||||
| /// </summary> | |||||
| /// <param name="input"> A `Tensor`. The `input` to squeeze.</param> | |||||
| /// <param name="axis"> An optional list of `ints`. Defaults to `[]`. If specified, only squeezes the dimensions listed.</param> | |||||
| /// <param name="name"> A name for the operation (optional).</param> | |||||
| /// <returns> A `Tensor`. Has the same type as `input`.</returns> | |||||
| public static Tensor squeeze(Tensor input, int[] axis = null, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Squeeze", name, args: new { input, axis, name }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,128 +1,152 @@ | |||||
| using NumSharp.Core; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public static class gen_math_ops | |||||
| { | |||||
| public static OpDefLibrary _op_def_lib = new OpDefLibrary(); | |||||
| public static Tensor add(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Add", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor cast(Tensor x, TF_DataType DstT, bool Truncate= false, string name= "") | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Cast", name, args: new { x, DstT, Truncate }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor neg(Tensor x, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Neg", name, args: new { x }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor sub<Tx, Ty>(Tx x, Ty y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor mul(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Mul", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor real_div(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("RealDiv", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor floor_mod(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("FloorMod", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor floor_div(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("FloorDiv", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Multiply the matrix "a" by the matrix "b". | |||||
| /// </summary> | |||||
| /// <param name="a"></param> | |||||
| /// <param name="b"></param> | |||||
| /// <param name="transpose_a"></param> | |||||
| /// <param name="transpose_b"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor mat_mul(Tensor a, Tensor b, bool transpose_a = false, bool transpose_b = false, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("MatMul", name, args: new { a, b, transpose_a, transpose_b }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Returns the max of x and y (i.e. x > y ? x : y) element-wise. | |||||
| /// </summary> | |||||
| /// <param name="x"></param> | |||||
| /// <param name="y"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor maximum<T1, T2>(T1 x, T2 y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Maximum", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor pow<Tx, Ty>(Tx x, Ty y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Pow", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor sum(Tensor input, Tensor axis = null, bool keep_dims = false, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { input, reduction_indices = axis, keep_dims }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Creates a sequence of numbers. | |||||
| /// </summary> | |||||
| /// <param name="start"></param> | |||||
| /// <param name="limit"></param> | |||||
| /// <param name="delta"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor range(Tensor start, Tensor limit, Tensor delta, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Range", name, new { start, limit, delta }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| } | |||||
| } | |||||
| using NumSharp.Core; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public static class gen_math_ops | |||||
| { | |||||
| public static OpDefLibrary _op_def_lib = new OpDefLibrary(); | |||||
| /// <summary> | |||||
| /// Computes the mean of elements across dimensions of a tensor. | |||||
| /// Reduces `input` along the dimensions given in `axis`. Unless /// `keep_dims` is true, the rank of the tensor is reduced by 1 for each entry in /// `axis`. If `keep_dims` is true, the reduced dimensions are retained with length 1. | |||||
| /// </summary> | |||||
| /// <param name="input">A `Tensor`. Must be one of the following types: | |||||
| /// `float32`, `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`, `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`, `uint32`, `uint64`. | |||||
| /// The tensor to reduce.</param> | |||||
| /// <param name="axis">A `Tensor`. Must be one of the following types: `int32`, `int64`. The dimensions to reduce.</param> | |||||
| /// <param name="keep_dims"> An optional `bool`. Defaults to `False`. If true, retain reduced dimensions with length 1.</param> | |||||
| /// <param name="name"> A name for the operation (optional).</param> | |||||
| /// <returns> A `Tensor`. Has the same type as `input`.</returns> | |||||
| public static Tensor mean(Tensor input, Tensor axis, bool keep_dims= false, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Mean", name, args: new { input, axis }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor add(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Add", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor squared_difference(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("SquaredDifference", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor cast(Tensor x, TF_DataType DstT, bool Truncate= false, string name= "") | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Cast", name, args: new { x, DstT, Truncate }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor neg(Tensor x, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Neg", name, args: new { x }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor sub<Tx, Ty>(Tx x, Ty y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor mul(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Mul", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor real_div(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("RealDiv", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor floor_mod(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("FloorMod", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor floor_div(Tensor x, Tensor y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("FloorDiv", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Multiply the matrix "a" by the matrix "b". | |||||
| /// </summary> | |||||
| /// <param name="a"></param> | |||||
| /// <param name="b"></param> | |||||
| /// <param name="transpose_a"></param> | |||||
| /// <param name="transpose_b"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor mat_mul(Tensor a, Tensor b, bool transpose_a = false, bool transpose_b = false, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("MatMul", name, args: new { a, b, transpose_a, transpose_b }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Returns the max of x and y (i.e. x > y ? x : y) element-wise. | |||||
| /// </summary> | |||||
| /// <param name="x"></param> | |||||
| /// <param name="y"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor maximum<T1, T2>(T1 x, T2 y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Maximum", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor pow<Tx, Ty>(Tx x, Ty y, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Pow", name, args: new { x, y }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| public static Tensor sum(Tensor input, Tensor axis = null, bool keep_dims = false, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { input, reduction_indices = axis, keep_dims }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| /// <summary> | |||||
| /// Creates a sequence of numbers. | |||||
| /// </summary> | |||||
| /// <param name="start"></param> | |||||
| /// <param name="limit"></param> | |||||
| /// <param name="delta"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor range(Tensor start, Tensor limit, Tensor delta, string name = null) | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Range", name, new { start, limit, delta }); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -24,33 +24,34 @@ namespace Tensorflow | |||||
| }); | }); | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// | |||||
| /// Computes the mean of elements across dimensions of a tensor. | |||||
| /// Reduces `input_tensor` along the dimensions given in `axis`. | |||||
| /// Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each | |||||
| /// entry in `axis`. If `keepdims` is true, the reduced dimensionsare retained with length 1. | |||||
| /// If `axis` is None, all dimensions are reduced, and a tensor with a single element is returned. | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="input_tensor"></param> | |||||
| /// <param name="axes"></param> | |||||
| /// <param name="keepdims"></param> | |||||
| /// <param name="name"></param> | |||||
| public static Tensor reduce_mean(Tensor input_tensor, int[] axes = null, bool keepdims = false, string name = null) | |||||
| /// <param name="input_tensor"> The tensor to reduce. Should have numeric type.</param> | |||||
| /// <param name="axis">The dimensions to reduce. If `None` (the default), reduces all | |||||
| /// dimensions.Must be in the range `[-rank(input_tensor), rank(input_tensor))`.</param> | |||||
| /// <param name="keepdims"> If true, retains reduced dimensions with length 1.</param> | |||||
| /// <param name="name"> A name for the operation (optional).</param> | |||||
| public static Tensor reduce_mean(Tensor input_tensor, int[] axis = null, bool keepdims = false, string name = null) | |||||
| { | { | ||||
| throw new NotFiniteNumberException(); | |||||
| var r = _ReductionDims(input_tensor, new Tensor(axis)); | |||||
| var m = gen_math_ops.mean(input_tensor, r); | |||||
| return _may_reduce_to_scalar(keepdims, m); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Reduction Operation | |||||
| /// Returns (x - y)(x - y) element-wise. | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="x"></param> | |||||
| /// <param name="axis"></param> | |||||
| /// <param name="reduction_indices"></param> | |||||
| public void _ReductionDims(Tensor x, int[] axis, int[] reduction_indices = null) | |||||
| /// <param name="x"> A `Tensor`. Must be one of the following types: `bfloat16`, `half`, `float32`, `float64`, `int32`, `int64`, `complex64`, `complex128`.</param> | |||||
| /// <param name="y"> A `Tensor`. Must have the same type as `x`.</param> | |||||
| /// <param name="name"> A name for the operation (optional).</param> | |||||
| /// <returns>A `Tensor`. Has the same type as `x`.</returns> | |||||
| public static Tensor square_difference(Tensor x, Tensor y, string name = null) | |||||
| { | { | ||||
| if (reduction_indices != null || reduction_indices.Length != 0) | |||||
| { | |||||
| if (axis != null) | |||||
| { | |||||
| } | |||||
| } | |||||
| throw new NotSupportedException("Can't specify both axis' and 'reduction_indices'."); | |||||
| var m = gen_math_ops.squared_difference(x, y); | |||||
| return m; | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -9,24 +9,46 @@ namespace Tensorflow | |||||
| /// <summary> | /// <summary> | ||||
| /// Calculate the mean and variance of `x` | /// Calculate the mean and variance of `x` | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="x"></param> | |||||
| /// <param name="axes"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="keep_dims"></param> | |||||
| /// <returns></returns> | |||||
| public (Tensor, Tensor) moments(Tensor x, | |||||
| /// <param name="x"> A `Tensor`.</param> | |||||
| /// <param name="axes"> Array of ints. Axes along which to compute mean and variance.</param> | |||||
| /// <param name="name"> Name used to scope the operations that compute the moments.</param> | |||||
| /// <param name="keep_dims"> Produce moments with the same dimensionality as the input.</param> | |||||
| /// <returns> Two `Tensor` objects: `mean` and `variance`.</returns> | |||||
| public Tuple<Tensor, Tensor> moments(Tensor x, | |||||
| int[] axes, | int[] axes, | ||||
| string name = null, | string name = null, | ||||
| bool keep_dims = false) | bool keep_dims = false) | ||||
| { | { | ||||
| Tuple<Tensor, Tensor> t = null; | |||||
| with<ops.name_scope>(new ops.name_scope(name, "moments", new { x, axes }), scope => | with<ops.name_scope>(new ops.name_scope(name, "moments", new { x, axes }), scope => | ||||
| { | { | ||||
| // The dynamic range of fp16 is too limited to support the collection of | |||||
| // sufficient statistics. As a workaround we simply perform the operations | |||||
| // on 32-bit floats before converting the mean and variance back to fp16 | |||||
| var y = math_ops.cast(x, TF_DataType.TF_FLOAT); | var y = math_ops.cast(x, TF_DataType.TF_FLOAT); | ||||
| // mean = math_ops.reduce_mean(y, axes, keepdims = True, name = "mean") | |||||
| // Compute true mean while keeping the dims for proper broadcasting. | |||||
| var mean = math_ops.reduce_mean(y, axes, keep_dims = true, name = "mean"); | |||||
| // Sample variance, not unbiased variance | |||||
| // Note: stop_gradient does not change the gradient that gets | |||||
| // backpropagated to the mean from the variance calculation, | |||||
| // because that gradient is zero | |||||
| var variance = math_ops.reduce_mean(math_ops.reduce_mean(math_ops.square_difference(y, array_ops.stop_gradient(mean)), axes, keep_dims = true, name = "Variance")); | |||||
| if (!keep_dims) | |||||
| { | |||||
| mean = array_ops.squeeze(mean, axes); | |||||
| variance = array_ops.squeeze(variance, axes); | |||||
| } | |||||
| // TODO: if x.dtype == dtypes.float16: | |||||
| if (x.dtype == TF_DataType.TF_FLOAT) | |||||
| { | |||||
| t = Tuple.Create(math_ops.cast(mean, x.dtype), math_ops.cast(variance, x.dtype)); | |||||
| return; | |||||
| } | |||||
| else { | |||||
| t = Tuple.Create(mean, variance); | |||||
| } | |||||
| }); | }); | ||||
| throw new NotImplementedException(""); | |||||
| return t; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -19,20 +19,41 @@ namespace TensorFlowNET.Examples | |||||
| public void fit(NDArray X, NDArray y) | public void fit(NDArray X, NDArray y) | ||||
| { | { | ||||
| // separate training points by class | |||||
| // shape : nb_class * nb_samples * nb_features | |||||
| NDArray unique_y = y.unique<long>(); | NDArray unique_y = y.unique<long>(); | ||||
| NDArray points_by_class = np.array(y.Data<long>().Where(ys => unique_y.Data<long>().Contains(ys))); | |||||
| foreach (long cls in unique_y) | |||||
| Dictionary<int, List<NDArray>> dic = new Dictionary<int, List<NDArray>>(); | |||||
| // Init uy in dic | |||||
| foreach (int uy in unique_y.Data<int>()) | |||||
| { | { | ||||
| dic.Add(uy, new List<NDArray>()); | |||||
| } | |||||
| // Separate training points by class | |||||
| // Shape : nb_classes * nb_samples * nb_features | |||||
| int maxCount = 0; | |||||
| foreach (var (x, t) in zip(X.Data<float>(), y.Data<int>())) | |||||
| { | |||||
| int curClass = (y[t, 0] as NDArray).Data<int>().First(); | |||||
| List<NDArray> l = dic[curClass]; | |||||
| l.Add(x); | |||||
| if (l.Count > maxCount) | |||||
| { | |||||
| maxCount = l.Count; | |||||
| } | |||||
| dic.Add(curClass, l); | |||||
| } | |||||
| NDArray points_by_class = np.zeros(dic.Count,maxCount,X.shape[1]); | |||||
| foreach (KeyValuePair<int, List<NDArray>> kv in dic) | |||||
| { | |||||
| var cls = kv.Value.ToArray(); | |||||
| for (int i = 0; i < dic.Count; i++) | |||||
| { | |||||
| points_by_class[i] = dic[i]; | |||||
| } | |||||
| } | } | ||||
| // estimate mean and variance for each class / feature | // estimate mean and variance for each class / feature | ||||
| // shape : nb_classes * nb_features | // shape : nb_classes * nb_features | ||||
| var cons = tf.constant(points_by_class); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||