@@ -155,6 +155,8 @@ namespace Tensorflow | |||||
{ | { | ||||
switch (a) | switch (a) | ||||
{ | { | ||||
case Tensor tensor: | |||||
return tensor.shape[0]; | |||||
case Tensors arr: | case Tensors arr: | ||||
return arr.Length; | return arr.Length; | ||||
case Array arr: | case Array arr: | ||||
@@ -5,7 +5,7 @@ | |||||
<AssemblyName>TensorFlow.NET</AssemblyName> | <AssemblyName>TensorFlow.NET</AssemblyName> | ||||
<RootNamespace>Tensorflow</RootNamespace> | <RootNamespace>Tensorflow</RootNamespace> | ||||
<TargetTensorFlow>2.2.0</TargetTensorFlow> | <TargetTensorFlow>2.2.0</TargetTensorFlow> | ||||
<Version>0.40.1</Version> | |||||
<Version>0.50.0</Version> | |||||
<LangVersion>8.0</LangVersion> | <LangVersion>8.0</LangVersion> | ||||
<Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> | <Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> | ||||
<Company>SciSharp STACK</Company> | <Company>SciSharp STACK</Company> | ||||
@@ -19,7 +19,7 @@ | |||||
<Description>Google's TensorFlow full binding in .NET Standard. | <Description>Google's TensorFlow full binding in .NET Standard. | ||||
Building, training and infering deep learning models. | Building, training and infering deep learning models. | ||||
https://tensorflownet.readthedocs.io</Description> | https://tensorflownet.readthedocs.io</Description> | ||||
<AssemblyVersion>0.40.1.0</AssemblyVersion> | |||||
<AssemblyVersion>0.50.0.0</AssemblyVersion> | |||||
<PackageReleaseNotes>tf.net 0.20.x and above are based on tensorflow native 2.x. | <PackageReleaseNotes>tf.net 0.20.x and above are based on tensorflow native 2.x. | ||||
* Eager Mode is added finally. | * Eager Mode is added finally. | ||||
@@ -31,8 +31,9 @@ https://tensorflownet.readthedocs.io</Description> | |||||
TensorFlow .NET v0.3x is focused on making more Keras API works. | TensorFlow .NET v0.3x is focused on making more Keras API works. | ||||
Keras API is a separate package released as TensorFlow.Keras. | Keras API is a separate package released as TensorFlow.Keras. | ||||
tf.net 0.4x.x aligns with TensorFlow v2.4.1 native library.</PackageReleaseNotes> | |||||
<FileVersion>0.40.1.0</FileVersion> | |||||
tf.net 0.4x.x aligns with TensorFlow v2.4.1 native library. | |||||
tf.net 0.5x.x aligns with TensorFlow v2.5.x native library.</PackageReleaseNotes> | |||||
<FileVersion>0.50.0.0</FileVersion> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
<SignAssembly>true</SignAssembly> | <SignAssembly>true</SignAssembly> | ||||
@@ -120,6 +120,35 @@ namespace Tensorflow | |||||
}); | }); | ||||
} | } | ||||
public Tensor this[params Tensor[] slice] | |||||
{ | |||||
get | |||||
{ | |||||
var args = tensor_util.ParseSlices(slice); | |||||
return tf_with(ops.name_scope(null, "strided_slice", args), scope => | |||||
{ | |||||
string name = scope; | |||||
var tensor = gen_array_ops.strided_slice( | |||||
this, | |||||
args.PackedBegin, | |||||
args.PackedEnd, | |||||
args.PackedStrides, | |||||
begin_mask: args.BeginMask, | |||||
end_mask: args.EndMask, | |||||
shrink_axis_mask: args.ShrinkAxisMask, | |||||
new_axis_mask: args.NewAxisMask, | |||||
ellipsis_mask: args.EllipsisMask, | |||||
name: name); | |||||
tensor.OriginalVarSlice = args; | |||||
return tensor; | |||||
}); | |||||
} | |||||
} | |||||
public Tensor slice(int start) | public Tensor slice(int start) | ||||
{ | { | ||||
var slice_spec = new int[] { start }; | var slice_spec = new int[] { start }; | ||||
@@ -146,9 +146,7 @@ namespace Tensorflow | |||||
} | } | ||||
if (dtype == TF_DataType.TF_STRING && value is byte[] bytes) | if (dtype == TF_DataType.TF_STRING && value is byte[] bytes) | ||||
{ | |||||
return new EagerTensor(bytes, ctx.DeviceName, TF_DataType.TF_STRING); | return new EagerTensor(bytes, ctx.DeviceName, TF_DataType.TF_STRING); | ||||
} | |||||
switch (value) | switch (value) | ||||
{ | { | ||||
@@ -673,5 +673,38 @@ would not be rank 1.", tensor.op.get_attr("axis"))); | |||||
NewAxisMask = new_axis_mask | NewAxisMask = new_axis_mask | ||||
}; | }; | ||||
} | } | ||||
public static ParsedSliceArgs ParseSlices(Tensor[] slices) | |||||
{ | |||||
var begin = new List<Tensor>(); | |||||
var end = new List<Tensor>(); | |||||
var strides = new List<Tensor>(); | |||||
var index = 0; | |||||
var (new_axis_mask, shrink_axis_mask) = (0, 0); | |||||
var (begin_mask, end_mask) = (0, 0); | |||||
var ellipsis_mask = 0; | |||||
foreach (var s in slices) | |||||
{ | |||||
begin.Add(s); | |||||
end.Add(s + 1); | |||||
shrink_axis_mask |= (1 << index); | |||||
strides.Add(tf.constant(1, dtype: s.dtype)); | |||||
index += 1; | |||||
} | |||||
return new ParsedSliceArgs | |||||
{ | |||||
PackedBegin = array_ops.stack(begin), | |||||
PackedEnd = array_ops.stack(end), | |||||
PackedStrides = array_ops.stack(strides), | |||||
BeginMask = begin_mask, | |||||
EndMask = end_mask, | |||||
EllipsisMask = ellipsis_mask, | |||||
ShrinkAxisMask = shrink_axis_mask, | |||||
NewAxisMask = new_axis_mask | |||||
}; | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,4 +1,6 @@ | |||||
using static Tensorflow.KerasApi; | using static Tensorflow.KerasApi; | ||||
using static Tensorflow.Binding; | |||||
using NumSharp; | |||||
namespace Tensorflow.Keras | namespace Tensorflow.Keras | ||||
{ | { | ||||
@@ -41,7 +43,7 @@ namespace Tensorflow.Keras | |||||
int num_channels = 0; | int num_channels = 0; | ||||
if (color_mode == "rgb") | if (color_mode == "rgb") | ||||
num_channels = 3; | num_channels = 3; | ||||
var (image_paths, label_list, class_name_list) = keras.preprocessing.dataset_utils.index_directory(directory, | var (image_paths, label_list, class_name_list) = keras.preprocessing.dataset_utils.index_directory(directory, | ||||
labels, | labels, | ||||
formats: WHITELIST_FORMATS, | formats: WHITELIST_FORMATS, | ||||
@@ -90,5 +92,50 @@ namespace Tensorflow.Keras | |||||
dataset.class_names = class_name_list; | dataset.class_names = class_name_list; | ||||
return dataset; | return dataset; | ||||
} | } | ||||
/// <summary> | |||||
/// Creates a dataset of sliding windows over a timeseries provided as array. | |||||
/// </summary> | |||||
/// <param name="data"></param> | |||||
/// <param name="sequence_length"></param> | |||||
/// <param name="sequence_stride"></param> | |||||
/// <param name="sampling_rate"></param> | |||||
/// <param name="batch_size"></param> | |||||
/// <param name="shuffle"></param> | |||||
/// <returns></returns> | |||||
public IDatasetV2 timeseries_dataset_from_array(Tensor data, int sequence_length, | |||||
int sequence_stride = 1, int sampling_rate = 1, int batch_size = 128, | |||||
bool shuffle = false, int seed = (int)1e6, int start_index = 0, int? end_index = null) | |||||
{ | |||||
if (!end_index.HasValue) | |||||
end_index = len(data); | |||||
var num_seqs = end_index.Value - start_index - (sequence_length * sampling_rate) + 1; | |||||
var index_dtype = num_seqs < 2147483647 ? tf.int32 : tf.int64; | |||||
var start_positions = np.arange(0, num_seqs, sequence_stride); | |||||
if (shuffle) | |||||
{ | |||||
var rng = np.random.RandomState(seed); | |||||
rng.shuffle(start_positions); | |||||
} | |||||
var sequence_length_tensor = math_ops.cast(sequence_length, dtype: index_dtype); | |||||
var sampling_rate_tensor = math_ops.cast(sampling_rate, dtype: index_dtype); | |||||
var start_positions_tensor = tf.constant(start_positions); | |||||
var positions_ds = tf.data.Dataset.from_tensor(start_positions_tensor).repeat(); | |||||
var z = tf.data.Dataset.zip(tf.data.Dataset.range(len(start_positions)), positions_ds); | |||||
var indices = z.map(m => | |||||
{ | |||||
var (i, positions) = (m[0], m[1]); | |||||
return tf.range(positions[i], positions[i] + sequence_length_tensor * sampling_rate_tensor, sampling_rate_tensor); | |||||
}, num_parallel_calls: -1); | |||||
return null; | |||||
} | |||||
IDatasetV2 sequences_from_indices(Tensor array, Tensor indices_ds, Tensor start_index, Tensor end_index) | |||||
{ | |||||
return null; | |||||
} | |||||
} | } | ||||
} | } |
@@ -6,7 +6,7 @@ | |||||
<LangVersion>8.0</LangVersion> | <LangVersion>8.0</LangVersion> | ||||
<RootNamespace>Tensorflow.Keras</RootNamespace> | <RootNamespace>Tensorflow.Keras</RootNamespace> | ||||
<Platforms>AnyCPU;x64</Platforms> | <Platforms>AnyCPU;x64</Platforms> | ||||
<Version>0.5.1</Version> | |||||
<Version>0.5.2</Version> | |||||
<Authors>Haiping Chen</Authors> | <Authors>Haiping Chen</Authors> | ||||
<Product>Keras for .NET</Product> | <Product>Keras for .NET</Product> | ||||
<Copyright>Apache 2.0, Haiping Chen 2021</Copyright> | <Copyright>Apache 2.0, Haiping Chen 2021</Copyright> | ||||
@@ -24,7 +24,8 @@ | |||||
* Support model.load_weights. | * Support model.load_weights. | ||||
* Add Subtract layer | * Add Subtract layer | ||||
* Support YOLOv3 model. | * Support YOLOv3 model. | ||||
* Text preprocessing</PackageReleaseNotes> | |||||
* Text preprocessing | |||||
* Preprocessing.timeseries_dataset_from_array</PackageReleaseNotes> | |||||
<Description>Keras for .NET | <Description>Keras for .NET | ||||
Keras is an API designed for human beings, not machines. Keras follows best practices for reducing cognitive load: it offers consistent & simple APIs, it minimizes the number of user actions required for common use cases, and it provides clear & actionable error messages.</Description> | Keras is an API designed for human beings, not machines. Keras follows best practices for reducing cognitive load: it offers consistent & simple APIs, it minimizes the number of user actions required for common use cases, and it provides clear & actionable error messages.</Description> | ||||
@@ -35,8 +36,8 @@ Keras is an API designed for human beings, not machines. Keras follows best prac | |||||
<RepositoryType>Git</RepositoryType> | <RepositoryType>Git</RepositoryType> | ||||
<SignAssembly>true</SignAssembly> | <SignAssembly>true</SignAssembly> | ||||
<AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile> | <AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile> | ||||
<AssemblyVersion>0.5.1.0</AssemblyVersion> | |||||
<FileVersion>0.5.1.0</FileVersion> | |||||
<AssemblyVersion>0.5.2.0</AssemblyVersion> | |||||
<FileVersion>0.5.2.0</FileVersion> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
</PropertyGroup> | </PropertyGroup> | ||||