Browse Source

experimental v0.20 version.

tags/v0.20
Oceania2018 5 years ago
parent
commit
332b1351e2
33 changed files with 262 additions and 504 deletions
  1. +1
    -1
      src/TensorFlowNET.Core/APIs/c_api.cs
  2. +3
    -0
      src/TensorFlowNET.Core/Eager/EagerTensor.cs
  3. +14
    -17
      src/TensorFlowNET.Core/Eager/Execute.cs
  4. +0
    -15
      src/TensorFlowNET.Core/Eager/wrap_tfe_src..cs
  5. +0
    -33
      src/TensorFlowNET.Core/Eager/wrap_tfe_src.RecordGradient.cs
  6. +0
    -62
      src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_Execute.cs
  7. +0
    -163
      src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
  8. +34
    -0
      src/TensorFlowNET.Core/Keras/Optimizers/OptimizerV2.cs
  9. +26
    -5
      src/TensorFlowNET.Core/Operations/array_ops.cs
  10. +20
    -13
      src/TensorFlowNET.Core/Operations/gen_array_ops.cs
  11. +45
    -35
      src/TensorFlowNET.Core/Operations/gen_math_ops.cs
  12. +17
    -0
      src/TensorFlowNET.Core/Operations/math_ops.cs
  13. +9
    -0
      src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs
  14. +18
    -6
      src/TensorFlowNET.Core/Tensors/Tensor.Value.cs
  15. +1
    -0
      src/TensorFlowNET.Core/Tensors/constant_op.cs
  16. +1
    -0
      src/TensorFlowNET.Core/Tensors/tf.constant.cs
  17. +9
    -5
      src/TensorFlowNET.Core/Variables/ResourceVariable.Implicit.cs
  18. +0
    -8
      src/TensorFlowNET.Core/Variables/gen_state_ops.py.cs
  19. +4
    -0
      src/TensorFlowNet.Benchmarks/README.md
  20. +10
    -11
      src/TensorFlowNet.Benchmarks/TensorBenchmark.cs
  21. +5
    -2
      src/TensorFlowNet.Benchmarks/Tensorflow.Benchmark.csproj
  22. +1
    -3
      test/TensorFlowNET.UnitTest/Basics/VariableTest.cs
  23. +1
    -0
      test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs
  24. +1
    -0
      test/TensorFlowNET.UnitTest/CApiColocationTest.cs
  25. +3
    -10
      test/TensorFlowNET.UnitTest/ConstantTest.cs
  26. +1
    -0
      test/TensorFlowNET.UnitTest/Eager/GradientEagerTest.cs
  27. +0
    -110
      test/TensorFlowNET.UnitTest/GradientTest/GradientTapeTest.cs
  28. +1
    -0
      test/TensorFlowNET.UnitTest/GradientTest/GradientTest.cs
  29. +1
    -0
      test/TensorFlowNET.UnitTest/GraphTest.cs
  30. +2
    -1
      test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
  31. +32
    -0
      test/TensorFlowNET.UnitTest/Training/BasicLinearModel.cs
  32. +1
    -0
      test/TensorFlowNET.UnitTest/functional_ops_test/ScanTestCase.cs
  33. +1
    -4
      test/Tensorflow.Keras.UnitTest/OptimizerTest.cs

+ 1
- 1
src/TensorFlowNET.Core/APIs/c_api.cs View File

@@ -43,7 +43,7 @@ namespace Tensorflow
/// </summary>
public partial class c_api
{
public const string TensorFlowLibName = @"D:\SciSharp\tensorflow-google\bazel-bin\tensorflow\tensorflow.dll";
public const string TensorFlowLibName = "tensorflow";

public static string StringPiece(IntPtr handle)
{


+ 3
- 0
src/TensorFlowNET.Core/Eager/EagerTensor.cs View File

@@ -39,6 +39,9 @@ namespace Tensorflow.Eager
EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle);
}

public IntPtr GetTfeTensorHandle()
=> tfe_tensor_handle;

public override string ToString()
{
switch (rank)


+ 14
- 17
src/TensorFlowNET.Core/Eager/Execute.cs View File

@@ -35,22 +35,24 @@ namespace Tensorflow.Eager

// TFE_TensorHandle
using var status = new Status();
var retVals = wrap_tfe_src.TFE_Execute(ctx, ctx.device_name, op_name, inputs, attrs, num_outputs, status);
/*var retVals = wrap_tfe_src.TFE_Execute(ctx, ctx.device_name, op_name, inputs, attrs, num_outputs, status);

return new EagerTensor((TFE_TensorHandle)retVals[0]);
return new EagerTensor((TFE_TensorHandle)retVals[0]);*/

/*IntPtr[] outputs = new IntPtr[num_outputs];
c_api.TFE_QuickExecute(ctx, ctx.device_name,
"Sum",
inputs.Select(x => (IntPtr)(TFE_TensorHandle)(x as EagerTensor)).ToArray(), inputs.Length,
op => wrap_tfe_src.SetOpAttrs(ctx, op, attrs, 0, status),
outputs, num_outputs,
status);
IntPtr[] outputs = new IntPtr[num_outputs];
c_api.TFE_QuickExecute(ctx,
ctx.device_name,
op_name,
inputs.Select(x => (x as EagerTensor).GetTfeTensorHandle()).ToArray(),
inputs.Length,
op => wrap_tfe_src.SetOpAttrs(ctx, op, attrs, status),
outputs,
num_outputs,
status);
status.Check(true);

var tfe_tensor_handle = outputs[0];
var eager_tensor_handle = c_api.TFE_EagerTensorFromHandle(ctx, tfe_tensor_handle);
return new EagerTensor(eager_tensor_handle);*/
TFE_TensorHandle tfe_tensor_handle = outputs[0];
return new EagerTensor(tfe_tensor_handle);
}

public (TF_DataType, Tensor[]) args_to_matching_eager(Context ctx, TF_DataType default_dtype = TF_DataType.DtInvalid, object[] args = null)
@@ -83,10 +85,5 @@ namespace Tensorflow.Eager
else
throw new NotImplementedException("");
}

public void record_gradient(string op_name, InputList inputs, Dictionary<string, object> attrs, Tensor[] results, string name = null)
{
wrap_tfe_src.RecordGradient(op_name, inputs._inputs, attrs, results, name);
}
}
}

+ 0
- 15
src/TensorFlowNET.Core/Eager/wrap_tfe_src..cs View File

@@ -1,15 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System;
using static Tensorflow.OpDef.Types;

namespace Tensorflow.Eager
{
/// <summary>
/// python\eager\pywrap_tfe_src.cc
/// </summary>
public partial class wrap_tfe_src
{

}
}

+ 0
- 33
src/TensorFlowNET.Core/Eager/wrap_tfe_src.RecordGradient.cs View File

@@ -1,33 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System;
using Tensorflow.Gradients;

namespace Tensorflow.Eager
{
/// <summary>
/// python\eager\pywrap_tfe_src.cc
/// </summary>
public partial class wrap_tfe_src
{
public static void RecordGradient(string op_name, Tensor[] inputs, Dictionary<string, object> attrs, Tensor[] results, string name = null)
{
var input_ids = inputs.Select(x => x.Id).ToArray();
var input_dtypes = inputs.Select(x => x.dtype).ToArray();

bool should_record = false;
foreach (var input_dtype in input_dtypes)
{
if (Tape.IsDtypeTrainable(input_dtype.as_datatype_enum()))
{
should_record = true;
break;
}
}
if (!should_record) return;

var op_outputs = results;
var op_inputs = inputs;
}
}
}

+ 0
- 62
src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_Execute.cs View File

@@ -1,62 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System;
using static Tensorflow.OpDef.Types;

namespace Tensorflow.Eager
{
/// <summary>
/// python\eager\pywrap_tfe_src.cc
/// </summary>
public partial class wrap_tfe_src
{
public static IntPtr[] TFE_Execute(Context ctx,
string device_name,
string op_name,
Tensor[] inputs,
object[] attrs,
int num_outputs,
Status status)
=> TFE_ExecuteCancelable(ctx, device_name, op_name, inputs, attrs, num_outputs, status);

public static IntPtr[] TFE_ExecuteCancelable(Context ctx,
string device_name,
string op_name,
Tensor[] inputs,
object[] attrs,
int num_outputs,
Status status)
{
var op = GetOp(ctx, op_name, status);
status.Check(true);
c_api.TFE_OpSetDevice(op, device_name, status);
if(status.ok())
{
for (int i = 0; i < inputs.Length; ++i)
{
TFE_TensorHandle tensor_handle;
switch (inputs[i])
{
case EagerTensor et:
tensor_handle = (TFE_TensorHandle)et;
break;
default:
tensor_handle = c_api.TFE_NewTensorHandle(inputs[i], status);
break;
}
c_api.TFE_OpAddInput(op, tensor_handle, status);
}
}
if (status.ok())
SetOpAttrs(ctx, op, attrs, status);

var outputs = new IntPtr[num_outputs];
if (status.ok())
{
c_api.TFE_Execute(op, outputs, ref num_outputs, status);
status.Check(true);
}
return outputs;
}
}
}

+ 0
- 163
src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs View File

@@ -10,169 +10,6 @@ namespace Tensorflow.Eager
/// </summary>
public partial class wrap_tfe_src
{
static int kFastPathExecuteInputStartIndex = 0;

[Obsolete]
public static EagerTensor TFE_FastPathExecute(Context ctx,
string device_name,
string opName,
string name,
Action callbacks,
params object[] args)
{
int args_size = args.Length;
var attr_list_sizes = new Dictionary<string, long>();
using (var status = new Status())
{
var op = GetOp(ctx, opName, status);

var op_def = Graph.TFE_GetOpDef(opName);

// Set non-inferred attrs, including setting defaults if the attr is passed in
// as None.
for (int i = kFastPathExecuteInputStartIndex + op_def.InputArg.Count; i < args_size; i += 2)
{
var attr_name = args[i].ToString();
var attr_value = args[i + 1];

foreach(var attr in op_def.Attr)
{
if(attr_name == attr.Name)
{
SetOpAttrWithDefaults(ctx, op, attr, attr_name, attr_value, attr_list_sizes, status);
status.Check(true);
break;
}
}
}

c_api.TFE_OpSetDevice(op, device_name, status);
status.Check(true);

// Add inferred attrs and inputs.
for (int i = 0; i < op_def.InputArg.Count; i++)
{
var input_arg = op_def.InputArg[i];
if (!string.IsNullOrEmpty(input_arg.NumberAttr))
{
int len = (args[kFastPathExecuteInputStartIndex + i] as object[]).Length;
c_api.TFE_OpSetAttrInt(op, input_arg.NumberAttr, len);
attr_list_sizes[input_arg.NumberAttr] = len;

if (len > 0)
{
var fast_input_array = (object[])args[i];
// First item adds the type attr.
if (!AddInputToOp(fast_input_array[i], true, input_arg, op, status))
return null;

for (var j = 1; j < len; j++)
{
// Since the list is homogeneous, we don't need to re-add the attr.
if (!AddInputToOp(fast_input_array[j], false, input_arg, op, status))
return null;
}
}
}
else if (!string.IsNullOrEmpty(input_arg.TypeListAttr))
{

}
else
{
// The item is a single item.
AddInputToOp(args[i], true, input_arg, op, status);
}
}

int num_retvals = 0;
for (int i = 0; i < op_def.OutputArg.Count; i++)
{
var output_arg = op_def.OutputArg[i];
var delta = 1L;
if (!string.IsNullOrEmpty(output_arg.NumberAttr))
delta = attr_list_sizes[output_arg.NumberAttr];
else if (!string.IsNullOrEmpty(output_arg.TypeListAttr))
delta = attr_list_sizes[output_arg.TypeListAttr];
if(delta < 0)
throw new RuntimeError("Attributes suggest that the size of an output list is less than 0");
num_retvals += (int)delta;
}

var retVals = new IntPtr[num_retvals];
c_api.TFE_Execute(op, retVals, ref num_retvals, status);
status.Check(true);

return num_retvals == 0 ? null : new EagerTensor(retVals[0]);
}
}

private static TFE_Op GetOp(Context ctx, string op_or_function_name, Status status)
{
var maybe_op = ReleaseThreadLocalOp();
if (maybe_op != IntPtr.Zero)
{
c_api.TFE_OpReset(maybe_op, op_or_function_name, ctx.device_name, status);
}
else
{
maybe_op = c_api.TFE_NewOp(ctx, op_or_function_name, status);
op = maybe_op;
}

status.Check(true);
return maybe_op;
}

static TFE_Op op;
private static TFE_Op ReleaseThreadLocalOp()
{
return op;
}

/// <summary>
/// Adds input and type attr to the op, and to the list of flattened
/// inputs/attrs.
/// </summary>
/// <param name="inputs"></param>
/// <param name="add_type_attr"></param>
/// <param name="input_arg"></param>
/// <param name="op"></param>
/// <param name="status"></param>
/// <returns></returns>
private static bool AddInputToOp(object inputs,
bool add_type_attr,
ArgDef input_arg,
IntPtr op,
Status status)
{
TFE_TensorHandle input_handle;

// ConvertToTensor();
switch (inputs)
{
case EagerTensor input:
input_handle = (TFE_TensorHandle)input;
break;
case EagerTensor[] input_list:
input_handle = (TFE_TensorHandle)input_list[0];
break;
default:
throw new NotImplementedException("");
}

if(add_type_attr && !string.IsNullOrEmpty(input_arg.TypeAttr))
{
var dtype = c_api.TFE_TensorHandleDataType(input_handle);
c_api.TFE_OpSetAttrType(op, input_arg.TypeAttr, dtype);
}

c_api.TFE_OpAddInput(op, input_handle, status);
status.Check(true);

return true;
}

public static void SetOpAttrs(Context ctx, TFE_Op op, object[] attrs, Status out_status)
{
var len = attrs.Length;


+ 34
- 0
src/TensorFlowNET.Core/Keras/Optimizers/OptimizerV2.cs View File

@@ -21,6 +21,7 @@ namespace Tensorflow.Keras.Optimizers
Dictionary<string, float> _hyper = new Dictionary<string, float>();
Dictionary<string, ResourceVariable> _hyper_variables = new Dictionary<string, ResourceVariable>();
protected bool _momentum;
protected float _initial_decay = 0.0f;

public OptimizerV2() : base()
{
@@ -40,16 +41,49 @@ namespace Tensorflow.Keras.Optimizers
//var apply_state =
_prepare(var_list);

_aggregate_gradients(grads_and_vars);

return control_flow_ops.no_op();
});
}

void _aggregate_gradients(IEnumerable<(Tensor, ResourceVariable)> grads_and_vars)
{
var lr_t = _hyper_variables["learning_rate"];
foreach (var grad_and_var in grads_and_vars)
{
var grad = grad_and_var.Item1;
var variable = grad_and_var.Item2;
// variable.Handle - grad * lr_t.Handle;
}
}

void _prepare(ResourceVariable[] var_list)
{
var keys = new HashSet<(string, TF_DataType)>();
foreach(var variable in var_list)
{
var lr_t = _prepare_local(variable.Device, variable.dtype.as_base_dtype());
var momentum = _get_hyper("momentum", variable.dtype);
array_ops.identity(momentum);
}
}

ResourceVariable _prepare_local(string var_device, TF_DataType var_dtype)
{
var lr_t = _get_hyper("learning_rate", var_dtype);
if(_initial_decay > 0)
{

}

return lr_t;
}

ResourceVariable _get_hyper(string name, TF_DataType dtype = TF_DataType.DtInvalid)
{
var value = _hyper_variables[name];
return math_ops.cast(value, dtype);
}

void _create_all_weights(ResourceVariable[] var_list)


+ 26
- 5
src/TensorFlowNET.Core/Operations/array_ops.cs View File

@@ -226,6 +226,21 @@ namespace Tensorflow
private static Tensor expand_dims_v2(Tensor input, int axis, string name = null)
=> gen_array_ops.expand_dims(input, axis, name);

/// <summary>
/// Creates a tensor filled with a scalar value.
/// This operation creates a tensor of shape `dims` and fills it with `value`.
/// </summary>
/// <param name="dims">A 1-D sequence of non-negative numbers.</param>
/// <param name="value">A value to fill the returned `tf.Tensor`.</param>
/// <param name="name">Optional string. The name of the output `tf.Tensor`.</param>
/// <returns>A `tf.Tensor` with shape `dims` and the same dtype as `value`.</returns>
public static Tensor fill(Tensor dims, Tensor value, string name = null)
{
var result = gen_array_ops.fill(dims, value, name: name);
// tensor_util.maybe_set_static_shape(result, dims)
return result;
}

/// <summary>
/// Returns the rank of a tensor.
/// </summary>
@@ -312,20 +327,26 @@ namespace Tensorflow
});
}

public static Tensor ones(int[] dims, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null)
=> tf_with(ops.name_scope(name, "ones", new { dims }), scope =>
public static Tensor ones(TensorShape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = null)
=> tf_with(ops.name_scope(name, "ones", shape), scope =>
{
dtype = dtype.as_base_dtype();
name = scope;
var shape_tensor = constant_op._tensor_shape_tensor_conversion_function(shape);
Tensor ones = null;
switch (dtype)
{
case TF_DataType.TF_DOUBLE:
return _constant_if_small(1.0d, dims, dtype, name);
ones = constant(1.0d);
break;
case TF_DataType.TF_FLOAT:
return _constant_if_small(1.0f, dims, dtype, name);
ones = constant(1.0f);
break;
default:
return _constant_if_small(1, dims, dtype, name);
ones = constant(1);
break;
}
return fill(shape_tensor, ones, name: name);
});

public static Tensor one_hot(Tensor indices, int depth,


+ 20
- 13
src/TensorFlowNET.Core/Operations/gen_array_ops.cs View File

@@ -54,17 +54,26 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
try
{
var _result = wrap_tfe_src.TFE_FastPathExecute(tf.context, tf.context.device_name,
"ConcatV2", name, null,
values, axis);
return _result;
}
catch (Exception)
{
return concat_v2_eager_fallback(values, axis, name, tf.context);
}
using var status = new Status();
EagerTensorHandle tensor = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
"ConcatV2", name, new IntPtr[]
{
values as EagerTensor,
axis as EagerTensor
}, 2, null, status);
status.Check(true);
return tensor;
}

var _op = _op_def_lib._apply_op_helper("ConcatV2", name: name, args: new { values, axis });
return _op.output;
}

public static Tensor concat_v2(Tensor[] values, Tensor axis, string name = null)
{
if (tf.context.executing_eagerly())
{
return concat_v2_eager_fallback(values, axis, name, tf.context);
}

var _op = _op_def_lib._apply_op_helper("ConcatV2", name: name, args: new { values, axis });
@@ -176,8 +185,6 @@ namespace Tensorflow
_attrs["dtype"] = _op.get_attr("dtype");
_attrs["shape"] = _op.get_attr("shape");

_execute.record_gradient("Placeholder", _inputs_flat, _attrs, _result, name);

return new Tensor(_op, 0, dtype);
}



+ 45
- 35
src/TensorFlowNET.Core/Operations/gen_math_ops.cs View File

@@ -131,25 +131,18 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
try
{
using var status = new Status();
var tensor = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
"Mean", name,
new IntPtr[]
{
using var status = new Status();
var tensor = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
"Mean", name,
new IntPtr[]
{
input as EagerTensor,
axis as EagerTensor
}, 2,
op => wrap_tfe_src.SetOpAttrs(tf.context, op, new object[] { "keep_dims", keep_dims }, status),
status);
status.Check(true);
return new EagerTensor(tensor);
}
catch (Exception)
{
return mean_eager_fallback(input as Tensor[], axis as Tensor, keep_dims: keep_dims, name: name, ctx: tf.context);
}
}, 2,
op => wrap_tfe_src.SetOpAttrs(tf.context, op, new object[] { "keep_dims", keep_dims }, status),
status);
status.Check(true);
return new EagerTensor(tensor);
}

var _op = _op_def_lib._apply_op_helper("Mean", name, args: new { input, reduction_indices = axis, keep_dims = keep_dims });
@@ -157,6 +150,18 @@ namespace Tensorflow
return _op.output;
}

public static Tensor mean(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null)
{
if (tf.context.executing_eagerly())
{
return mean_eager_fallback(inputs, axis, keep_dims: keep_dims, name: name, ctx: tf.context);
}

var _op = _op_def_lib._apply_op_helper("Mean", name, args: new { inputs, reduction_indices = axis, keep_dims = keep_dims });

return _op.output;
}

private static Tensor mean_eager_fallback(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null, Context ctx = null)
{
var (_attr_T, input) = _execute.args_to_matching_eager(ctx, args: new[] { inputs });
@@ -1036,26 +1041,18 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
try
{
using var status = new Status();
var tensor = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name,
"Sum", name,
new IntPtr[]
{
using var status = new Status();
var tensor = 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(tf.context, op, new object[] { "keep_dims", keep_dims }, status),
status);
status.Check(true);
return new EagerTensor(tensor);
}
catch (Exception)
{
return _sum_eager_fallback(input as Tensor[], axis as Tensor,
keep_dims: keep_dims, name: name, ctx: tf.context);
}
}, 2,
op => wrap_tfe_src.SetOpAttrs(tf.context, op, new object[] { "keep_dims", keep_dims }, status),
status);
status.Check(true);
return new EagerTensor(tensor);
}

var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { input, reduction_indices = axis, keep_dims });
@@ -1063,6 +1060,19 @@ namespace Tensorflow
return _op.outputs[0];
}

public static Tensor _sum(Tensor[] inputs, Tensor axis = default, bool keep_dims = false, string name = null)
{
if (tf.context.executing_eagerly())
{
return _sum_eager_fallback(inputs, axis,
keep_dims: keep_dims, name: name, ctx: tf.context);
}

var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { inputs, reduction_indices = axis, keep_dims });

return _op.outputs[0];
}

private static Tensor _sum_eager_fallback(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null, Context ctx = null)
{
var (_attr_T, input) = _execute.args_to_matching_eager(ctx, args: new[] { inputs });


+ 17
- 0
src/TensorFlowNET.Core/Operations/math_ops.cs View File

@@ -85,6 +85,23 @@ namespace Tensorflow
});
}

public static ResourceVariable cast(ResourceVariable x, TF_DataType dtype = TF_DataType.DtInvalid, string name = null)
{
var base_type = dtype.as_base_dtype();
if (base_type == x.dtype)
return x;

return tf_with(ops.name_scope(name, "Cast", new { x }), scope =>
{
name = scope;
var t_x = ops.convert_to_tensor(x, name: "x");
if (t_x.dtype.as_base_dtype() != base_type)
t_x = gen_math_ops.cast(t_x, base_type, name: name);

return x;
});
}

public static Tensor cast(Tensor x, TF_DataType dtype = TF_DataType.DtInvalid, string name = null)
{
var base_type = dtype.as_base_dtype();


+ 9
- 0
src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs View File

@@ -23,6 +23,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using static Tensorflow.c_api;
using static Tensorflow.Binding;

namespace Tensorflow
{
@@ -59,6 +60,14 @@ namespace Tensorflow
//no need to set AllocationType = AllocationType.None;
}

public Tensor(int value)
{
unsafe
{
_handle = TF_NewTensor(tf.int32, dims: null, num_dims: 0, data: null, len: sizeof(int));
}
}

/// <summary>
/// Create a new Tensor from the given unmanaged memory pointer (which must be allocated, fixed or pinned by the caller)
/// Note: the caller is responsible for freeing the memory. Calling Dispose on this object will dispose the TensorFlow tensor


+ 18
- 6
src/TensorFlowNET.Core/Tensors/Tensor.Value.cs View File

@@ -1,4 +1,5 @@
using NumSharp;
using NumSharp.Backends;
using NumSharp.Backends.Unmanaged;
using NumSharp.Utilities;
using System;
@@ -150,26 +151,37 @@ namespace Tensorflow
/// Tensor has rank 0.
/// </returns>
public NDArray numpy()
=> NDims == 0 ? GetScalar(dtype) : GetNDArray(dtype);
=> GetNDArray(dtype);

protected unsafe NDArray GetNDArray(TF_DataType dtype)
{
UnmanagedStorage storage;
switch (dtype)
{
case TF_DataType.TF_STRING:
return StringData();
case TF_DataType.TF_INT32:
return ToArray<int>();
storage = new UnmanagedStorage(NPTypeCode.Int32);
break;
case TF_DataType.TF_FLOAT:
return ToArray<float>();
storage = new UnmanagedStorage(NPTypeCode.Float);
break;
case TF_DataType.TF_DOUBLE:
return ToArray<double>();
storage = new UnmanagedStorage(NPTypeCode.Double);
break;
default:
return BufferToArray();
}

storage.Allocate(new Shape(shape));

var bytesize = (long)this.bytesize;
System.Buffer.MemoryCopy(buffer.ToPointer(), storage.Address, bytesize, bytesize);

return new NDArray(storage);
}

protected unsafe NDArray GetScalar(TF_DataType dtype)
/*protected unsafe NDArray GetScalar(TF_DataType dtype)
{
switch(dtype)
{
@@ -184,7 +196,7 @@ namespace Tensorflow
default:
return BufferToArray();
}
}
}*/

/// <summary>
/// Copies the memory of current buffer onto newly allocated array.


+ 1
- 0
src/TensorFlowNET.Core/Tensors/constant_op.cs View File

@@ -116,6 +116,7 @@ namespace Tensorflow
// convert data type
if (dtype != TF_DataType.DtInvalid &&
value.GetType().Name != "NDArray" &&
value.GetType().BaseType.Name != "Array" &&
dtypes.as_base_dtype(dtype) != dtypes.as_dtype(value.GetType()))
{
switch (dtype)


+ 1
- 0
src/TensorFlowNET.Core/Tensors/tf.constant.cs View File

@@ -15,6 +15,7 @@
******************************************************************************/

using NumSharp;
using Tensorflow.Eager;

namespace Tensorflow
{


+ 9
- 5
src/TensorFlowNET.Core/Variables/ResourceVariable.Implicit.cs View File

@@ -16,13 +16,10 @@ namespace Tensorflow
}

public static implicit operator Tensor(ResourceVariable var)
=> var.Handle;
=> var._dense_var_to_tensor();

public static implicit operator EagerTensor(ResourceVariable var)
=> var.Handle as EagerTensor;

/*public static implicit operator ResourceVariable(Tensor var)
=> var.ResourceVar;*/
=> var._dense_var_to_tensor() as EagerTensor;

public static implicit operator RefVariable(ResourceVariable var)
{
@@ -31,5 +28,12 @@ namespace Tensorflow

public static implicit operator IntPtr(ResourceVariable var)
=> var._handle;

Tensor _dense_var_to_tensor(TF_DataType dtype = TF_DataType.DtInvalid,
string name = null,
bool as_ref = false)
{
return value();
}
}
}

+ 0
- 8
src/TensorFlowNET.Core/Variables/gen_state_ops.py.cs View File

@@ -48,8 +48,6 @@ namespace Tensorflow
_attrs["container"] = _op.get_attr("container");
_attrs["shared_name"] = _op.get_attr("shared_name");

_execute.record_gradient("VariableV2", _inputs_flat, _attrs, _result, name);

return _result[0];
}

@@ -76,8 +74,6 @@ namespace Tensorflow
_attrs["validate_shape"] = _op.get_attr("validate_shape");
_attrs["use_locking"] = _op.get_attr("use_locking");

_execute.record_gradient("Assign", _inputs_flat, _attrs, _result, name);

return _result[0];
}

@@ -96,8 +92,6 @@ namespace Tensorflow
_attrs["validate_shape"] = _op.get_attr("validate_shape");
_attrs["use_locking"] = _op.get_attr("use_locking");

_execute.record_gradient("Assign", _inputs_flat, _attrs, _result, name);

return _result[0];
}

@@ -116,8 +110,6 @@ namespace Tensorflow
_attrs["validate_shape"] = _op.get_attr("validate_shape");
_attrs["use_locking"] = _op.get_attr("use_locking");

_execute.record_gradient("Assign", _inputs_flat, _attrs, _result, name);

return _result[0];
}



+ 4
- 0
src/TensorFlowNet.Benchmarks/README.md View File

@@ -0,0 +1,4 @@
```powershell
dotnet run -c release
```


+ 10
- 11
src/TensorFlowNet.Benchmarks/TensorBenchmark.cs View File

@@ -6,7 +6,7 @@ using static Tensorflow.Binding;

namespace TensorFlowBenchmark
{
[SimpleJob(launchCount: 1, warmupCount: 2, targetCount: 10)]
[SimpleJob(launchCount: 1, warmupCount: 1, targetCount: 10)]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class TensorBenchmark
{
@@ -64,7 +64,7 @@ namespace TensorFlowBenchmark
public void TensorFromNDArray()
{
var g = new Graph();
for (int i = 0; i < 1000; i++)
for (int i = 0; i < 100; i++)
{
using (var tensor = new Tensor(new NDArray(data)))
{
@@ -73,15 +73,14 @@ namespace TensorFlowBenchmark
}
}

//[Benchmark]
//public void Constant()
//{
// for (int i = 0; i < 100; i++)
// {
// //var tensor = new Tensor(new NDArray(data));
// var c = tf.constant(42.0);
// }
//}
[Benchmark]
public void Constant()
{
for (int i = 0; i < 100; i++)
{
var c = tf.constant(3112);
}
}

}
}


+ 5
- 2
src/TensorFlowNet.Benchmarks/Tensorflow.Benchmark.csproj View File

@@ -28,8 +28,11 @@

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.1.0" />
<PackageReference Include="TensorFlow.NET" Version="0.15.1" />
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TensorFlowNET.Core\Tensorflow.Binding.csproj" />
</ItemGroup>

</Project>

+ 1
- 3
test/TensorFlowNET.UnitTest/Basics/VariableTest.cs View File

@@ -10,12 +10,10 @@ namespace TensorFlowNET.UnitTest.Basics
[TestClass]
public class VariableTest
{
[Ignore]
[TestMethod]
public void NewVariable()
{
var x = tf.Variable(10, name: "new_variable_x");
Assert.AreEqual("new_variable_x:0", x.Name);
var x = tf.Variable(10, name: "x");
Assert.AreEqual(0, x.shape.ndim);
Assert.AreEqual(10, (int)x.numpy());
}


+ 1
- 0
test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs View File

@@ -8,6 +8,7 @@ namespace TensorFlowNET.UnitTest
/// tensorflow\c\c_api_test.cc
/// `class CApiAttributesTest`
/// </summary>
[Ignore]
[TestClass]
public class CApiAttributesTestcs : CApiTest, IDisposable
{


+ 1
- 0
test/TensorFlowNET.UnitTest/CApiColocationTest.cs View File

@@ -9,6 +9,7 @@ namespace TensorFlowNET.UnitTest
/// tensorflow\c\c_api_test.cc
/// `class CApiColocationTest`
/// </summary>
[Ignore]
[TestClass]
public class CApiColocationTest : CApiTest, IDisposable
{


+ 3
- 10
test/TensorFlowNET.UnitTest/ConstantTest.cs View File

@@ -17,8 +17,11 @@ namespace TensorFlowNET.UnitTest
public void ScalarConst()
{
var tensor1 = tf.constant(8); // int
Assert.AreEqual(tensor1.dtype, TF_DataType.TF_INT32);
var tensor2 = tf.constant(6.0f); // float
Assert.AreEqual(tensor2.dtype, TF_DataType.TF_FLOAT);
var tensor3 = tf.constant(6.0); // double
Assert.AreEqual(tensor3.dtype, TF_DataType.TF_DOUBLE);
}

/*[DataTestMethod]
@@ -173,15 +176,5 @@ namespace TensorFlowNET.UnitTest
Assert.AreEqual(str.Length, Marshal.ReadByte(dst));
//c_api.TF_StringDecode(dst, (ulong)str.Length, IntPtr.Zero, ref dst_len, status);
}

/// <summary>
/// tensorflow\c\c_api_test.cc
/// TestEncodeDecode
/// </summary>
[TestMethod]
public void EncodeDecode()
{

}
}
}

+ 1
- 0
test/TensorFlowNET.UnitTest/Eager/GradientEagerTest.cs View File

@@ -10,6 +10,7 @@ namespace TensorFlowNET.UnitTest.Gradient
[TestClass]
public class GradientEagerTest : PythonTest
{
[Ignore]
[TestMethod]
public void ConstantSq()
{


+ 0
- 110
test/TensorFlowNET.UnitTest/GradientTest/GradientTapeTest.cs View File

@@ -1,110 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NumSharp;
using System.Linq;
using Tensorflow;
using static Tensorflow.Binding;

namespace TensorFlowNET.UnitTest.Gradient
{
[TestClass]
public class GradientTapeTest
{
[TestMethod]
public void GradientTape()
{
var x = tf.ones((2, 2));
using (var t = tf.GradientTape())
{
t.watch(x);
}
}

[TestMethod]
public void Gradients()
{
var a = tf.constant(0.0);
var b = 2.0 * a;
//Assert.AreEqual(b.name, "mul:0");
//Assert.AreEqual(b.op.inputs[0].name, "mul/x:0");
//Assert.AreEqual(b.op.inputs[1].name, "Const:0");

var ys = a + b;
//Assert.AreEqual(ys.name, "add:0");
//Assert.AreEqual(ys.op.inputs[0].name, "Const:0");
//Assert.AreEqual(ys.op.inputs[1].name, "mul:0");

//var g = tf.gradients(ys, new Tensor[] { a, b }, stop_gradients: new Tensor[] { a, b });
//Assert.AreEqual(g[0].name, "gradients/Fill:0");
//Assert.AreEqual(g[1].name, "gradients/Fill:0");
}

[TestMethod]
public void Gradient2x()
{
var x = tf.constant(7.0f);
var y = x * x * tf.constant(0.1f);

//var grad = tf.gradients(y, x);
//Assert.AreEqual(grad[0].name, "gradients/AddN:0");

//float r = sess.run(grad[0]);
//Assert.AreEqual(r, 1.4f);
}

[TestMethod]
public void Gradient3x()
{
var graph = tf.Graph().as_default();
tf_with(tf.Session(graph), sess => {
var x = tf.constant(7.0f);
var y = x * x * x * tf.constant(0.1f);

var grad = tf.gradients(y, x);
Assert.AreEqual(grad[0].name, "gradients/AddN:0");

float r = sess.run(grad[0]);
Assert.AreEqual(r, 14.700001f);
});
}

[TestMethod]
public void StridedSlice()
{
var graph = tf.Graph().as_default();

var t = tf.constant(np.array(new int[,,]
{
{
{ 11, 12, 13 },
{ 21, 22, 23 }
},
{
{ 31, 32, 33 },
{ 41, 42, 43 }
},
{
{ 51, 52, 53 },
{ 61, 62, 63 }
}
}));

var slice = tf.strided_slice(t,
begin: new[] { 0, 0, 0 },
end: new[] { 3, 2, 3 },
strides: new[] { 2, 2, 2 });

var y = slice + slice;

var g = tf.gradients(y, new Tensor[] { slice, slice });

using (var sess = tf.Session(graph))
{
var r = sess.run(slice);

Assert.IsTrue(Enumerable.SequenceEqual(r.shape, new[] { 2, 1, 2 }));
Assert.IsTrue(Enumerable.SequenceEqual(r[0].GetData<int>(), new[] { 11, 13 }));
Assert.IsTrue(Enumerable.SequenceEqual(r[1].GetData<int>(), new[] { 51, 53 }));
}
}
}
}

+ 1
- 0
test/TensorFlowNET.UnitTest/GradientTest/GradientTest.cs View File

@@ -8,6 +8,7 @@ using static Tensorflow.Binding;

namespace TensorFlowNET.UnitTest.Gradient
{
[Ignore]
[TestClass]
public class GradientTest : PythonTest
{


+ 1
- 0
test/TensorFlowNET.UnitTest/GraphTest.cs View File

@@ -7,6 +7,7 @@ using static Tensorflow.Binding;

namespace TensorFlowNET.UnitTest
{
[Ignore]
[TestClass]
public class GraphTest : CApiTest
{


+ 2
- 1
test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj View File

@@ -19,7 +19,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -46,6 +46,7 @@
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
<PackageReference Include="NumSharp.Lite" Version="0.1.7" />
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.2.0" />
</ItemGroup>

<ItemGroup>


+ 32
- 0
test/TensorFlowNET.UnitTest/Training/BasicLinearModel.cs View File

@@ -0,0 +1,32 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NumSharp;
using System;
using System.Collections.Generic;
using System.Text;
using Tensorflow;
using static Tensorflow.Binding;

namespace TensorFlowNET.UnitTest.Training
{
[TestClass]
public class BasicLinearModel
{
int NUM_EXAMPLES = 1000;

[TestMethod]
public void FitLinear()
{
// Initialize the weights to `5.0` and the bias to `0.0`
// In practice, these should be initialized to random values (for example, with `tf.random.normal`)
var W = tf.Variable(5.0f);
var b = tf.Variable(0.0);

// define linear model
Func<NDArray, Tensor> model = (x) => W * x + b;

// var inputs = tf.random.normal(shape =[NUM_EXAMPLES]);
// noise = tf.random.normal(shape =[NUM_EXAMPLES])
// outputs = inputs * TRUE_W + TRUE_b + noise
}
}
}

+ 1
- 0
test/TensorFlowNET.UnitTest/functional_ops_test/ScanTestCase.cs View File

@@ -9,6 +9,7 @@ namespace TensorFlowNET.UnitTest.functional_ops_test
/// <summary>
/// https://www.tensorflow.org/api_docs/python/tf/scan
/// </summary>
[Ignore]
[TestClass]
public class ScanTestCase
{


+ 1
- 4
test/Tensorflow.Keras.UnitTest/OptimizerTest.cs View File

@@ -6,9 +6,6 @@ namespace Tensorflow.Keras.UnitTest
[TestClass]
public class OptimizerTest
{
[TestMethod]
public void BaseConstruct()
{
}

}
}

Loading…
Cancel
Save