Browse Source

implement: (1)tf.nn.moments (2)math_ops.reduce_mean (3)math_ops.square_differnece (4)array_ops.squeeze

tags/v0.8.0
Bo Peng 6 years ago
parent
commit
b445e28f07
6 changed files with 501 additions and 375 deletions
  1. +243
    -208
      src/TensorFlowNET.Core/Operations/array_ops.py.cs
  2. +23
    -0
      src/TensorFlowNET.Core/Operations/gen_array_ops.cs
  3. +152
    -128
      src/TensorFlowNET.Core/Operations/gen_math_ops.cs
  4. +22
    -21
      src/TensorFlowNET.Core/Operations/math_ops.py.cs
  5. +32
    -10
      src/TensorFlowNET.Core/Operations/nn_impl.py.cs
  6. +29
    -8
      test/TensorFlowNET.Examples/NaiveBayesClassifier.cs

+ 243
- 208
src/TensorFlowNET.Core/Operations/array_ops.py.cs View File

@@ -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);
}
}
}

+ 23
- 0
src/TensorFlowNET.Core/Operations/gen_array_ops.cs View File

@@ -155,5 +155,28 @@ namespace Tensorflow
var _op = _op_def_lib._apply_op_helper("ZerosLike", name, new { x });
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];
}
}
}

+ 152
- 128
src/TensorFlowNET.Core/Operations/gen_math_ops.cs View File

@@ -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];
}
}
}

+ 22
- 21
src/TensorFlowNET.Core/Operations/math_ops.py.cs View File

@@ -24,33 +24,34 @@ namespace Tensorflow
});
}
/// <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>
/// <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>
/// Reduction Operation
/// Returns (x - y)(x - y) element-wise.
/// </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>


+ 32
- 10
src/TensorFlowNET.Core/Operations/nn_impl.py.cs View File

@@ -9,24 +9,46 @@ namespace Tensorflow
/// <summary>
/// Calculate the mean and variance of `x`
/// </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,
string name = null,
bool keep_dims = false)
{
Tuple<Tensor, Tensor> t = null;
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);
// 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;
}
}
}

+ 29
- 8
test/TensorFlowNET.Examples/NaiveBayesClassifier.cs View File

@@ -19,20 +19,41 @@ namespace TensorFlowNET.Examples

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 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
// shape : nb_classes * nb_features
var cons = tf.constant(points_by_class);
}
}
}

Loading…
Cancel
Save