@@ -47,4 +47,14 @@ var tensor = tf.constant(nd); | |||||
Now let's explore how constant works. | Now let's explore how constant works. | ||||
现在让我探究一下`tf.constant`是怎么工作的。 | |||||
现在让我探究一下`tf.constant`是怎么工作的。 | |||||
##### Other functions to create a Constant | |||||
* tf.zeros | |||||
* tf.zeros_like | |||||
* tf.ones | |||||
* tf.ones_like | |||||
* tf.fill |
@@ -36,13 +36,13 @@ namespace Tensorflow | |||||
{ | { | ||||
Tensor rank; | Tensor rank; | ||||
string name; | string name; | ||||
using (var namescop = new ops.name_scope<Tensor>("", "Rank", new List<Tensor> { input })) | |||||
using (var namescop = new ops.name_scope("", "Rank", new List<Tensor> { input })) | |||||
{ | { | ||||
name = namescop; | name = namescop; | ||||
rank = gen_array_ops.rank(input, namescop); | rank = gen_array_ops.rank(input, namescop); | ||||
} | } | ||||
using (var namescope = new ops.name_scope<Tensor>("range", "Range", new List<Tensor> { 0D, input, 1D })) | |||||
using (var namescope = new ops.name_scope("range", "Range", new List<Tensor> { 0D, input, 1D })) | |||||
{ | { | ||||
name = namescope; | name = namescope; | ||||
var start = ops.convert_to_tensor(0D); | var start = ops.convert_to_tensor(0D); | ||||
@@ -50,7 +50,7 @@ namespace Tensorflow | |||||
all.AddRange(grad_ys1); | all.AddRange(grad_ys1); | ||||
string grad_scope = ""; | string grad_scope = ""; | ||||
using (var namescope = new ops.name_scope<Tensor>(name, "gradients", values: all)) | |||||
using (var namescope = new ops.name_scope(name, "gradients", values: all)) | |||||
{ | { | ||||
grad_scope = namescope; | grad_scope = namescope; | ||||
// Get a uid for this call to gradients that can be used to help | // Get a uid for this call to gradients that can be used to help | ||||
@@ -41,7 +41,7 @@ namespace Tensorflow | |||||
var input_types = new List<TF_DataType>(); | var input_types = new List<TF_DataType>(); | ||||
string scope = ""; | string scope = ""; | ||||
using (var namescope = new ops.name_scope<object>(name)) | |||||
using (var namescope = new ops.name_scope(name)) | |||||
{ | { | ||||
scope = namescope; | scope = namescope; | ||||
@@ -0,0 +1,56 @@ | |||||
using NumSharp.Core; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace Tensorflow | |||||
{ | |||||
public class array_ops | |||||
{ | |||||
public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = "") | |||||
{ | |||||
Tensor output = null; | |||||
dtype = dtype.as_base_dtype(); | |||||
Python.with(new ops.name_scope(name, "zeros", shape), self => | |||||
{ | |||||
name = self as ops.name_scope; | |||||
switch (dtype) | |||||
{ | |||||
case TF_DataType.TF_BOOL: | |||||
output = _constant_if_small(false, shape, dtype, name); | |||||
break; | |||||
case TF_DataType.TF_DOUBLE: | |||||
output = _constant_if_small(0.0D, shape, dtype, name); | |||||
break; | |||||
case TF_DataType.TF_FLOAT: | |||||
output = _constant_if_small(0.0F, shape, dtype, name); | |||||
break; | |||||
case TF_DataType.TF_INT32: | |||||
output = _constant_if_small(0, shape, dtype, name); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}); | |||||
return output; | |||||
} | |||||
private static Tensor _constant_if_small<T>(T value, Shape shape, TF_DataType dtype, string name) | |||||
{ | |||||
Tensor tShape = null; | |||||
var nd = np.zeros<T>(shape); | |||||
if (shape.Size < 1000) | |||||
{ | |||||
return constant_op.Constant(nd, name); | |||||
} | |||||
else | |||||
{ | |||||
tShape = constant_op._tensor_shape_tensor_conversion_function(shape.as_shape(), dtype, name); | |||||
var c = constant_op.Constant(nd, name); | |||||
return gen_array_ops.fill<T>(shape, value, name); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -9,7 +9,7 @@ namespace Tensorflow | |||||
{ | { | ||||
public static Operation group(List<Operation> inputs, string name = "") | public static Operation group(List<Operation> inputs, string name = "") | ||||
{ | { | ||||
using(var namescope = new ops.name_scope<Operation>(name, "group_deps", inputs)) | |||||
using(var namescope = new ops.name_scope(name, "group_deps", inputs)) | |||||
{ | { | ||||
name = namescope; | name = namescope; | ||||
@@ -55,5 +55,24 @@ namespace Tensorflow | |||||
return _op.outputs[0]; | return _op.outputs[0]; | ||||
} | } | ||||
/// <summary> | |||||
/// Creates a tensor filled with a scalar value. | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="dims"></param> | |||||
/// <param name="value"></param> | |||||
/// <param name="name"></param> | |||||
/// <returns></returns> | |||||
public static Tensor fill<T>(int[] dims, T value, string name = "") | |||||
{ | |||||
var keywords = new Dictionary<string, object>(); | |||||
keywords.Add("dims", dims); | |||||
keywords.Add("value", value); | |||||
var _op = _op_def_lib._apply_op_helper("Fill", name); | |||||
return _op.outputs[0]; | |||||
} | |||||
} | } | ||||
} | } |
@@ -14,12 +14,12 @@ namespace Tensorflow | |||||
Console.WriteLine(obj.ToString()); | Console.WriteLine(obj.ToString()); | ||||
} | } | ||||
public static void with(IPython py, Action action) | |||||
public static void with(IPython py, Action<IPython> action) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
py.__enter__(); | py.__enter__(); | ||||
action(); | |||||
action(py); | |||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
@@ -37,7 +37,7 @@ TensorFlow 1.13 RC.</PackageReleaseNotes> | |||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Google.Protobuf" Version="3.6.1" /> | <PackageReference Include="Google.Protobuf" Version="3.6.1" /> | ||||
<PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
<PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
@@ -46,5 +46,37 @@ namespace Tensorflow | |||||
return op.outputs[0]; | return op.outputs[0]; | ||||
} | } | ||||
/// <summary> | |||||
/// Function to convert TensorShape to Tensor. | |||||
/// </summary> | |||||
/// <param name="s"></param> | |||||
/// <param name="dtype"></param> | |||||
/// <param name="name"></param> | |||||
/// <param name="as_ref"></param> | |||||
/// <returns></returns> | |||||
public static Tensor _tensor_shape_tensor_conversion_function(TensorShape s, TF_DataType dtype = TF_DataType.DtInvalid, string name = "", bool as_ref = false) | |||||
{ | |||||
var s_list = s.Dimensions; | |||||
var int64_value = 0; | |||||
foreach(var dim in s_list) | |||||
{ | |||||
if (dim > Math.Pow(2, 31)) | |||||
{ | |||||
int64_value = dim; | |||||
break; | |||||
} | |||||
} | |||||
if(int64_value > 0) | |||||
{ | |||||
dtype = TF_DataType.TF_INT32; | |||||
} | |||||
if (string.IsNullOrEmpty(name)) | |||||
name = "shape_as_tensor"; | |||||
return constant_op.Constant(s_list, name); | |||||
} | |||||
} | } | ||||
} | } |
@@ -70,5 +70,12 @@ namespace Tensorflow | |||||
(TF_DataType)Enum.Parse(typeof(TF_DataType), ((int)type - 100).ToString()) : | (TF_DataType)Enum.Parse(typeof(TF_DataType), ((int)type - 100).ToString()) : | ||||
type; | type; | ||||
} | } | ||||
public static DataType as_base_dtype(this DataType type) | |||||
{ | |||||
return (int)type > 100 ? | |||||
(DataType)Enum.Parse(typeof(DataType), ((int)type - 100).ToString()) : | |||||
type; | |||||
} | |||||
} | } | ||||
} | } |
@@ -18,7 +18,7 @@ namespace Tensorflow | |||||
var tensor_proto = new tensor_pb2.TensorProto | var tensor_proto = new tensor_pb2.TensorProto | ||||
{ | { | ||||
Dtype = numpy_dtype.as_datatype_enum(), | Dtype = numpy_dtype.as_datatype_enum(), | ||||
TensorShape = shape.as_shape(nd.shape).as_proto() | |||||
TensorShape = shape.reshape(nd.shape).as_proto() | |||||
}; | }; | ||||
switch (nd.dtype.Name) | switch (nd.dtype.Name) | ||||
@@ -94,7 +94,12 @@ namespace Tensorflow | |||||
return new TensorShape(dims.Select(x => (int)x).ToArray()); | return new TensorShape(dims.Select(x => (int)x).ToArray()); | ||||
} | } | ||||
public static TensorShape as_shape(this IShape shape, int[] dims) | |||||
public static TensorShape as_shape(this IShape shape) | |||||
{ | |||||
return new TensorShape(shape.Dimensions); | |||||
} | |||||
public static TensorShape reshape(this IShape shape, int[] dims) | |||||
{ | { | ||||
return new TensorShape(dims); | return new TensorShape(dims); | ||||
} | } | ||||
@@ -11,5 +11,10 @@ namespace Tensorflow | |||||
{ | { | ||||
return constant_op.Constant(nd, name, verify_shape); | return constant_op.Constant(nd, name, verify_shape); | ||||
} | } | ||||
public static Tensor zeros(Shape shape, TF_DataType dtype = TF_DataType.TF_FLOAT, string name = "") | |||||
{ | |||||
return array_ops.zeros(shape, dtype, name); | |||||
} | |||||
} | } | ||||
} | } |
@@ -65,7 +65,7 @@ namespace Tensorflow | |||||
ops.init_scope(); | ops.init_scope(); | ||||
var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | ||||
using (var namescope = new ops.name_scope<object>(name, "Variable", values)) | |||||
using (var namescope = new ops.name_scope(name, "Variable", values)) | |||||
{ | { | ||||
name = namescope; | name = namescope; | ||||
@@ -7,7 +7,7 @@ namespace Tensorflow | |||||
{ | { | ||||
public partial class ops | public partial class ops | ||||
{ | { | ||||
public class name_scope<T> : IDisposable | |||||
public class name_scope : IPython | |||||
{ | { | ||||
public string _name; | public string _name; | ||||
public string _default_name; | public string _default_name; | ||||
@@ -16,7 +16,7 @@ namespace Tensorflow | |||||
public string _name_scope; | public string _name_scope; | ||||
private object _g_manager; | private object _g_manager; | ||||
public name_scope(string name, string default_name = "", List<T> values = null) | |||||
public name_scope(string name, string default_name = "", object values = null) | |||||
{ | { | ||||
_name = name; | _name = name; | ||||
_default_name = default_name; | _default_name = default_name; | ||||
@@ -24,7 +24,7 @@ namespace Tensorflow | |||||
// _ctx = new Context(); | // _ctx = new Context(); | ||||
} | } | ||||
public string __enter__() | |||||
public void __enter__() | |||||
{ | { | ||||
if (String.IsNullOrEmpty(_name)) | if (String.IsNullOrEmpty(_name)) | ||||
{ | { | ||||
@@ -39,8 +39,6 @@ namespace Tensorflow | |||||
g = get_default_graph(); | g = get_default_graph(); | ||||
_name_scope = g.name_scope(_name); | _name_scope = g.name_scope(_name); | ||||
return _name_scope; | |||||
} | } | ||||
public void Dispose() | public void Dispose() | ||||
@@ -51,16 +49,17 @@ namespace Tensorflow | |||||
g.old_stack = ""; | g.old_stack = ""; | ||||
} | } | ||||
public void __exit__() | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// __enter__() | /// __enter__() | ||||
/// </summary> | /// </summary> | ||||
/// <param name="ns"></param> | /// <param name="ns"></param> | ||||
public static implicit operator string(name_scope<T> ns) | |||||
public static implicit operator string(name_scope ns) | |||||
{ | { | ||||
if (string.IsNullOrEmpty(ns._name_scope)) | |||||
return ns.__enter__(); | |||||
else | |||||
return ns._name_scope; | |||||
return ns._name_scope; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -6,7 +6,7 @@ | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
<PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
<PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -2,6 +2,7 @@ | |||||
using NumSharp.Core; | using NumSharp.Core; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
using Tensorflow; | using Tensorflow; | ||||
@@ -26,6 +27,17 @@ namespace TensorFlowNET.UnitTest | |||||
tensor = tf.constant("Elephant"); | tensor = tf.constant("Elephant"); | ||||
} | } | ||||
[TestMethod] | |||||
public void ZerosConst() | |||||
{ | |||||
tensor = tf.zeros(new Shape(3, 2), TF_DataType.TF_INT32, "x"); | |||||
Assert.AreEqual(tensor.shape[0], 3); | |||||
Assert.AreEqual(tensor.shape[0], 2); | |||||
Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 0, 0, 0, 0, 0, 0 }, tensor.Data<int>())); | |||||
tensor = tf.zeros(new Shape(200, 300), TF_DataType.TF_INT32, "x"); | |||||
} | |||||
[TestMethod] | [TestMethod] | ||||
public void NDimConst() | public void NDimConst() | ||||
{ | { | ||||
@@ -19,7 +19,7 @@ | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | ||||
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> | <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> | ||||
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> | <PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> | ||||
<PackageReference Include="NumSharp" Version="0.6.6" /> | |||||
<PackageReference Include="NumSharp" Version="0.7.0" /> | |||||
<PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | <PackageReference Include="TensorFlow.NET" Version="0.1.0" /> | ||||
</ItemGroup> | </ItemGroup> | ||||