diff --git a/src/TensorFlowHub/TensorFlowHub.csproj b/src/TensorFlowHub/TensorFlowHub.csproj
index cf72c898..ae79533a 100644
--- a/src/TensorFlowHub/TensorFlowHub.csproj
+++ b/src/TensorFlowHub/TensorFlowHub.csproj
@@ -2,7 +2,7 @@
Tensorflow.Hub
netstandard2.0
- 0.0.1
+ 0.0.2
Kerry Jiang
SciSharp STACK
Apache 2.0
@@ -13,7 +13,7 @@
TensorFlow Hub is a library to foster the publication, discovery, and consumption of reusable parts of machine learning models.
SciSharp.TensorFlowHub
true
- 1. Add MNIST loader.
+
https://avatars3.githubusercontent.com/u/44989469?s=200&v=4
diff --git a/src/TensorFlowHub/Utils.cs b/src/TensorFlowHub/Utils.cs
index 72ee9430..699e911a 100644
--- a/src/TensorFlowHub/Utils.cs
+++ b/src/TensorFlowHub/Utils.cs
@@ -28,20 +28,13 @@ namespace Tensorflow.Hub
var fileSaveTo = Path.Combine(dirSaveTo, fileName);
if (File.Exists(fileSaveTo))
+ return;
+
+ Directory.CreateDirectory(dirSaveTo);
+
+ using (var wc = new WebClient())
{
- //TODO:maybe you can check file's hashcode and "donglowad.info" to complete file ...
- Console.WriteLine($"{fileSaveTo} already exists.");
- }
- else
- {
- if (!Directory.Exists(dirSaveTo))
- Directory.CreateDirectory(dirSaveTo);
-
- using (var wc = new WebClient())
- {
- await wc.DownloadFileTaskAsync(url, fileSaveTo);
- }
-
+ await wc.DownloadFileTaskAsync(url, fileSaveTo);
}
}
@@ -52,8 +45,7 @@ namespace Tensorflow.Hub
if (!Path.IsPathRooted(saveTo))
saveTo = Path.Combine(AppContext.BaseDirectory, saveTo);
- if (!Directory.Exists(saveTo))
- Directory.CreateDirectory(saveTo);
+ Directory.CreateDirectory(saveTo);
if (!Path.IsPathRooted(zipFile))
zipFile = Path.Combine(AppContext.BaseDirectory, zipFile);
diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs
index fb65d31b..b787bf1d 100644
--- a/src/TensorFlowNET.Core/APIs/tf.math.cs
+++ b/src/TensorFlowNET.Core/APIs/tf.math.cs
@@ -192,6 +192,9 @@ namespace Tensorflow
public static Tensor logical_and(Tensor x, Tensor y, string name = null)
=> gen_math_ops.logical_and(x, y, name);
+ public static Tensor logical_not(Tensor x, string name = null)
+ => gen_math_ops.logical_not(x, name);
+
///
/// Clips tensor values to a specified min and max.
///
diff --git a/src/TensorFlowNET.Core/Graphs/DefaultGraphStack.cs b/src/TensorFlowNET.Core/Graphs/DefaultGraphStack.cs
index 9e6f6346..f066676d 100644
--- a/src/TensorFlowNET.Core/Graphs/DefaultGraphStack.cs
+++ b/src/TensorFlowNET.Core/Graphs/DefaultGraphStack.cs
@@ -34,10 +34,17 @@ namespace Tensorflow
public Graph get_controller()
{
- if (stack.Count == 0)
+ if (stack.Count(x => x.IsDefault) == 0)
stack.Add(new StackModel { Graph = tf.Graph(), IsDefault = true });
- return stack.First(x => x.IsDefault).Graph;
+ return stack.Last(x => x.IsDefault).Graph;
+ }
+
+ public bool remove(Graph g)
+ {
+ var sm = stack.FirstOrDefault(x => x.Graph == g);
+ if (sm == null) return false;
+ return stack.Remove(sm);
}
public void reset()
diff --git a/src/TensorFlowNET.Core/Graphs/Graph.cs b/src/TensorFlowNET.Core/Graphs/Graph.cs
index 7121e0be..2949b5d4 100644
--- a/src/TensorFlowNET.Core/Graphs/Graph.cs
+++ b/src/TensorFlowNET.Core/Graphs/Graph.cs
@@ -73,9 +73,8 @@ namespace Tensorflow
all variables that are created during the construction of a graph. The caller
may define additional collections by specifying a new name.
*/
- public partial class Graph : IPython, IDisposable, IEnumerable
+ public partial class Graph : DisposableObject, IEnumerable
{
- private IntPtr _handle;
private Dictionary _nodes_by_id;
public Dictionary _nodes_by_name;
private Dictionary _names_in_use;
@@ -121,10 +120,6 @@ namespace Tensorflow
_graph_key = $"grap-key-{ops.uid()}/";
}
- public void __enter__()
- {
- }
-
public ITensorOrOperation as_graph_element(object obj, bool allow_tensor = true, bool allow_operation = true)
{
return _as_graph_element_locked(obj, allow_tensor, allow_operation);
@@ -443,14 +438,15 @@ namespace Tensorflow
_unfetchable_ops.Add(op);
}
- public void Dispose()
- {
- /*if (_handle != IntPtr.Zero)
- c_api.TF_DeleteGraph(_handle);
-
- _handle = IntPtr.Zero;
-
- GC.SuppressFinalize(this);*/
+ protected override void DisposeManagedState()
+ {
+ ops.default_graph_stack.remove(this);
+ }
+
+ protected override void DisposeUnManagedState(IntPtr handle)
+ {
+ Console.WriteLine($"Destroy graph {handle}");
+ c_api.TF_DeleteGraph(handle);
}
///
@@ -481,17 +477,19 @@ namespace Tensorflow
return new TensorShape(dims.Select(x => (int)x).ToArray());
}
+ string debugString = string.Empty;
public override string ToString()
{
- int len = 0;
- return c_api.TF_GraphDebugString(_handle, out len);
+ return $"{graph_key}, ({_handle})";
+ /*if (string.IsNullOrEmpty(debugString))
+ {
+ int len = 0;
+ debugString = c_api.TF_GraphDebugString(_handle, out len);
+ }
+
+ return debugString;*/
}
- public void __exit__()
- {
-
- }
-
private IEnumerable GetEnumerable()
=> c_api_util.tf_operations(this);
diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs
index d7590b97..059290f4 100644
--- a/src/TensorFlowNET.Core/Operations/Operation.cs
+++ b/src/TensorFlowNET.Core/Operations/Operation.cs
@@ -84,7 +84,7 @@ namespace Tensorflow
// Dict mapping op name to file and line information for op colocation
// context managers.
- _control_flow_context = graph._get_control_flow_context();
+ _control_flow_context = _graph._get_control_flow_context();
// Note: _control_flow_post_processing() must not be called here, the caller is responsible for calling it when using this constructor.
}
diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
index a8b9ac49..c3b30d8f 100644
--- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
@@ -357,6 +357,13 @@ namespace Tensorflow
return _op.outputs[0];
}
+ public static Tensor logical_not(Tensor x, string name = null)
+ {
+ var _op = _op_def_lib._apply_op_helper("LogicalNot", name, args: new { x });
+
+ 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, name });
diff --git a/src/TensorFlowNET.Core/Sessions/BaseSession.cs b/src/TensorFlowNET.Core/Sessions/BaseSession.cs
index e92e90f3..46daf2ec 100644
--- a/src/TensorFlowNET.Core/Sessions/BaseSession.cs
+++ b/src/TensorFlowNET.Core/Sessions/BaseSession.cs
@@ -31,7 +31,6 @@ namespace Tensorflow
protected bool _closed;
protected int _current_version;
protected byte[] _target;
- protected IntPtr _session;
public Graph graph => _graph;
public BaseSession(string target = "", Graph g = null, SessionOptions opts = null)
@@ -46,7 +45,7 @@ namespace Tensorflow
var status = new Status();
- _session = c_api.TF_NewSession(_graph, opts ?? newOpts, status);
+ _handle = c_api.TF_NewSession(_graph, opts ?? newOpts, status);
// dispose newOpts
if (opts == null)
@@ -216,7 +215,7 @@ namespace Tensorflow
var output_values = fetch_list.Select(x => IntPtr.Zero).ToArray();
- c_api.TF_SessionRun(_session,
+ c_api.TF_SessionRun(_handle,
run_options: null,
inputs: feed_dict.Select(f => f.Key).ToArray(),
input_values: feed_dict.Select(f => (IntPtr)f.Value).ToArray(),
diff --git a/src/TensorFlowNET.Core/Sessions/Session.cs b/src/TensorFlowNET.Core/Sessions/Session.cs
index 36797ec7..6b238ae7 100644
--- a/src/TensorFlowNET.Core/Sessions/Session.cs
+++ b/src/TensorFlowNET.Core/Sessions/Session.cs
@@ -30,7 +30,7 @@ namespace Tensorflow
public Session(IntPtr handle, Graph g = null)
: base("", g, null)
{
- _session = handle;
+ _handle = handle;
}
public Session(Graph g, SessionOptions opts = null, Status s = null)
@@ -73,7 +73,7 @@ namespace Tensorflow
return new Session(sess, g: new Graph(graph).as_default());
}
- public static implicit operator IntPtr(Session session) => session._session;
+ public static implicit operator IntPtr(Session session) => session._handle;
public static implicit operator Session(IntPtr handle) => new Session(handle);
public void __enter__()
diff --git a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj
index af74b38d..33e5f928 100644
--- a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj
+++ b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj
@@ -37,7 +37,7 @@ Docs: https://tensorflownet.readthedocs.io
15. Fix Tensor memory leak.
16. Rename with to tf_with that is only used to build graph purpose.
7.3
- 0.10.9.0
+ 0.10.10.0
LICENSE
true
true
diff --git a/test/TensorFlowNET.Examples/ImageProcessing/RetrainImageClassifier.cs b/test/TensorFlowNET.Examples/ImageProcessing/RetrainImageClassifier.cs
index 60329304..90660778 100644
--- a/test/TensorFlowNET.Examples/ImageProcessing/RetrainImageClassifier.cs
+++ b/test/TensorFlowNET.Examples/ImageProcessing/RetrainImageClassifier.cs
@@ -52,7 +52,8 @@ namespace TensorFlowNET.Examples
// The location where variable checkpoints will be stored.
string CHECKPOINT_NAME = Path.Join(data_dir, "_retrain_checkpoint");
string tfhub_module = "https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3";
- string final_tensor_name = "final_result";
+ string input_tensor_name = "Placeholder";
+ string final_tensor_name = "Score";
float testing_percentage = 0.1f;
float validation_percentage = 0.1f;
float learning_rate = 0.01f;
@@ -81,13 +82,13 @@ namespace TensorFlowNET.Examples
PrepareData();
#region For debug purpose
-
+
// predict images
// Predict(null);
// load saved pb and test new images.
// Test(null);
-
+
#endregion
var graph = IsImportingGraph ? ImportGraph() : BuildGraph();
@@ -276,16 +277,13 @@ namespace TensorFlowNET.Examples
private (Graph, Tensor, Tensor, bool) create_module_graph()
{
var (height, width) = (299, 299);
-
- return tf_with(tf.Graph().as_default(), graph =>
- {
- tf.train.import_meta_graph("graph/InceptionV3.meta");
- Tensor resized_input_tensor = graph.OperationByName("Placeholder"); //tf.placeholder(tf.float32, new TensorShape(-1, height, width, 3));
- // var m = hub.Module(module_spec);
- Tensor bottleneck_tensor = graph.OperationByName("module_apply_default/hub_output/feature_vector/SpatialSqueeze");// m(resized_input_tensor);
- var wants_quantization = false;
- return (graph, bottleneck_tensor, resized_input_tensor, wants_quantization);
- });
+ var graph = tf.Graph().as_default();
+ tf.train.import_meta_graph("graph/InceptionV3.meta");
+ Tensor resized_input_tensor = graph.OperationByName(input_tensor_name); //tf.placeholder(tf.float32, new TensorShape(-1, height, width, 3));
+ // var m = hub.Module(module_spec);
+ Tensor bottleneck_tensor = graph.OperationByName("module_apply_default/hub_output/feature_vector/SpatialSqueeze");// m(resized_input_tensor);
+ var wants_quantization = false;
+ return (graph, bottleneck_tensor, resized_input_tensor, wants_quantization);
}
private (NDArray, long[], string[]) get_random_cached_bottlenecks(Session sess, Dictionary> image_lists,
@@ -594,13 +592,10 @@ namespace TensorFlowNET.Examples
create_module_graph();
// Add the new layer that we'll be training.
- tf_with(graph.as_default(), delegate
- {
- (train_step, cross_entropy, bottleneck_input,
- ground_truth_input, final_tensor) = add_final_retrain_ops(
- class_count, final_tensor_name, bottleneck_tensor,
- wants_quantization, is_training: true);
- });
+ (train_step, cross_entropy, bottleneck_input,
+ ground_truth_input, final_tensor) = add_final_retrain_ops(
+ class_count, final_tensor_name, bottleneck_tensor,
+ wants_quantization, is_training: true);
return graph;
}
@@ -734,15 +729,15 @@ namespace TensorFlowNET.Examples
var labels = File.ReadAllLines(output_labels);
// predict image
- var img_path = Path.Join(image_dir, "roses", "12240303_80d87f77a3_n.jpg");
+ var img_path = Path.Join(image_dir, "daisy", "5547758_eea9edfd54_n.jpg");
var fileBytes = ReadTensorFromImageFile(img_path);
// import graph and variables
var graph = new Graph();
graph.Import(output_graph, "");
- Tensor input = graph.OperationByName("Placeholder");
- Tensor output = graph.OperationByName("final_result");
+ Tensor input = graph.OperationByName(input_tensor_name);
+ Tensor output = graph.OperationByName(final_tensor_name);
using (var sess = tf.Session(graph))
{
diff --git a/test/TensorFlowNET.UnitTest/NameScopeTest.cs b/test/TensorFlowNET.UnitTest/NameScopeTest.cs
index 39401fe0..9a2b4346 100644
--- a/test/TensorFlowNET.UnitTest/NameScopeTest.cs
+++ b/test/TensorFlowNET.UnitTest/NameScopeTest.cs
@@ -7,12 +7,13 @@ namespace TensorFlowNET.UnitTest
[TestClass]
public class NameScopeTest
{
- Graph g = ops.get_default_graph();
string name = "";
[TestMethod]
public void NestedNameScope()
{
+ Graph g = tf.Graph().as_default();
+
tf_with(new ops.NameScope("scope1"), scope1 =>
{
name = scope1;
@@ -37,6 +38,8 @@ namespace TensorFlowNET.UnitTest
Assert.AreEqual("scope1/Const_1:0", const3.name);
});
+ g.Dispose();
+
Assert.AreEqual("", g._name_stack);
}
}
diff --git a/test/TensorFlowNET.UnitTest/OperationsTest.cs b/test/TensorFlowNET.UnitTest/OperationsTest.cs
index 10046f0c..68c44831 100644
--- a/test/TensorFlowNET.UnitTest/OperationsTest.cs
+++ b/test/TensorFlowNET.UnitTest/OperationsTest.cs
@@ -131,7 +131,7 @@ namespace TensorFlowNET.UnitTest
}
[TestMethod]
- public void logicalAndTest()
+ public void logicalOpsTest()
{
var a = tf.constant(new[] {1f, 2f, 3f, 4f, -4f, -3f, -2f, -1f});
var b = tf.less(a, 0f);
@@ -144,6 +144,15 @@ namespace TensorFlowNET.UnitTest
var o = sess.run(d);
Assert.IsTrue(o.array_equal(check));
}
+
+ d = tf.cast(tf.logical_not(b), tf.int32);
+ check = np.array(new[] { 1, 1, 1, 1, 0, 0, 0, 0 });
+
+ using (var sess = tf.Session())
+ {
+ var o = sess.run(d);
+ Assert.IsTrue(o.array_equal(check));
+ }
}
[TestMethod]