| @@ -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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NumSharp.Core", "..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj", "{1FE7246F-9273-42A8-841C-98051356FB67}" | |||
| 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 | |||
| {1FE7246F-9273-42A8-841C-98051356FB67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {1FE7246F-9273-42A8-841C-98051356FB67}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {1FE7246F-9273-42A8-841C-98051356FB67}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {1FE7246F-9273-42A8-841C-98051356FB67}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| @@ -9,7 +9,7 @@ namespace Tensorflow | |||
| { | |||
| public static Tensor constant(NDArray nd, string name = "Const", bool verify_shape = false) | |||
| { | |||
| return constant_op.Create(nd, name, verify_shape); | |||
| return constant_op.Constant(nd, name, verify_shape); | |||
| } | |||
| } | |||
| } | |||
| @@ -21,14 +21,14 @@ namespace Tensorflow | |||
| return gen_math_ops.mul(x, y); | |||
| } | |||
| public static Tensor pow(Tensor x, Tensor y) | |||
| public static Tensor pow(Tensor x, double y) | |||
| { | |||
| return gen_math_ops.pow(x, y); | |||
| } | |||
| public static Tensor reduce_sum(Tensor input, int? axis = null) | |||
| public static Tensor reduce_sum(Tensor input, int[] axis = null) | |||
| { | |||
| return gen_math_ops.sum(input, input); | |||
| return gen_math_ops.sum(input, axis); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using NumSharp.Core; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Runtime.InteropServices; | |||
| @@ -21,21 +22,30 @@ namespace Tensorflow | |||
| string scope = g.unique_name(name) + "/"; | |||
| var default_type_attr_map = new Dictionary<string, object>(); | |||
| foreach (var attr_def in op_def.Attr) | |||
| { | |||
| if (attr_def.Type != "type") continue; | |||
| var key = attr_def.Name; | |||
| if(attr_def.DefaultValue != null) | |||
| { | |||
| default_type_attr_map[key] = attr_def.DefaultValue.Type; | |||
| } | |||
| } | |||
| var attrs = new Dictionary<string, object>(); | |||
| // Perform input type inference | |||
| var inputs = new List<Tensor>(); | |||
| var input_types = new List<TF_DataType>(); | |||
| // Perform input type inference | |||
| foreach (var input_arg in op_def.InputArg) | |||
| { | |||
| var input_name = input_arg.Name; | |||
| if (keywords[input_name] is double int_value) | |||
| { | |||
| keywords[input_name] = constant_op.Constant(int_value, input_name); | |||
| } | |||
| if (keywords[input_name] is Tensor value) | |||
| { | |||
| if (keywords.ContainsKey(input_name)) | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using NumSharp.Core; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Text; | |||
| @@ -42,6 +43,17 @@ namespace Tensorflow | |||
| return new Tensor(_op, 0, _op.OutputType(0)); | |||
| } | |||
| public static Tensor real_div(Tensor x, Tensor y) | |||
| { | |||
| var keywords = new Dictionary<string, object>(); | |||
| keywords.Add("x", x); | |||
| keywords.Add("y", y); | |||
| var _op = _op_def_lib._apply_op_helper("RealDiv", name: "truediv", keywords: keywords); | |||
| return new Tensor(_op, 0, _op.OutputType(0)); | |||
| } | |||
| public static Tensor mat_mul(Tensor a, Tensor b, bool transpose_a = false, bool transpose_b = false) | |||
| { | |||
| var keywords = new Dictionary<string, object>(); | |||
| @@ -55,7 +67,7 @@ namespace Tensorflow | |||
| return new Tensor(_op, 0, _op.OutputType(0)); | |||
| } | |||
| public static Tensor pow(Tensor x, Tensor y) | |||
| public static Tensor pow(Tensor x, double y) | |||
| { | |||
| var keywords = new Dictionary<string, object>(); | |||
| keywords.Add("x", x); | |||
| @@ -66,13 +78,15 @@ namespace Tensorflow | |||
| return new Tensor(_op, 0, _op.OutputType(0)); | |||
| } | |||
| public static Tensor sum(Tensor x, Tensor y) | |||
| public static Tensor sum(Tensor input, int[] axis = null) | |||
| { | |||
| if(axis == null) axis = new int[0]; | |||
| var keywords = new Dictionary<string, object>(); | |||
| keywords.Add("x", x); | |||
| keywords.Add("y", y); | |||
| keywords.Add("input", input); | |||
| keywords.Add("reduction_indices", constant_op.Constant(axis)); | |||
| keywords.Add("keep_dims", false); | |||
| var _op = _op_def_lib._apply_op_helper("Pow", name: "Pow", keywords: keywords); | |||
| var _op = _op_def_lib._apply_op_helper("Sum", keywords: keywords); | |||
| return new Tensor(_op, 0, _op.OutputType(0)); | |||
| } | |||
| @@ -7,7 +7,7 @@ using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class BaseSession : IDisposable | |||
| public class BaseSession | |||
| { | |||
| protected Graph _graph; | |||
| protected bool _opened; | |||
| @@ -35,19 +35,12 @@ namespace Tensorflow | |||
| c_api.TF_DeleteSessionOptions(opts); | |||
| } | |||
| public void Dispose() | |||
| public virtual NDArray run(Tensor fetches, Dictionary<Tensor, NDArray> feed_dict = null) | |||
| { | |||
| return _run(fetches, feed_dict); | |||
| } | |||
| public virtual object run(Tensor fetches, Dictionary<Tensor, NDArray> feed_dict = null) | |||
| { | |||
| var result = _run(fetches, feed_dict); | |||
| return result; | |||
| } | |||
| private object _run(Tensor fetches, Dictionary<Tensor, NDArray> feed_dict = null) | |||
| private NDArray _run(Tensor fetches, Dictionary<Tensor, NDArray> feed_dict = null) | |||
| { | |||
| var feed_dict_tensor = new Dictionary<Tensor, NDArray>(); | |||
| @@ -77,7 +70,7 @@ namespace Tensorflow | |||
| return fetch_handler.build_results(null, results); | |||
| } | |||
| private object[] _do_run(List<Tensor> fetch_list, Dictionary<Tensor, NDArray> feed_dict) | |||
| private NDArray[] _do_run(List<Tensor> fetch_list, Dictionary<Tensor, NDArray> feed_dict) | |||
| { | |||
| var feeds = feed_dict.Select(x => new KeyValuePair<TF_Output, Tensor>(x.Key._as_tf_output(), new Tensor(x.Value))).ToArray(); | |||
| var fetches = fetch_list.Select(x => x._as_tf_output()).ToArray(); | |||
| @@ -85,7 +78,7 @@ namespace Tensorflow | |||
| return _call_tf_sessionrun(feeds, fetches); | |||
| } | |||
| private unsafe object[] _call_tf_sessionrun(KeyValuePair<TF_Output, Tensor>[] feed_dict, TF_Output[] fetch_list) | |||
| private unsafe NDArray[] _call_tf_sessionrun(KeyValuePair<TF_Output, Tensor>[] feed_dict, TF_Output[] fetch_list) | |||
| { | |||
| // Ensure any changes to the graph are reflected in the runtime. | |||
| _extend_graph(); | |||
| @@ -109,14 +102,12 @@ namespace Tensorflow | |||
| status.Check(true); | |||
| object[] result = new object[fetch_list.Length]; | |||
| var result = new NDArray[fetch_list.Length]; | |||
| for (int i = 0; i < fetch_list.Length; i++) | |||
| { | |||
| var tensor = new Tensor(output_values[i]); | |||
| Type type = tensor.dtype.as_numpy_datatype(); | |||
| var ndims = tensor.shape.Select(x => (int)x).ToArray(); | |||
| switch (tensor.dtype) | |||
| { | |||
| case TF_DataType.TF_STRING: | |||
| @@ -124,25 +115,25 @@ namespace Tensorflow | |||
| // wired, don't know why we have to start from offset 9. | |||
| var bytes = tensor.Data(); | |||
| var output = UTF8Encoding.Default.GetString(bytes, 9, bytes.Length - 9); | |||
| result[i] = fetchValue(tensor, ndims, output); | |||
| result[i] = fetchValue(tensor, output); | |||
| } | |||
| break; | |||
| case TF_DataType.TF_FLOAT: | |||
| { | |||
| var output = *(float*)c_api.TF_TensorData(output_values[i]); | |||
| result[i] = fetchValue(tensor, ndims, output); | |||
| result[i] = fetchValue(tensor, output); | |||
| } | |||
| break; | |||
| case TF_DataType.TF_INT16: | |||
| { | |||
| var output = *(short*)c_api.TF_TensorData(output_values[i]); | |||
| result[i] = fetchValue(tensor, ndims, output); | |||
| result[i] = fetchValue(tensor, output); | |||
| } | |||
| break; | |||
| case TF_DataType.TF_INT32: | |||
| { | |||
| var output = *(int*)c_api.TF_TensorData(output_values[i]); | |||
| result[i] = fetchValue(tensor, ndims, output); | |||
| result[i] = fetchValue(tensor, output); | |||
| } | |||
| break; | |||
| default: | |||
| @@ -153,16 +144,22 @@ namespace Tensorflow | |||
| return result; | |||
| } | |||
| private object fetchValue<T>(Tensor tensor, int[] ndims, T output) | |||
| private NDArray fetchValue<T>(Tensor tensor, T output) | |||
| { | |||
| NDArray nd; | |||
| Type type = tensor.dtype.as_numpy_datatype(); | |||
| var ndims = tensor.shape.Select(x => (int)x).ToArray(); | |||
| if (tensor.NDims == 0) | |||
| { | |||
| return output; | |||
| nd = np.array(output).reshape(); | |||
| } | |||
| else | |||
| { | |||
| return np.array(output).reshape(ndims); | |||
| nd = np.array(output).reshape(ndims); | |||
| } | |||
| return nd; | |||
| } | |||
| /// <summary> | |||
| @@ -4,7 +4,7 @@ using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class Session : BaseSession | |||
| public class Session : BaseSession, IDisposable | |||
| { | |||
| private IntPtr _handle; | |||
| public Status Status { get; } | |||
| @@ -34,5 +34,12 @@ namespace Tensorflow | |||
| public static implicit operator IntPtr(Session session) => session._handle; | |||
| public static implicit operator Session(IntPtr handle) => new Session(handle); | |||
| public void Dispose() | |||
| { | |||
| Options.Dispose(); | |||
| Status.Dispose(); | |||
| c_api.TF_DeleteSession(_handle, Status); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using NumSharp.Core; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| @@ -21,7 +22,7 @@ namespace Tensorflow | |||
| } | |||
| } | |||
| public object build_results(object[] values) | |||
| public NDArray build_results(NDArray[] values) | |||
| { | |||
| return values[0]; | |||
| } | |||
| @@ -35,7 +35,7 @@ namespace Tensorflow | |||
| _final_fetches = _fetches; | |||
| } | |||
| public object build_results(Session session, object[] results) | |||
| public NDArray build_results(Session session, NDArray[] results) | |||
| { | |||
| return _fetch_mapper.build_results(results); | |||
| } | |||
| @@ -7,12 +7,25 @@ namespace Tensorflow | |||
| { | |||
| public static partial class c_api | |||
| { | |||
| /// <summary> | |||
| /// Destroy a session object. | |||
| /// | |||
| /// Even if error information is recorded in *status, this call discards all | |||
| /// local resources associated with the session. The session may not be used | |||
| /// during or after this call (and the session drops its reference to the | |||
| /// corresponding graph). | |||
| /// </summary> | |||
| /// <param name="session">TF_Session*</param> | |||
| /// <param name="status">TF_Status*</param> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TF_DeleteSession(IntPtr session, IntPtr status); | |||
| /// <summary> | |||
| /// Destroy an options object. | |||
| /// </summary> | |||
| /// <param name="opts">TF_SessionOptions*</param> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static unsafe extern void TF_DeleteSessionOptions(IntPtr opts); | |||
| public static extern void TF_DeleteSessionOptions(IntPtr opts); | |||
| /// <summary> | |||
| /// Return a new execution session with the associated graph, or NULL on | |||
| @@ -43,4 +43,8 @@ Docs: https://tensorflownet.readthedocs.io</Description> | |||
| <Content CopyToOutputDirectory="PreserveNewest" Include="./runtimes/win-x64/native/tensorflow.dll" Link="tensorflow.dll" Pack="true" PackagePath="runtimes/win-x64/native/tensorflow.dll" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,34 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public partial class Tensor | |||
| { | |||
| public static implicit operator Tensor(double scalar) | |||
| { | |||
| return constant_op.Constant(scalar); | |||
| } | |||
| public static implicit operator Tensor(int scalar) | |||
| { | |||
| return constant_op.Constant(scalar); | |||
| } | |||
| public static implicit operator IntPtr(Tensor tensor) | |||
| { | |||
| return tensor._handle; | |||
| } | |||
| public static implicit operator Tensor(IntPtr handle) | |||
| { | |||
| return new Tensor(handle); | |||
| } | |||
| public static implicit operator Tensor(RefVariable var) | |||
| { | |||
| return var._initial_value; | |||
| } | |||
| } | |||
| } | |||
| @@ -20,5 +20,10 @@ namespace Tensorflow | |||
| { | |||
| return gen_math_ops.mul(t1, t2); | |||
| } | |||
| public static Tensor operator /(Tensor t1, Tensor t2) | |||
| { | |||
| return gen_math_ops.real_div(t1, t2); | |||
| } | |||
| } | |||
| } | |||
| @@ -19,7 +19,7 @@ namespace Tensorflow | |||
| public Operation op { get; } | |||
| public string name; | |||
| public object value; | |||
| public int value_index { get; } | |||
| private Status status = new Status(); | |||
| @@ -90,7 +90,6 @@ namespace Tensorflow | |||
| public Tensor(NDArray nd) | |||
| { | |||
| _handle = Allocate(nd); | |||
| value = nd.Data(); | |||
| } | |||
| private IntPtr Allocate(NDArray nd) | |||
| @@ -205,30 +204,24 @@ namespace Tensorflow | |||
| } | |||
| } | |||
| public void Dispose() | |||
| { | |||
| c_api.TF_DeleteTensor(_handle); | |||
| status.Dispose(); | |||
| } | |||
| public static implicit operator Tensor(int scalar) | |||
| { | |||
| return new Tensor(scalar); | |||
| } | |||
| public static implicit operator IntPtr(Tensor tensor) | |||
| public override string ToString() | |||
| { | |||
| return tensor._handle; | |||
| } | |||
| if(NDims == 0) | |||
| { | |||
| switch (dtype) | |||
| { | |||
| case TF_DataType.TF_INT32: | |||
| return Data<int>()[0].ToString(); | |||
| } | |||
| } | |||
| public static implicit operator Tensor(IntPtr handle) | |||
| { | |||
| return new Tensor(handle); | |||
| return ""; | |||
| } | |||
| public static implicit operator Tensor(RefVariable var) | |||
| public void Dispose() | |||
| { | |||
| return var._initial_value; | |||
| c_api.TF_DeleteTensor(_handle); | |||
| status.Dispose(); | |||
| } | |||
| } | |||
| } | |||
| @@ -19,7 +19,7 @@ namespace Tensorflow | |||
| /// <param name="name">Optional name for the tensor.</param> | |||
| /// <param name="verify_shape">Boolean that enables verification of a shape of values.</param> | |||
| /// <returns></returns> | |||
| public static Tensor Create(NDArray nd, string name = "Const", bool verify_shape = false) | |||
| public static Tensor Constant(NDArray nd, string name = "Const", bool verify_shape = false) | |||
| { | |||
| Graph g = ops.get_default_graph(); | |||
| var tensor_pb = tensor_util.make_tensor_proto(nd, verify_shape); | |||
| @@ -44,10 +44,7 @@ namespace Tensorflow | |||
| attrs: attrs, | |||
| name: name); | |||
| var const_tensor = op.outputs[0]; | |||
| const_tensor.value = nd.Data(); | |||
| return const_tensor; | |||
| return op.outputs[0]; | |||
| } | |||
| } | |||
| } | |||
| @@ -88,7 +88,7 @@ namespace TensorFlowNET.Examples | |||
| { | |||
| var result = sess.run(product); | |||
| Console.WriteLine(result); | |||
| if((result as NDArray).Data<int>()[0] != 12) | |||
| if(result.Data<int>()[0] != 12) | |||
| { | |||
| throw new Exception("BasicOperations error"); | |||
| } | |||
| @@ -26,6 +26,10 @@ namespace TensorFlowNET.Examples | |||
| // Run the op | |||
| var result = sess.run(hello); | |||
| Console.WriteLine(result); | |||
| if(!result.ToString().Equals("Hello, TensorFlow!")) | |||
| { | |||
| throw new Exception("HelloWorld error"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -40,8 +40,14 @@ namespace TensorFlowNET.Examples | |||
| var pred = tf.add(part1, b); | |||
| // Mean squared error | |||
| var pow = tf.pow(pred - Y, 2); | |||
| //var cost = tf.reduce_sum(pow) / (2 * n_samples); | |||
| var sub = pred - Y; | |||
| var pow = tf.pow(sub, 2); | |||
| var reduce = tf.reduce_sum(pow); | |||
| var cost = reduce / (2d * n_samples); | |||
| // radient descent | |||
| // Note, minimize() knows to modify W and b because Variable objects are trainable=True by default | |||
| // var optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost); | |||
| } | |||
| } | |||
| } | |||
| @@ -11,6 +11,7 @@ | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj" /> | |||
| <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||
| </ItemGroup> | |||
| @@ -24,6 +24,7 @@ | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj" /> | |||
| <ProjectReference Include="..\..\src\TensorFlowNET.Core\TensorFlowNET.Core.csproj" /> | |||
| </ItemGroup> | |||