diff --git a/TensorFlow.NET.sln b/TensorFlow.NET.sln
index 84a1aa7e..cae87d55 100644
--- a/TensorFlow.NET.sln
+++ b/TensorFlow.NET.sln
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Examples", "t
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\TensorFlowNET.Core\TensorFlowNET.Core.csproj", "{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TensorFlowNET.Utility", "src\TensorFlowNET.Utility\TensorFlowNET.Utility.csproj", "{00D9085C-0FC7-453C-A0CC-BAD98F44FEA0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD682AC0-7B2D-45D3-8B0D-C6D678B04144}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00D9085C-0FC7-453C-A0CC-BAD98F44FEA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00D9085C-0FC7-453C-A0CC-BAD98F44FEA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00D9085C-0FC7-453C-A0CC-BAD98F44FEA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00D9085C-0FC7-453C-A0CC-BAD98F44FEA0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/TensorFlowNET.Core/APIs/tf.array.cs b/src/TensorFlowNET.Core/APIs/tf.array.cs
new file mode 100644
index 00000000..9fb04b98
--- /dev/null
+++ b/src/TensorFlowNET.Core/APIs/tf.array.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow
+{
+ public static partial class tf
+ {
+ ///
+ /// Inserts a dimension of 1 into a tensor's shape.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A `Tensor` with the same data as `input`, but its shape has an additional
+ /// dimension of size 1 added.
+ ///
+ public static Tensor expand_dims(Tensor input, int axis = -1, string name = "", int dim = -1)
+ => array_ops.expand_dims(input, axis, name, dim);
+ }
+}
diff --git a/src/TensorFlowNET.Core/Operations/tf.init_ops.cs b/src/TensorFlowNET.Core/APIs/tf.init.cs
similarity index 100%
rename from src/TensorFlowNET.Core/Operations/tf.init_ops.cs
rename to src/TensorFlowNET.Core/APIs/tf.init.cs
diff --git a/src/TensorFlowNET.Core/APIs/tf.io.cs b/src/TensorFlowNET.Core/APIs/tf.io.cs
new file mode 100644
index 00000000..c792862e
--- /dev/null
+++ b/src/TensorFlowNET.Core/APIs/tf.io.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow
+{
+ public partial class tf
+ {
+ public static Tensor read_file(string filename, string name = "") => gen_io_ops.read_file(filename, name);
+
+ public static gen_image_ops image => new gen_image_ops();
+ }
+}
diff --git a/src/TensorFlowNET.Core/APIs/tf.linalg.cs b/src/TensorFlowNET.Core/APIs/tf.linalg.cs
index ccfbbc2b..923cf581 100644
--- a/src/TensorFlowNET.Core/APIs/tf.linalg.cs
+++ b/src/TensorFlowNET.Core/APIs/tf.linalg.cs
@@ -6,9 +6,6 @@ namespace Tensorflow
{
public static partial class tf
{
- public static unsafe Tensor matmul(Tensor a, Tensor b)
- {
- return gen_math_ops.mat_mul(a, b);
- }
+ public static unsafe Tensor matmul(Tensor a, Tensor b) => gen_math_ops.mat_mul(a, b);
}
}
diff --git a/src/TensorFlowNET.Core/Operations/Losses/tf.loss.cs b/src/TensorFlowNET.Core/APIs/tf.loss.cs
similarity index 100%
rename from src/TensorFlowNET.Core/Operations/Losses/tf.loss.cs
rename to src/TensorFlowNET.Core/APIs/tf.loss.cs
diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs
index 9df2f333..44e04b3e 100644
--- a/src/TensorFlowNET.Core/APIs/tf.math.cs
+++ b/src/TensorFlowNET.Core/APIs/tf.math.cs
@@ -6,25 +6,19 @@ namespace Tensorflow
{
public static partial class tf
{
- public static Tensor add(Tensor a, Tensor b)
- {
- return gen_math_ops.add(a, b);
- }
-
- public static Tensor sub(Tensor a, Tensor b)
- {
- return gen_math_ops.sub(a, b);
- }
-
- public static Tensor multiply(Tensor x, Tensor y)
- {
- return gen_math_ops.mul(x, y);
- }
-
- public static Tensor pow(Tensor x, double y)
- {
- return gen_math_ops.pow(x, y);
- }
+ public static Tensor add(Tensor a, Tensor b) => gen_math_ops.add(a, b);
+
+ public static Tensor sub(Tensor a, Tensor b) => gen_math_ops.sub(a, b);
+
+ public static Tensor subtract(Tensor x, T[] y, string name = "") where T : struct
+ => gen_math_ops.sub(x, ops.convert_to_tensor(y, dtype: x.dtype.as_base_dtype(), name: "y"), name);
+
+ public static Tensor multiply(Tensor x, Tensor y) => gen_math_ops.mul(x, y);
+
+ public static Tensor divide(Tensor x, T[] y, string name = "") where T : struct
+ => x / ops.convert_to_tensor(y, dtype: x.dtype.as_base_dtype(), name: "y");
+
+ public static Tensor pow(Tensor x, double y) => gen_math_ops.pow(x, y);
///
/// Computes the sum of elements across dimensions of a tensor.
@@ -32,9 +26,9 @@ namespace Tensorflow
///
///
///
- public static Tensor reduce_sum(Tensor input, int[] axis = null)
- {
- return math_ops.reduce_sum(input);
- }
+ public static Tensor reduce_sum(Tensor input, int[] axis = null) => math_ops.reduce_sum(input);
+
+ public static Tensor cast(Tensor x, TF_DataType dtype = TF_DataType.DtInvalid, string name = "")
+ => math_ops.cast(x, dtype, name);
}
}
diff --git a/src/TensorFlowNET.Core/Framework/importer.py.cs b/src/TensorFlowNET.Core/Framework/importer.py.cs
index e8c971c7..80faf264 100644
--- a/src/TensorFlowNET.Core/Framework/importer.py.cs
+++ b/src/TensorFlowNET.Core/Framework/importer.py.cs
@@ -28,8 +28,8 @@ namespace Tensorflow
var graph = ops.get_default_graph();
Python.with(new ops.name_scope(name, "import", input_map.Values), scope =>
{
- /*prefix = scope;
- if (!string.IsNullOrEmpty(prefix))
+ prefix = scope;
+ /*if (!string.IsNullOrEmpty(prefix))
prefix = prefix.Substring(0, prefix.Length - 1);
else
prefix = "";*/
@@ -113,9 +113,16 @@ namespace Tensorflow
var key = attr_def.Name;
if(attr_def.DefaultValue != null)
{
- var value = node_def.Attr[key];
- if (value == null)
+ if (node_def.Attr.ContainsKey(key))
+ {
+ var value = node_def.Attr[key];
+ if (value == null)
+ node_def.Attr[key] = attr_def.DefaultValue;
+ }
+ else
+ {
node_def.Attr[key] = attr_def.DefaultValue;
+ }
}
}
}
diff --git a/src/TensorFlowNET.Core/Graphs/Graph.Operation.cs b/src/TensorFlowNET.Core/Graphs/Graph.Operation.cs
index 2f16b880..a9ad7a14 100644
--- a/src/TensorFlowNET.Core/Graphs/Graph.Operation.cs
+++ b/src/TensorFlowNET.Core/Graphs/Graph.Operation.cs
@@ -24,6 +24,9 @@ namespace Tensorflow
return c_api.TF_NewOperation(_handle, opType, opName);
}
+ public Operation get_operation_by_name(string name)
+ => as_graph_element(name, allow_tensor: false, allow_operation: true) as Operation;
+
public ITensorOrOperation _get_operation_by_name_unsafe(string name)
{
return _nodes_by_name.ContainsKey(name) ? _nodes_by_name[name] : null;
diff --git a/src/TensorFlowNET.Core/Operations/array_ops.py.cs b/src/TensorFlowNET.Core/Operations/array_ops.py.cs
index 38ca2799..5bfd279c 100644
--- a/src/TensorFlowNET.Core/Operations/array_ops.py.cs
+++ b/src/TensorFlowNET.Core/Operations/array_ops.py.cs
@@ -46,6 +46,10 @@ namespace Tensorflow
}
}
+ public static Tensor expand_dims(Tensor input, int axis = -1, string name = "", int dim = -1) => expand_dims_v2(input, axis, name);
+
+ private static Tensor expand_dims_v2(Tensor input, int axis, string name = "") => gen_array_ops.expand_dims(input, axis, name);
+
public static Tensor rank(Tensor input, string name = "")
{
return math_ops.rank_internal(input, name, optimize: true);
diff --git a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
index 8bf345fc..dbf25111 100644
--- a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
@@ -12,6 +12,13 @@ namespace Tensorflow
public static OpDefLibrary _op_def_lib = new OpDefLibrary();
public static Execute _execute = new Execute();
+ public static Tensor expand_dims(Tensor input, int axis, string name = "")
+ {
+ var _op = _op_def_lib._apply_op_helper("ExpandDims", name: name, args: new { input, dim = axis });
+
+ return _op.outputs[0];
+ }
+
public static Tensor greater(Tx x, Ty y, string name = "")
{
var _op = _op_def_lib._apply_op_helper("Greater", name: name, args: new { x, y });
diff --git a/src/TensorFlowNET.Core/Operations/gen_image_ops.py.cs b/src/TensorFlowNET.Core/Operations/gen_image_ops.py.cs
new file mode 100644
index 00000000..c6eeae8f
--- /dev/null
+++ b/src/TensorFlowNET.Core/Operations/gen_image_ops.py.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow
+{
+ public class gen_image_ops
+ {
+ public static OpDefLibrary _op_def_lib = new OpDefLibrary();
+
+ public Tensor decode_jpeg(Tensor contents,
+ int channels = 0,
+ int ratio = 1,
+ bool fancy_upscaling = true,
+ bool try_recover_truncated = false,
+ float acceptable_fraction = 1,
+ string dct_method = "",
+ string name = "")
+ {
+ // Add nodes to the TensorFlow graph.
+ if (tf.context.executing_eagerly())
+ {
+ throw new NotImplementedException("decode_jpeg");
+ }
+ else
+ {
+ var _op = _op_def_lib._apply_op_helper("DecodeJpeg", name: name, args: new
+ {
+ contents,
+ channels,
+ ratio,
+ fancy_upscaling,
+ try_recover_truncated,
+ acceptable_fraction,
+ dct_method
+ });
+
+ return _op.outputs[0];
+ }
+ }
+
+ public Tensor resize_bilinear(Tensor images, int[] size, bool align_corners = false, string name = "")
+ {
+ if (tf.context.executing_eagerly())
+ {
+ throw new NotImplementedException("resize_bilinear");
+ }
+ else
+ {
+ var _op = _op_def_lib._apply_op_helper("ResizeBilinear", name: name, args: new
+ {
+ images,
+ size,
+ align_corners
+ });
+
+ return _op.outputs[0];
+ }
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Core/Operations/gen_io_ops.py.cs b/src/TensorFlowNET.Core/Operations/gen_io_ops.py.cs
index 6c33a80e..34300e78 100644
--- a/src/TensorFlowNET.Core/Operations/gen_io_ops.py.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_io_ops.py.cs
@@ -21,5 +21,12 @@ namespace Tensorflow
return _op.outputs;
}
+
+ public static Tensor read_file(string filename, string name = "")
+ {
+ var _op = _op_def_lib._apply_op_helper("ReadFile", name: name, args: new { filename });
+
+ return _op.outputs[0];
+ }
}
}
diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
index 57921209..a93ffd8c 100644
--- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
@@ -17,6 +17,13 @@ namespace Tensorflow
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 = "")
{
var _op = _op_def_lib._apply_op_helper("Neg", name, args: new { x });
diff --git a/src/TensorFlowNET.Core/Operations/math_ops.py.cs b/src/TensorFlowNET.Core/Operations/math_ops.py.cs
index 1e78285a..ed0a5609 100644
--- a/src/TensorFlowNET.Core/Operations/math_ops.py.cs
+++ b/src/TensorFlowNET.Core/Operations/math_ops.py.cs
@@ -4,7 +4,7 @@ using System.Text;
namespace Tensorflow
{
- public class math_ops
+ public class math_ops : Python
{
public static Tensor add(Tensor x, Tensor y, string name = "") => gen_math_ops.add(x, y, name);
@@ -14,7 +14,14 @@ namespace Tensorflow
if(base_type == x.dtype)
return x;
- throw new NotImplementedException("math_ops.cast");
+ return with(new ops.name_scope(name, "Cast", new { x }), scope =>
+ {
+ x = ops.convert_to_tensor(x, name: "x");
+ if (x.dtype.as_base_dtype() != base_type)
+ x = gen_math_ops.cast(x, base_type, name: name);
+
+ return x;
+ });
}
///
diff --git a/src/TensorFlowNET.Core/Sessions/BaseSession.cs b/src/TensorFlowNET.Core/Sessions/BaseSession.cs
index 9748e33f..553ec32f 100644
--- a/src/TensorFlowNET.Core/Sessions/BaseSession.cs
+++ b/src/TensorFlowNET.Core/Sessions/BaseSession.cs
@@ -35,8 +35,7 @@ namespace Tensorflow
c_api.TF_DeleteSessionOptions(opts);
}
-
- public virtual NDArray run(object fetches, FeedItem[] feed_dict = null)
+ public virtual NDArray run(object fetches, params FeedItem[] feed_dict)
{
return _run(fetches, feed_dict);
}
@@ -62,6 +61,9 @@ namespace Tensorflow
var subfeed_dtype = subfeed_t.dtype.as_numpy_datatype();
switch (subfeed_val)
{
+ case NDArray nd:
+ feed_dict_tensor[subfeed_t] = nd;
+ break;
case float floatVal:
feed_dict_tensor[subfeed_t] = (NDArray)floatVal;
break;
@@ -193,25 +195,25 @@ namespace Tensorflow
case TF_DataType.TF_INT16:
var shorts = new short[tensor.size];
for (ulong i = 0; i < tensor.size; i++)
- shorts[i] = *(short*)(c_api.TF_TensorData(output) + (int)(tensor.dataTypeSize * i));
+ shorts[i] = *(short*)(c_api.TF_TensorData(output) + (int)(tensor.itemsize * i));
nd = np.array(shorts).reshape(ndims);
break;
case TF_DataType.TF_INT32:
var ints = new int[tensor.size];
for (ulong i = 0; i < tensor.size; i++)
- ints[i] = *(int*)(c_api.TF_TensorData(output) + (int)(tensor.dataTypeSize * i));
+ ints[i] = *(int*)(c_api.TF_TensorData(output) + (int)(tensor.itemsize * i));
nd = np.array(ints).reshape(ndims);
break;
case TF_DataType.TF_FLOAT:
var floats = new float[tensor.size];
for (ulong i = 0; i < tensor.size; i++)
- floats[i] = *(float*)(c_api.TF_TensorData(output) + (int)(tensor.dataTypeSize * i));
+ floats[i] = *(float*)(c_api.TF_TensorData(output) + (int)(tensor.itemsize * i));
nd = np.array(floats).reshape(ndims);
break;
case TF_DataType.TF_DOUBLE:
var doubles = new double[tensor.size];
for (ulong i = 0; i < tensor.size; i++)
- doubles[i] = *(double*)(c_api.TF_TensorData(output) + (int)(tensor.dataTypeSize * i));
+ doubles[i] = *(double*)(c_api.TF_TensorData(output) + (int)(tensor.itemsize * i));
nd = np.array(doubles).reshape(ndims);
break;
default:
diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.cs b/src/TensorFlowNET.Core/Tensors/Tensor.cs
index 7cd0e95f..50a5bbdd 100644
--- a/src/TensorFlowNET.Core/Tensors/Tensor.cs
+++ b/src/TensorFlowNET.Core/Tensors/Tensor.cs
@@ -35,8 +35,8 @@ namespace Tensorflow
private TF_DataType _dtype = TF_DataType.DtInvalid;
public TF_DataType dtype => _handle == IntPtr.Zero ? _dtype : c_api.TF_TensorType(_handle);
public ulong bytesize => _handle == IntPtr.Zero ? 0 : c_api.TF_TensorByteSize(_handle);
- public ulong dataTypeSize => _handle == IntPtr.Zero ? 0 : c_api.TF_DataTypeSize(dtype);
- public ulong size => _handle == IntPtr.Zero ? 0 : bytesize / dataTypeSize;
+ public ulong itemsize => _handle == IntPtr.Zero ? 0 : c_api.TF_DataTypeSize(dtype);
+ public ulong size => _handle == IntPtr.Zero ? 0 : bytesize / itemsize;
public IntPtr buffer => _handle == IntPtr.Zero ? IntPtr.Zero : c_api.TF_TensorData(_handle);
public int num_consumers(TF_Output oper_out) => _handle == IntPtr.Zero ? 0 : c_api.TF_OperationOutputNumConsumers(oper_out);
@@ -122,7 +122,7 @@ namespace Tensorflow
for (ulong i = 0; i < size; i++)
{
- data[i] = Marshal.PtrToStructure(buffer + (int)(i * dataTypeSize));
+ data[i] = Marshal.PtrToStructure(buffer + (int)(i * itemsize));
}
return data;
diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs
index 4c0bd693..2075d554 100644
--- a/src/TensorFlowNET.Core/Tensors/dtypes.cs
+++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs
@@ -21,7 +21,7 @@ namespace Tensorflow
case TF_DataType.TF_STRING:
return typeof(string);
default:
- throw new NotImplementedException("as_numpy_datatype failed");
+ return null;
}
}
diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs
index a7d728d2..11761f56 100644
--- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs
+++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs
@@ -44,6 +44,7 @@ namespace Tensorflow
// We first convert value to a numpy array or scalar.
NDArray nparray = null;
+ var np_dt = dtype.as_numpy_datatype();
if (values is NDArray nd)
{
@@ -54,31 +55,61 @@ namespace Tensorflow
if (values == null)
throw new ValueError("None values not supported.");
- switch (values)
+ if(np_dt == null)
{
- case bool boolVal:
- nparray = boolVal;
- break;
- case int intVal:
- nparray = intVal;
- break;
- case int[] intVals:
- nparray = np.array(intVals);
- break;
- case float floatVal:
- nparray = floatVal;
- break;
- case double doubleVal:
- nparray = doubleVal;
- break;
- case string strVal:
- nparray = strVal;
- break;
- case string[] strVals:
- nparray = strVals;
- break;
- default:
- throw new Exception("make_tensor_proto Not Implemented");
+ switch (values)
+ {
+ case bool boolVal:
+ nparray = boolVal;
+ break;
+ case int intVal:
+ nparray = intVal;
+ break;
+ case int[] intVals:
+ nparray = np.array(intVals);
+ break;
+ case float floatVal:
+ nparray = floatVal;
+ break;
+ case double doubleVal:
+ nparray = doubleVal;
+ break;
+ case string strVal:
+ nparray = strVal;
+ break;
+ case string[] strVals:
+ nparray = strVals;
+ break;
+ default:
+ throw new NotImplementedException("make_tensor_proto Not Implemented");
+ }
+ }
+ else
+ {
+ // convert data type
+ switch (np_dt.Name)
+ {
+ case "Int32":
+ if (values.GetType().IsArray)
+ nparray = np.array((int[])values, np_dt);
+ else
+ nparray = (int)values;
+ break;
+ case "Single":
+ if (values.GetType().IsArray)
+ nparray = np.array((float[])values, np_dt);
+ else
+ nparray = (float)values;
+ break;
+ case "Double":
+ nparray = (double)values;
+ break;
+ case "String":
+ nparray = values.ToString();
+ break;
+ default:
+ throw new NotImplementedException("make_tensor_proto Not Implemented");
+ }
}
}
diff --git a/src/TensorFlowNET.Core/Train/Saving/Saver.cs b/src/TensorFlowNET.Core/Train/Saving/Saver.cs
index 4cdc85a5..cb95628d 100644
--- a/src/TensorFlowNET.Core/Train/Saving/Saver.cs
+++ b/src/TensorFlowNET.Core/Train/Saving/Saver.cs
@@ -169,9 +169,9 @@ namespace Tensorflow
if (!_is_empty)
{
- model_checkpoint_path = sess.run(_saver_def.SaveTensorName, new FeedItem[] {
+ model_checkpoint_path = sess.run(_saver_def.SaveTensorName,
new FeedItem(_saver_def.FilenameTensorName, checkpoint_file)
- });
+ );
if (write_state)
{
@@ -227,10 +227,8 @@ namespace Tensorflow
if (tf.context.executing_eagerly())
;
else
- sess.run(_saver_def.RestoreOpName, new FeedItem[]
- {
- new FeedItem(_saver_def.FilenameTensorName, save_path)
- });
+ sess.run(_saver_def.RestoreOpName,
+ new FeedItem(_saver_def.FilenameTensorName, save_path));
}
///
diff --git a/src/TensorFlowNET.Core/ops.py.cs b/src/TensorFlowNET.Core/ops.py.cs
index 026e7feb..42833978 100644
--- a/src/TensorFlowNET.Core/ops.py.cs
+++ b/src/TensorFlowNET.Core/ops.py.cs
@@ -418,6 +418,9 @@ namespace Tensorflow
string name = "", TF_DataType preferred_dtype = TF_DataType.DtInvalid,
bool as_ref = false)
{
+ if (dtype == TF_DataType.DtInvalid)
+ dtype = preferred_dtype;
+
switch (value)
{
case Tensor tensor:
@@ -432,6 +435,8 @@ namespace Tensorflow
return constant_op.constant(intArray, dtype: dtype, name: name);
case float floatVal:
return constant_op.constant(floatVal, dtype: dtype, name: name);
+ case float[] floatArray:
+ return constant_op.constant(floatArray, dtype: dtype, name: name);
case double doubleVal:
return constant_op.constant(doubleVal, dtype: dtype, name: name);
case RefVariable varVal:
diff --git a/src/TensorFlowNET.Utility/Compress.cs b/src/TensorFlowNET.Utility/Compress.cs
new file mode 100644
index 00000000..086f7a9b
--- /dev/null
+++ b/src/TensorFlowNET.Utility/Compress.cs
@@ -0,0 +1,37 @@
+using ICSharpCode.SharpZipLib.GZip;
+using ICSharpCode.SharpZipLib.Tar;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TensorFlowNET.Utility
+{
+ public class Compress
+ {
+ public static void ExtractTGZ(String gzArchiveName, String destFolder)
+ {
+ Console.WriteLine($"Extracting.");
+ var task = Task.Run(() =>
+ {
+ using (var inStream = File.OpenRead(gzArchiveName))
+ {
+ using (var gzipStream = new GZipInputStream(inStream))
+ {
+ using (TarArchive tarArchive = TarArchive.CreateInputTarArchive(gzipStream))
+ tarArchive.ExtractContents(destFolder);
+ }
+ }
+ });
+
+ while (!task.IsCompleted)
+ {
+ Thread.Sleep(200);
+ Console.Write(".");
+ }
+
+ Console.WriteLine("");
+ Console.WriteLine("Extracting is completed.");
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Utility/TensorFlowNET.Utility.csproj b/src/TensorFlowNET.Utility/TensorFlowNET.Utility.csproj
new file mode 100644
index 00000000..efeb641a
--- /dev/null
+++ b/src/TensorFlowNET.Utility/TensorFlowNET.Utility.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.0
+ TensorFlowNET.Utility
+ TensorFlowNET.Utility
+
+
+
+
+
+
+
diff --git a/src/TensorFlowNET.Utility/Web.cs b/src/TensorFlowNET.Utility/Web.cs
new file mode 100644
index 00000000..dfaf5236
--- /dev/null
+++ b/src/TensorFlowNET.Utility/Web.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TensorFlowNET.Utility
+{
+ public class Web
+ {
+ public static bool Download(string url, string file)
+ {
+ if (File.Exists(file))
+ {
+ Console.WriteLine($"{file} already exists.");
+ return false;
+ }
+
+ var wc = new WebClient();
+ Console.WriteLine($"Downloading {file}");
+ var download = Task.Run(() => wc.DownloadFile(url, file));
+ while (!download.IsCompleted)
+ {
+ Thread.Sleep(1000);
+ Console.Write(".");
+ }
+ Console.WriteLine("");
+ Console.WriteLine($"Downloaded {file}");
+
+ return true;
+ }
+ }
+}
diff --git a/test/TensorFlowNET.Examples/LabelImage.cs b/test/TensorFlowNET.Examples/LabelImage.cs
new file mode 100644
index 00000000..c0f4193a
--- /dev/null
+++ b/test/TensorFlowNET.Examples/LabelImage.cs
@@ -0,0 +1,120 @@
+using ICSharpCode.SharpZipLib.GZip;
+using ICSharpCode.SharpZipLib.Tar;
+using NumSharp.Core;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tensorflow;
+
+namespace TensorFlowNET.Examples
+{
+ ///
+ /// Port from tensorflow\examples\label_image\label_image.py
+ ///
+ public class LabelImage : Python, IExample
+ {
+ string dir = "label_image_data";
+ string pbFile = "inception_v3_2016_08_28_frozen.pb";
+ string labelFile = "imagenet_slim_labels.txt";
+ string picFile = "grace_hopper.jpg";
+ int input_height = 299;
+ int input_width = 299;
+ int input_mean = 0;
+ int input_std = 255;
+ string input_layer = "input";
+ string output_layer = "InceptionV3/Predictions/Reshape_1";
+
+ public void Run()
+ {
+ PrepareData();
+ var graph = LoadGraph(Path.Join(dir, pbFile));
+ var t = ReadTensorFromImageFile(Path.Join(dir, picFile),
+ input_height: input_height,
+ input_width: input_width,
+ input_mean: input_mean,
+ input_std: input_std);
+
+ var input_name = "import/" + input_layer;
+ var output_name = "import/" + output_layer;
+
+ var input_operation = graph.get_operation_by_name(input_name);
+ var output_operation = graph.get_operation_by_name(output_name);
+
+ NDArray results = null;
+ with(tf.Session(graph), sess =>
+ {
+ results = sess.run(output_operation.outputs[0], new FeedItem(input_operation.outputs[0], t));
+ });
+
+ // equivalent np.squeeze
+ results.reshape(results.shape.Where(x => x > 1).ToArray());
+ // top_k = results.argsort()[-5:][::-1]
+ var top_k = results.Data().Take(5).ToArray();
+ var labels = LoadLabels(Path.Join(dir, labelFile));
+ foreach (var i in top_k)
+ Console.WriteLine($"{labels[i]}, {results[i]}");
+ }
+
+ private string[] LoadLabels(string file)
+ {
+ return File.ReadAllLines(file);
+ }
+
+ private Graph LoadGraph(string modelFile)
+ {
+ var graph = tf.Graph();
+ var graph_def = GraphDef.Parser.ParseFrom(File.ReadAllBytes(modelFile));
+ importer.import_graph_def(graph_def);
+ return graph;
+ }
+
+ private NDArray ReadTensorFromImageFile(string file_name,
+ int input_height = 299,
+ int input_width = 299,
+ int input_mean = 0,
+ int input_std = 255)
+ {
+ string input_name = "file_reader";
+ string output_name = "normalized";
+ Tensor image_reader = null;
+
+ var file_reader = tf.read_file(file_name, input_name);
+ image_reader = tf.image.decode_jpeg(file_reader, channels: 3, name: "jpeg_reader");
+
+ var float_caster = tf.cast(image_reader, tf.float32);
+ var dims_expander = tf.expand_dims(float_caster, 0);
+ var resized = tf.image.resize_bilinear(dims_expander, new int[] { input_height, input_width });
+ var normalized = tf.divide(tf.subtract(resized, new float[] { input_mean }), new float[] { input_std });
+
+ return with(tf.Session(), sess =>
+ {
+ var result = sess.run(normalized);
+ return result;
+ });
+ }
+
+ private void PrepareData()
+ {
+
+ Directory.CreateDirectory(dir);
+
+ // get model file
+ string url = "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz";
+
+ string zipFile = Path.Join(dir, $"{pbFile}.tar.gz");
+ Utility.Web.Download(url, zipFile);
+
+ if (!File.Exists(Path.Join(dir, pbFile)))
+ Utility.Compress.ExtractTGZ(zipFile, dir);
+
+ // download sample picture
+ string pic = "grace_hopper.jpg";
+ Utility.Web.Download($"https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/examples/label_image/data/{pic}", Path.Join(dir, pic));
+ }
+ }
+}
diff --git a/test/TensorFlowNET.Examples/LinearRegression.cs b/test/TensorFlowNET.Examples/LinearRegression.cs
index 79db1ed9..65175cfb 100644
--- a/test/TensorFlowNET.Examples/LinearRegression.cs
+++ b/test/TensorFlowNET.Examples/LinearRegression.cs
@@ -65,21 +65,17 @@ namespace TensorFlowNET.Examples
{
foreach (var (x, y) in Python.zip(train_X, train_Y))
{
- sess.run(optimizer, feed_dict: new FeedItem[]
- {
+ sess.run(optimizer,
new FeedItem(X, x),
- new FeedItem(Y, y)
- });
+ new FeedItem(Y, y));
}
// Display logs per epoch step
if ((epoch + 1) % display_step == 0)
{
- var c = sess.run(cost, feed_dict: new FeedItem[]
- {
+ var c = sess.run(cost,
new FeedItem(X, train_X),
- new FeedItem(Y, train_Y)
- });
+ new FeedItem(Y, train_Y));
var rW = sess.run(W);
Console.WriteLine($"Epoch: {epoch + 1} cost={c} " +
$"W={rW} b={sess.run(b)}");
diff --git a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj
index 5ed00751..ec79057c 100644
--- a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj
+++ b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj
@@ -12,6 +12,7 @@
+
diff --git a/test/TensorFlowNET.UnitTest/OperationsTest.cs b/test/TensorFlowNET.UnitTest/OperationsTest.cs
index f0d0c8bd..601b66b9 100644
--- a/test/TensorFlowNET.UnitTest/OperationsTest.cs
+++ b/test/TensorFlowNET.UnitTest/OperationsTest.cs
@@ -33,11 +33,9 @@ namespace TensorFlowNET.UnitTest
using(var sess = tf.Session())
{
- var o = sess.run(c, feed_dict: new FeedItem[]
- {
+ var o = sess.run(c,
new FeedItem(a, 3.0f),
- new FeedItem(b, 2.0f)
- });
+ new FeedItem(b, 2.0f));
Assert.AreEqual((float)o, 5.0f);
}
}
diff --git a/test/TensorFlowNET.UnitTest/PlaceholderTest.cs b/test/TensorFlowNET.UnitTest/PlaceholderTest.cs
index f4ba9856..3bc6a892 100644
--- a/test/TensorFlowNET.UnitTest/PlaceholderTest.cs
+++ b/test/TensorFlowNET.UnitTest/PlaceholderTest.cs
@@ -17,10 +17,8 @@ namespace TensorFlowNET.UnitTest
Python.with(tf.Session(), sess =>
{
- var result = sess.run(y, feed_dict: new FeedItem[]
- {
- new FeedItem(x, 2)
- });
+ var result = sess.run(y,
+ new FeedItem(x, 2));
Assert.AreEqual((int)result, 6);
});
}