@@ -63,7 +63,7 @@ Import TF.NET and Keras API in your project. | |||||
using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
using static Tensorflow.KerasApi; | using static Tensorflow.KerasApi; | ||||
using Tensorflow; | using Tensorflow; | ||||
using NumSharp; | |||||
using Tensorflow.NumPy; | |||||
``` | ``` | ||||
Linear Regression in `Eager` mode: | Linear Regression in `Eager` mode: | ||||
@@ -162,10 +162,9 @@ Linear Regression in `Eager` mode: | |||||
#r "nuget: TensorFlow.Net" | #r "nuget: TensorFlow.Net" | ||||
#r "nuget: TensorFlow.Keras" | #r "nuget: TensorFlow.Keras" | ||||
#r "nuget: SciSharp.TensorFlow.Redist" | #r "nuget: SciSharp.TensorFlow.Redist" | ||||
#r "nuget: NumSharp" | |||||
open NumSharp | |||||
open Tensorflow | open Tensorflow | ||||
open Tensorflow.NumPy | |||||
open type Tensorflow.Binding | open type Tensorflow.Binding | ||||
open type Tensorflow.KerasApi | open type Tensorflow.KerasApi | ||||
@@ -203,13 +203,6 @@ namespace Tensorflow | |||||
yield return values[i]; | yield return values[i]; | ||||
} | } | ||||
public static T New<T>() where T : ITensorFlowObject, new() | |||||
{ | |||||
var instance = new T(); | |||||
instance.__init__(); | |||||
return instance; | |||||
} | |||||
[DebuggerStepThrough] | [DebuggerStepThrough] | ||||
public static void tf_with(ITensorFlowObject py, Action<ITensorFlowObject> action) | public static void tf_with(ITensorFlowObject py, Action<ITensorFlowObject> action) | ||||
{ | { | ||||
@@ -81,7 +81,7 @@ namespace Tensorflow.Eager | |||||
if (ops.gradientFunctions[op_name] == null) | if (ops.gradientFunctions[op_name] == null) | ||||
return new Tensor[op_inputs.Length]; | return new Tensor[op_inputs.Length]; | ||||
var gradients = ops.gradientFunctions[op_name](new EagerOperation | |||||
var op = new EagerOperation | |||||
{ | { | ||||
Name = op_name, | Name = op_name, | ||||
NumInputs = op_inputs.Length, | NumInputs = op_inputs.Length, | ||||
@@ -90,9 +90,9 @@ namespace Tensorflow.Eager | |||||
Outputs = op_outputs, | Outputs = op_outputs, | ||||
SkipInputIndices = unneeded_gradients, | SkipInputIndices = unneeded_gradients, | ||||
Attrs = attrs | Attrs = attrs | ||||
}, output_grads); | |||||
}; | |||||
return gradients; | |||||
return ops.gradientFunctions[op_name](op, output_grads); | |||||
}; | }; | ||||
bool CouldForwardprop() | bool CouldForwardprop() | ||||
@@ -20,15 +20,8 @@ namespace Tensorflow | |||||
{ | { | ||||
public interface ITensorFlowObject : IDisposable | public interface ITensorFlowObject : IDisposable | ||||
{ | { | ||||
/// <summary> | |||||
/// Called when the instance is created. | |||||
/// </summary> | |||||
void __init__(); | |||||
void __enter__(); | void __enter__(); | ||||
void __exit__(); | void __exit__(); | ||||
void __del__(); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,16 @@ | |||||
using static Tensorflow.Binding; | |||||
namespace Tensorflow.Keras.ArgsDefinition | |||||
{ | |||||
public class LayerNormalizationArgs : LayerArgs | |||||
{ | |||||
public Axis Axis { get; set; } = -1; | |||||
public float Epsilon { get; set; } = 1e-3f; | |||||
public bool Center { get; set; } = true; | |||||
public bool Scale { get; set; } = true; | |||||
public IInitializer BetaInitializer { get; set; } = tf.zeros_initializer; | |||||
public IInitializer GammaInitializer { get; set; } = tf.ones_initializer; | |||||
public IRegularizer BetaRegularizer { get; set; } | |||||
public IRegularizer GammaRegularizer { get; set; } | |||||
} | |||||
} |
@@ -89,8 +89,8 @@ tf.net 0.6x.x aligns with TensorFlow v2.6.x native library.</PackageReleaseNotes | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.139" /> | |||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" /> | |||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.144" /> | |||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> | |||||
<PackageReference Include="Protobuf.Text" Version="0.5.0" /> | <PackageReference Include="Protobuf.Text" Version="0.5.0" /> | ||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" /> | <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -316,7 +316,7 @@ namespace Tensorflow.Keras.Engine | |||||
var outputs = node.Layer.Apply(layer_inputs, is_training: training ?? false); | var outputs = node.Layer.Apply(layer_inputs, is_training: training ?? false); | ||||
foreach (var output in outputs.Where(x => x != null)) | foreach (var output in outputs.Where(x => x != null)) | ||||
tf.Logger.Information($"Depth {depth}: {node.Layer}: {node.Layer.Name} {output.shape}"); | tf.Logger.Information($"Depth {depth}: {node.Layer}: {node.Layer.Name} {output.shape}"); | ||||
// Update tensor_dict for next input | |||||
// Update tensor_dict for next or later input | |||||
foreach (var (x_id, y) in zip(node.Outputs.Select(x => x.Id), outputs)) | foreach (var (x_id, y) in zip(node.Outputs.Select(x => x.Id), outputs)) | ||||
tensor_dict[x_id] = new Queue<Tensor>(Enumerable.Range(0, tensor_usage_count[x_id]).Select(x => y)); | tensor_dict[x_id] = new Queue<Tensor>(Enumerable.Range(0, tensor_usage_count[x_id]).Select(x => y)); | ||||
} | } | ||||
@@ -635,6 +635,21 @@ namespace Tensorflow.Keras.Layers | |||||
return layer.Apply(inputs); | return layer.Apply(inputs); | ||||
} | } | ||||
public Layer LayerNormalization(Axis? axis, | |||||
float epsilon = 1e-3f, | |||||
bool center = true, | |||||
bool scale = true, | |||||
IInitializer beta_initializer = null, | |||||
IInitializer gamma_initializer = null) | |||||
=> new LayerNormalization(new LayerNormalizationArgs | |||||
{ | |||||
Axis = axis ?? -1, | |||||
Epsilon = epsilon, | |||||
Center = center, | |||||
Scale = scale, | |||||
BetaInitializer = beta_initializer ?? tf.zeros_initializer | |||||
}); | |||||
/// <summary> | /// <summary> | ||||
/// Leaky version of a Rectified Linear Unit. | /// Leaky version of a Rectified Linear Unit. | ||||
/// </summary> | /// </summary> | ||||
@@ -218,7 +218,8 @@ namespace Tensorflow.Keras.Layers | |||||
beta, | beta, | ||||
mean: moving_mean, | mean: moving_mean, | ||||
variance: moving_variance, | variance: moving_variance, | ||||
epsilon: epsilon, is_training: true, | |||||
epsilon: epsilon, | |||||
is_training: true, | |||||
data_format: _data_format, | data_format: _data_format, | ||||
exponential_avg_factor: exponential_avg_factor); | exponential_avg_factor: exponential_avg_factor); | ||||
}; | }; | ||||
@@ -0,0 +1,145 @@ | |||||
/***************************************************************************** | |||||
Copyright 2021 Haiping Chen. All Rights Reserved. | |||||
Licensed under the Apache License, Version 2.0 (the "License"); | |||||
you may not use this file except in compliance with the License. | |||||
You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
******************************************************************************/ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using Tensorflow.Keras.ArgsDefinition; | |||||
using Tensorflow.Keras.Engine; | |||||
using Tensorflow.Keras.Utils; | |||||
using static Tensorflow.Binding; | |||||
namespace Tensorflow.Keras.Layers | |||||
{ | |||||
public class LayerNormalization : Layer | |||||
{ | |||||
LayerNormalizationArgs args; | |||||
float epsilon => args.Epsilon; | |||||
bool center => args.Center; | |||||
bool scale => args.Scale; | |||||
bool _fused; | |||||
int[] axis; | |||||
string _data_format; | |||||
Shape kernel_size; | |||||
IInitializer beta_initializer => args.BetaInitializer; | |||||
IInitializer gamma_initializer => args.GammaInitializer; | |||||
IRegularizer gamma_regularizer => args.GammaRegularizer; | |||||
IVariableV1 gamma; | |||||
IVariableV1 beta; | |||||
IVariableV1 moving_mean; | |||||
IVariableV1 moving_variance; | |||||
public LayerNormalization(LayerNormalizationArgs args) : base(args) | |||||
{ | |||||
this.args = args; | |||||
axis = args.Axis.axis; | |||||
} | |||||
protected override void build(Tensors inputs) | |||||
{ | |||||
Shape input_shape = inputs.shape; | |||||
var ndims = input_shape.ndim; | |||||
foreach (var (idx, x) in enumerate(axis)) | |||||
if (x < 0) | |||||
axis[idx] = ndims + x; | |||||
var axis_to_dim = new Dictionary<int, int>(); | |||||
foreach (var x in axis) | |||||
axis_to_dim[x] = (int)input_shape[x]; | |||||
inputSpec = new InputSpec(ndim: ndims, axes: axis_to_dim); | |||||
var param_dtype = DType == TF_DataType.DtInvalid ? TF_DataType.TF_FLOAT : DType; | |||||
var param_shape = inputSpec.AllAxisDim; | |||||
if (scale) | |||||
gamma = add_weight("gamma", | |||||
param_shape, | |||||
dtype: param_dtype, | |||||
initializer: gamma_initializer, | |||||
trainable: true); | |||||
if (center) | |||||
beta = add_weight("beta", | |||||
param_shape, | |||||
dtype: param_dtype, | |||||
initializer: beta_initializer, | |||||
trainable: true); | |||||
_fused = _fused_can_be_used(ndims); | |||||
built = true; | |||||
} | |||||
bool _fused_can_be_used(int ndims) | |||||
{ | |||||
var can_use_fused = false; | |||||
if (axis.Last() == ndims - 1 && axis.Last() - axis[0] == len(axis) - 1) | |||||
can_use_fused = true; | |||||
if (epsilon < 1.001e-5 || DType != tf.float32) | |||||
can_use_fused = false; | |||||
return can_use_fused; | |||||
} | |||||
public override Shape ComputeOutputShape(Shape input_shape) | |||||
{ | |||||
return input_shape; | |||||
} | |||||
protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) | |||||
{ | |||||
Tensors outputs = null; | |||||
var inputs_dtype = inputs.dtype.as_base_dtype(); | |||||
var input_shape = inputs.shape; | |||||
var ndims = len(input_shape); | |||||
var broadcast_shape = range(ndims).Select(x => 1).ToArray(); | |||||
foreach (var dim in axis) | |||||
broadcast_shape[dim] = input_shape.as_int_list()[dim]; | |||||
if (_fused) | |||||
{ | |||||
var tensor_shape = tf.shape(inputs); | |||||
var pre_dim = tf.constant(1); | |||||
var in_dim = tf.constant(1); | |||||
foreach (var dim in range(ndims)) | |||||
{ | |||||
var dim_tensor = tensor_shape[dim]; | |||||
if (dim < axis[0]) | |||||
pre_dim = pre_dim * dim_tensor; | |||||
else | |||||
in_dim = in_dim * dim_tensor; | |||||
} | |||||
inputs = tf.reshape(inputs, new object[] { 1, pre_dim, in_dim, 1 }); | |||||
var scale = tf.ones(new Shape((int)pre_dim), dtype: DType); | |||||
var offset = tf.zeros(new Shape((int)pre_dim), dtype: DType); | |||||
/*outputs = tf.nn.fused_batch_norm( | |||||
inputs, | |||||
scale: scale, | |||||
offset: offset, | |||||
epsilon: epsilon, | |||||
data_format: "NCHW");*/ | |||||
} | |||||
else | |||||
{ | |||||
} | |||||
return outputs; | |||||
} | |||||
} | |||||
} |
@@ -60,7 +60,7 @@ Keras is an API designed for human beings, not machines. Keras follows best prac | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.139" /> | |||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.144" /> | |||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | ||||
<PackageReference Include="SciSharp.Keras.HDF5" Version="1.1.10.500" /> | <PackageReference Include="SciSharp.Keras.HDF5" Version="1.1.10.500" /> | ||||
<PackageReference Include="SharpZipLib" Version="1.3.3" /> | <PackageReference Include="SharpZipLib" Version="1.3.3" /> | ||||
@@ -26,7 +26,7 @@ namespace TensorFlowNET.UnitTest | |||||
using (var sess = tf.Session()) | using (var sess = tf.Session()) | ||||
{ | { | ||||
var default_graph = tf.peak_default_graph(); | |||||
var default_graph = tf.get_default_graph(); | |||||
var sess_graph = sess.graph; | var sess_graph = sess.graph; | ||||
Assert.IsNotNull(default_graph); | Assert.IsNotNull(default_graph); | ||||
Assert.IsNotNull(sess_graph); | Assert.IsNotNull(sess_graph); | ||||
@@ -49,7 +49,7 @@ namespace TensorFlowNET.UnitTest | |||||
//tf.Session created an other graph | //tf.Session created an other graph | ||||
using (var sess = tf.Session()) | using (var sess = tf.Session()) | ||||
{ | { | ||||
var default_graph = tf.peak_default_graph(); | |||||
var default_graph = tf.get_default_graph(); | |||||
var sess_graph = sess.graph; | var sess_graph = sess.graph; | ||||
Assert.IsNotNull(default_graph); | Assert.IsNotNull(default_graph); | ||||
Assert.IsNotNull(sess_graph); | Assert.IsNotNull(sess_graph); | ||||
@@ -159,7 +159,8 @@ namespace TensorFlowNET.UnitTest | |||||
var math = a1 + a2; | var math = a1 + a2; | ||||
for (int i = 0; i < 100; i++) | for (int i = 0; i < 100; i++) | ||||
{ | { | ||||
using (var sess = tf.Session()) | |||||
var graph = tf.get_default_graph(); | |||||
using (var sess = tf.Session(graph)) | |||||
{ | { | ||||
var result = sess.run(math); | var result = sess.run(math); | ||||
Assert.AreEqual(result[0], 5f); | Assert.AreEqual(result[0], 5f); | ||||
@@ -171,14 +172,14 @@ namespace TensorFlowNET.UnitTest | |||||
[TestMethod] | [TestMethod] | ||||
public void SessionRun_InsideSession() | public void SessionRun_InsideSession() | ||||
{ | { | ||||
MultiThreadedUnitTestExecuter.Run(1, Core); | |||||
MultiThreadedUnitTestExecuter.Run(8, Core); | |||||
//the core method | //the core method | ||||
void Core(int tid) | void Core(int tid) | ||||
{ | { | ||||
using (var sess = tf.Session()) | using (var sess = tf.Session()) | ||||
{ | { | ||||
Assert.IsNotNull(tf.peak_default_graph()); | |||||
Assert.IsNotNull(tf.get_default_graph()); | |||||
//graph is created automatically to perform create these operations | //graph is created automatically to perform create these operations | ||||
var a1 = tf.constant(new[] { 2f }, shape: new[] { 1 }); | var a1 = tf.constant(new[] { 2f }, shape: new[] { 1 }); | ||||
var a2 = tf.constant(new[] { 3f }, shape: new[] { 1 }); | var a2 = tf.constant(new[] { 3f }, shape: new[] { 1 }); | ||||
@@ -200,7 +201,7 @@ namespace TensorFlowNET.UnitTest | |||||
{ | { | ||||
using (var sess = tf.Session()) | using (var sess = tf.Session()) | ||||
{ | { | ||||
Assert.IsNotNull(tf.peak_default_graph()); | |||||
Assert.IsNotNull(tf.get_default_graph()); | |||||
//graph is created automatically to perform create these operations | //graph is created automatically to perform create these operations | ||||
var a1 = tf.constant(new[] { 2f }, shape: new[] { 1 }); | var a1 = tf.constant(new[] { 2f }, shape: new[] { 1 }); | ||||
var a2 = tf.constant(new[] { 3f }, shape: new[] { 1 }); | var a2 = tf.constant(new[] { 3f }, shape: new[] { 1 }); | ||||
@@ -24,7 +24,7 @@ | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" /> | |||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | ||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | <PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | ||||
<PackageReference Include="coverlet.collector" Version="3.1.0"> | <PackageReference Include="coverlet.collector" Version="3.1.0"> | ||||
@@ -152,5 +152,14 @@ namespace TensorFlowNET.Keras.UnitTest | |||||
var output = layer.Apply(inputs); | var output = layer.Apply(inputs); | ||||
Assert.AreEqual((10, 16, 16, 3), output.shape); | Assert.AreEqual((10, 16, 16, 3), output.shape); | ||||
} | } | ||||
[TestMethod] | |||||
public void LayerNormalization() | |||||
{ | |||||
var inputs = tf.constant(np.arange(10).reshape((5, 2)) * 10, dtype: tf.float32); | |||||
var layer = keras.layers.LayerNormalization(axis: 1); | |||||
var output = layer.Apply(inputs); | |||||
// Assert.AreEqual((10, 16, 16, 3), output.shape); | |||||
} | |||||
} | } | ||||
} | } |
@@ -14,7 +14,7 @@ | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" /> | |||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | ||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | <PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | ||||
<PackageReference Include="coverlet.collector" Version="3.1.0"> | <PackageReference Include="coverlet.collector" Version="3.1.0"> | ||||
@@ -44,7 +44,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="FluentAssertions" Version="5.10.3" /> | <PackageReference Include="FluentAssertions" Version="5.10.3" /> | ||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" /> | |||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | ||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | <PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | ||||
<PackageReference Include="coverlet.collector" Version="3.1.0"> | <PackageReference Include="coverlet.collector" Version="3.1.0"> | ||||
@@ -47,8 +47,8 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="FluentAssertions" Version="5.10.3" /> | <PackageReference Include="FluentAssertions" Version="5.10.3" /> | ||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.139" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> | |||||
<PackageReference Include="MethodBoundaryAspect.Fody" Version="2.0.144" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" /> | |||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | <PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> | ||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | <PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> | ||||
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.6.0" /> | <PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.6.0" /> | ||||