| @@ -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> | ||||