| @@ -155,6 +155,8 @@ namespace Tensorflow | |||
| { | |||
| switch (a) | |||
| { | |||
| case Tensor tensor: | |||
| return tensor.shape[0]; | |||
| case Tensors arr: | |||
| return arr.Length; | |||
| case Array arr: | |||
| @@ -5,7 +5,7 @@ | |||
| <AssemblyName>TensorFlow.NET</AssemblyName> | |||
| <RootNamespace>Tensorflow</RootNamespace> | |||
| <TargetTensorFlow>2.2.0</TargetTensorFlow> | |||
| <Version>0.40.1</Version> | |||
| <Version>0.50.0</Version> | |||
| <LangVersion>8.0</LangVersion> | |||
| <Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> | |||
| <Company>SciSharp STACK</Company> | |||
| @@ -19,7 +19,7 @@ | |||
| <Description>Google's TensorFlow full binding in .NET Standard. | |||
| Building, training and infering deep learning models. | |||
| 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. | |||
| * 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. | |||
| 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> | |||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
| <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) | |||
| { | |||
| var slice_spec = new int[] { start }; | |||
| @@ -146,9 +146,7 @@ namespace Tensorflow | |||
| } | |||
| if (dtype == TF_DataType.TF_STRING && value is byte[] bytes) | |||
| { | |||
| return new EagerTensor(bytes, ctx.DeviceName, TF_DataType.TF_STRING); | |||
| } | |||
| switch (value) | |||
| { | |||
| @@ -673,5 +673,38 @@ would not be rank 1.", tensor.op.get_attr("axis"))); | |||
| 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.Binding; | |||
| using NumSharp; | |||
| namespace Tensorflow.Keras | |||
| { | |||
| @@ -41,7 +43,7 @@ namespace Tensorflow.Keras | |||
| int num_channels = 0; | |||
| if (color_mode == "rgb") | |||
| num_channels = 3; | |||
| var (image_paths, label_list, class_name_list) = keras.preprocessing.dataset_utils.index_directory(directory, | |||
| labels, | |||
| formats: WHITELIST_FORMATS, | |||
| @@ -90,5 +92,50 @@ namespace Tensorflow.Keras | |||
| dataset.class_names = class_name_list; | |||
| 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> | |||
| <RootNamespace>Tensorflow.Keras</RootNamespace> | |||
| <Platforms>AnyCPU;x64</Platforms> | |||
| <Version>0.5.1</Version> | |||
| <Version>0.5.2</Version> | |||
| <Authors>Haiping Chen</Authors> | |||
| <Product>Keras for .NET</Product> | |||
| <Copyright>Apache 2.0, Haiping Chen 2021</Copyright> | |||
| @@ -24,7 +24,8 @@ | |||
| * Support model.load_weights. | |||
| * Add Subtract layer | |||
| * Support YOLOv3 model. | |||
| * Text preprocessing</PackageReleaseNotes> | |||
| * Text preprocessing | |||
| * Preprocessing.timeseries_dataset_from_array</PackageReleaseNotes> | |||
| <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> | |||
| @@ -35,8 +36,8 @@ Keras is an API designed for human beings, not machines. Keras follows best prac | |||
| <RepositoryType>Git</RepositoryType> | |||
| <SignAssembly>true</SignAssembly> | |||
| <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> | |||
| </PropertyGroup> | |||