| @@ -66,7 +66,7 @@ using(var sess = tf.Session()) | |||||
| Read the docs & book [The Definitive Guide to Tensorflow.NET](https://tensorflownet.readthedocs.io/en/latest/FrontCover.html). | Read the docs & book [The Definitive Guide to Tensorflow.NET](https://tensorflownet.readthedocs.io/en/latest/FrontCover.html). | ||||
| More examples: | |||||
| ### More examples: | |||||
| * [Hello World](test/TensorFlowNET.Examples/HelloWorld.cs) | * [Hello World](test/TensorFlowNET.Examples/HelloWorld.cs) | ||||
| * [Basic Operations](test/TensorFlowNET.Examples/BasicOperations.cs) | * [Basic Operations](test/TensorFlowNET.Examples/BasicOperations.cs) | ||||
| @@ -7,7 +7,7 @@ namespace Tensorflow | |||||
| public static partial class tf | public static partial class tf | ||||
| { | { | ||||
| public static IInitializer zeros_initializer => new Zeros(); | public static IInitializer zeros_initializer => new Zeros(); | ||||
| public static IInitializer glorot_uniform => new GlorotUniform(); | |||||
| public static IInitializer glorot_uniform_initializer => new GlorotUniform(); | |||||
| public static variable_scope variable_scope(string name_or_scope, | public static variable_scope variable_scope(string name_or_scope, | ||||
| string default_name = null, | string default_name = null, | ||||
| @@ -24,10 +24,34 @@ namespace Tensorflow | |||||
| if (!seed2.HasValue) | if (!seed2.HasValue) | ||||
| seed2 = 0; | seed2 = 0; | ||||
| var _op = _op_def_lib._apply_op_helper("RandomStandardNormal", name: name, | |||||
| var _op = _op_def_lib._apply_op_helper("RandomStandardNormal", | |||||
| name: name, | |||||
| args: new { shape, dtype, seed, seed2 }); | args: new { shape, dtype, seed, seed2 }); | ||||
| return _op.outputs[0]; | return _op.outputs[0]; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Outputs random values from a uniform distribution. | |||||
| /// </summary> | |||||
| /// <param name="shape"></param> | |||||
| /// <param name="dtype"></param> | |||||
| /// <param name="seed"></param> | |||||
| /// <param name="seed2"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor random_uniform(Tensor shape, TF_DataType dtype, int? seed = 0, int? seed2 = 0, string name = null) | |||||
| { | |||||
| if (!seed.HasValue) | |||||
| seed = 0; | |||||
| if (!seed2.HasValue) | |||||
| seed2 = 0; | |||||
| var _op = _op_def_lib._apply_op_helper("RandomUniform", | |||||
| name: name, | |||||
| args: new { shape, dtype, seed, seed2}); | |||||
| return _op.outputs[0]; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -56,7 +56,11 @@ namespace Tensorflow | |||||
| return with<ops.name_scope, Tensor>(new ops.name_scope(name, "random_uniform", new { shape, minval, maxval }), scope => | return with<ops.name_scope, Tensor>(new ops.name_scope(name, "random_uniform", new { shape, minval, maxval }), scope => | ||||
| { | { | ||||
| name = scope; | name = scope; | ||||
| return null; | |||||
| var tensorShape = _ShapeTensor(shape); | |||||
| var minTensor = ops.convert_to_tensor(minval, dtype: dtype, name: "min"); | |||||
| var maxTensor = ops.convert_to_tensor(maxval, dtype: dtype, name: "max"); | |||||
| var rnd = gen_random_ops.random_uniform(tensorShape, dtype); | |||||
| return math_ops.add(rnd * (maxTensor - minTensor), minTensor, name: name); | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -77,6 +77,11 @@ namespace Tensorflow | |||||
| return null; | return null; | ||||
| } | } | ||||
| public TensorShape getShape() | |||||
| { | |||||
| return tensor_util.to_shape(shape); | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// number of dimensions | /// number of dimensions | ||||
| /// 0 Scalar (magnitude only) | /// 0 Scalar (magnitude only) | ||||
| @@ -1,4 +1,6 @@ | |||||
| using System; | |||||
| using Google.Protobuf; | |||||
| using Google.Protobuf.Collections; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Text; | using System.Text; | ||||
| @@ -99,7 +101,7 @@ namespace Tensorflow | |||||
| if (initial_value is null) | if (initial_value is null) | ||||
| throw new ValueError("initial_value must be specified."); | throw new ValueError("initial_value must be specified."); | ||||
| var init_from_fn = false; | |||||
| var init_from_fn = initial_value.GetType().Name == "Func`1"; | |||||
| if(collections == null) | if(collections == null) | ||||
| { | { | ||||
| @@ -115,12 +117,27 @@ namespace Tensorflow | |||||
| collections.Add(ops.GraphKeys.TRAINABLE_VARIABLES); | collections.Add(ops.GraphKeys.TRAINABLE_VARIABLES); | ||||
| ops.init_scope(); | ops.init_scope(); | ||||
| var values = init_from_fn ? new List<object>() : new List<object> { initial_value }; | |||||
| Python.with<ops.name_scope>(new ops.name_scope(name, "Variable", values), scope => | |||||
| var values = init_from_fn ? new object[0] : new object[] { initial_value }; | |||||
| with<ops.name_scope>(new ops.name_scope(name, "Variable", values), scope => | |||||
| { | { | ||||
| name = scope; | |||||
| if (init_from_fn) | if (init_from_fn) | ||||
| { | { | ||||
| // Use attr_scope and device(None) to simulate the behavior of | |||||
| // colocate_with when the variable we want to colocate with doesn't | |||||
| // yet exist. | |||||
| string true_name = ops._name_from_scope_name(name); | |||||
| var attr = new AttrValue | |||||
| { | |||||
| List = new AttrValue.Types.ListValue() | |||||
| }; | |||||
| attr.List.S.Add(ByteString.CopyFromUtf8($"loc:{true_name}")); | |||||
| with<ops.name_scope>(new ops.name_scope("Initializer"), scope2 => | |||||
| { | |||||
| _initial_value = (initial_value as Func<Tensor>)(); | |||||
| _initial_value = ops.convert_to_tensor(_initial_value, name: "initial_value", dtype: dtype); | |||||
| _variable = state_ops.variable_op_v2(_initial_value.shape, _initial_value.dtype.as_base_dtype(), name: name); | |||||
| }); | |||||
| } | } | ||||
| // Or get the initial value from a Tensor or Python object. | // Or get the initial value from a Tensor or Python object. | ||||
| else | else | ||||
| @@ -135,7 +152,9 @@ namespace Tensorflow | |||||
| // Manually overrides the variable's shape with the initial value's. | // Manually overrides the variable's shape with the initial value's. | ||||
| if (validate_shape) | if (validate_shape) | ||||
| { | { | ||||
| var initial_value_shape = _initial_value.shape; | |||||
| var initial_value_shape = _initial_value.getShape(); | |||||
| if (!initial_value_shape.is_fully_defined()) | |||||
| throw new ValueError($"initial_value must have a shape specified: {_initial_value}"); | |||||
| } | } | ||||
| // If 'initial_value' makes use of other variables, make sure we don't | // If 'initial_value' makes use of other variables, make sure we don't | ||||
| @@ -74,7 +74,9 @@ namespace Tensorflow | |||||
| VariableSynchronization synchronization = VariableSynchronization.AUTO, | VariableSynchronization synchronization = VariableSynchronization.AUTO, | ||||
| VariableAggregation aggregation = VariableAggregation.NONE) | VariableAggregation aggregation = VariableAggregation.NONE) | ||||
| { | { | ||||
| bool initializing_from_value = false; | |||||
| bool initializing_from_value = true; | |||||
| if (use_resource == null) | |||||
| use_resource = false; | |||||
| if (_vars.ContainsKey(name)) | if (_vars.ContainsKey(name)) | ||||
| { | { | ||||
| @@ -86,15 +88,18 @@ namespace Tensorflow | |||||
| throw new NotImplementedException("_get_single_variable"); | throw new NotImplementedException("_get_single_variable"); | ||||
| } | } | ||||
| Tensor init_val = null; | |||||
| RefVariable v = null; | |||||
| // Create the tensor to initialize the variable with default value. | // Create the tensor to initialize the variable with default value. | ||||
| if (initializer == null) | if (initializer == null) | ||||
| { | { | ||||
| if (dtype.is_floating()) | if (dtype.is_floating()) | ||||
| initializer = tf.glorot_uniform; | |||||
| { | |||||
| initializer = tf.glorot_uniform_initializer; | |||||
| initializing_from_value = false; | |||||
| } | |||||
| } | } | ||||
| // Create the variable. | |||||
| ops.init_scope(); | ops.init_scope(); | ||||
| { | { | ||||
| if (initializing_from_value) | if (initializing_from_value) | ||||
| @@ -103,23 +108,19 @@ namespace Tensorflow | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| init_val = initializer.call(shape, dtype); | |||||
| Func<Tensor> init_val = () => initializer.call(shape, dtype); | |||||
| var variable_dtype = dtype.as_base_dtype(); | var variable_dtype = dtype.as_base_dtype(); | ||||
| v = variable_scope.default_variable_creator(init_val, | |||||
| name: name, | |||||
| trainable: trainable, | |||||
| dtype: TF_DataType.DtInvalid, | |||||
| validate_shape: validate_shape, | |||||
| synchronization: synchronization, | |||||
| aggregation: aggregation); | |||||
| } | } | ||||
| } | } | ||||
| // Create the variable. | |||||
| if (use_resource == null) | |||||
| use_resource = false; | |||||
| var v = variable_scope.default_variable_creator(init_val, | |||||
| name: name, | |||||
| trainable: trainable, | |||||
| dtype: TF_DataType.DtInvalid, | |||||
| validate_shape: validate_shape, | |||||
| synchronization: synchronization, | |||||
| aggregation: aggregation); | |||||
| _vars[name] = v; | _vars[name] = v; | ||||
| return v; | return v; | ||||
| @@ -0,0 +1,28 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class state_ops | |||||
| { | |||||
| /// <summary> | |||||
| /// Create a variable Operation. | |||||
| /// </summary> | |||||
| /// <param name="shape"></param> | |||||
| /// <param name="dtype"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="container"></param> | |||||
| /// <param name="shared_name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor variable_op_v2(long[] shape, | |||||
| TF_DataType dtype, | |||||
| string name = "Variable", | |||||
| string container = "", | |||||
| string shared_name = "") => gen_state_ops.variable_v2(shape, | |||||
| dtype, | |||||
| name: name, | |||||
| container: container, | |||||
| shared_name: shared_name); | |||||
| } | |||||
| } | |||||
| @@ -16,7 +16,7 @@ namespace TensorFlowNET.Examples | |||||
| // Parameters | // Parameters | ||||
| float learning_rate = 0.01f; | float learning_rate = 0.01f; | ||||
| int training_epochs = 10000; | |||||
| int training_epochs = 1000; | |||||
| int display_step = 50; | int display_step = 50; | ||||
| public void Run() | public void Run() | ||||
| @@ -30,14 +30,18 @@ namespace TensorFlowNET.UnitTest | |||||
| var mammal2 = tf.Variable("Tiger"); | var mammal2 = tf.Variable("Tiger"); | ||||
| } | } | ||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/api_docs/python/tf/variable_scope | |||||
| /// </summary> | |||||
| [TestMethod] | [TestMethod] | ||||
| public void SimpleScope() | |||||
| public void VarCreation1() | |||||
| { | { | ||||
| with(tf.variable_scope("foo"), delegate | with(tf.variable_scope("foo"), delegate | ||||
| { | { | ||||
| with(tf.variable_scope("bar"), delegate | with(tf.variable_scope("bar"), delegate | ||||
| { | { | ||||
| var v = tf.get_variable("v", new TensorShape(1)); | var v = tf.get_variable("v", new TensorShape(1)); | ||||
| Assert.AreEqual(v.name, "foo/bar/v:0"); | |||||
| }); | }); | ||||
| }); | }); | ||||
| } | } | ||||