| @@ -56,7 +56,9 @@ namespace Tensorflow.Keras.Layers | |||
| protected override void build(TensorShape input_shape) | |||
| { | |||
| int channel_axis = data_format == "channels_first" ? 1 : -1; | |||
| int input_dim = input_shape.Dimensions[input_shape.NDim - 1]; | |||
| int input_dim = channel_axis < 0 ? | |||
| input_shape.Dimensions[input_shape.NDim + channel_axis] : | |||
| input_shape.Dimensions[channel_axis]; | |||
| var kernel_shape = new int[] { kernel_size[0], kernel_size[1], input_dim, filters }; | |||
| kernel = add_weight(name: "kernel", | |||
| shape: kernel_shape, | |||
| @@ -102,7 +104,7 @@ namespace Tensorflow.Keras.Layers | |||
| } | |||
| else | |||
| { | |||
| outputs = nn_ops.bias_add(outputs, bias._AsTensor(), data_format: "NHWC"); | |||
| outputs = nn_ops.bias_add(outputs, bias, data_format: "NHWC"); | |||
| } | |||
| } | |||
| @@ -206,12 +206,14 @@ namespace Tensorflow.Keras.Layers | |||
| _updates.AddRange(updates_op); | |||
| } | |||
| // Determine layer name (non-unique). | |||
| protected virtual void _init_set_name(string name, bool zero_based = true) | |||
| { | |||
| var base_name = name; | |||
| _name = name; | |||
| if (name == null) | |||
| _name = base_layer_utils.unique_layer_name(generic_utils.to_snake_case(this.GetType().Name), zero_based: zero_based); | |||
| else | |||
| _name = name; | |||
| (_name, base_name) = _make_unique_name(); | |||
| _base_name = base_name; | |||
| } | |||
| protected virtual (string, string) _make_unique_name() | |||
| @@ -67,13 +67,6 @@ namespace Tensorflow.Layers | |||
| return outputs; | |||
| } | |||
| protected override void _init_set_name(string name, bool zero_based = true) | |||
| { | |||
| // Determine layer name (non-unique). | |||
| base._init_set_name(name, zero_based: zero_based); | |||
| _base_name = this.name; | |||
| } | |||
| protected virtual void _add_elements_to_collection(Operation[] elements, string[] collection_list) | |||
| { | |||
| foreach(var name in collection_list) | |||
| @@ -0,0 +1,53 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow.Operations | |||
| { | |||
| public class Conv2dParams | |||
| { | |||
| public string Name { get; set; } | |||
| /// <summary> | |||
| /// An optional `string` from: `"NHWC", "NCHW"`. Defaults to `"NHWC"`. | |||
| /// Specify the data format of the input and output data. With the | |||
| /// default format "NHWC", the data is stored in the order of: | |||
| /// [batch, height, width, channels]. | |||
| /// </summary> | |||
| public string DataFormat { get; set; } = "NHWC"; | |||
| /// <summary> | |||
| /// Must be one of the following types: `half`, `bfloat16`, `float32`, `float64`. | |||
| /// A 4-D tensor. The dimension order is interpreted according to the value | |||
| /// </summary> | |||
| public Tensor Input { get; set; } | |||
| /// <summary> | |||
| /// A 4-D tensor of shape | |||
| /// </summary> | |||
| public Tensor Filter { get; set; } | |||
| /// <summary> | |||
| /// The stride of the sliding window for each | |||
| /// dimension of `input`. The dimension order is determined by the value of | |||
| /// `data_format`, see below for details. | |||
| /// </summary> | |||
| public int[] Strides { get; set; } | |||
| /// <summary> | |||
| /// A `string` from: `"SAME", "VALID", "EXPLICIT"`. | |||
| /// </summary> | |||
| public string Padding { get; set; } | |||
| public int[] ExplicitPaddings { get; set; } = new int[0]; | |||
| public bool UseCudnnOnGpu { get; set; } = true; | |||
| public int[] Dilations { get; set; } = new [] { 1, 1, 1, 1 }; | |||
| public Conv2dParams() | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -11,7 +11,7 @@ namespace Tensorflow.Operations | |||
| public string name; | |||
| public int[] strides; | |||
| public string data_format; | |||
| private Func<object, Tensor> conv_op; | |||
| private Func<Conv2dParams, Tensor> conv_op; | |||
| public _NonAtrousConvolution(TensorShape input_shape, | |||
| TensorShape filter_shape, | |||
| @@ -55,14 +55,14 @@ namespace Tensorflow.Operations | |||
| public Tensor __call__(Tensor inp, RefVariable filter) | |||
| { | |||
| return conv_op(new | |||
| return conv_op(new Conv2dParams | |||
| { | |||
| input = inp, | |||
| filter, | |||
| strides, | |||
| padding, | |||
| data_format, | |||
| name | |||
| Input = inp, | |||
| Filter = filter, | |||
| Strides = strides, | |||
| Padding = padding, | |||
| DataFormat = data_format, | |||
| Name = name | |||
| }); | |||
| } | |||
| } | |||
| @@ -10,28 +10,36 @@ namespace Tensorflow.Operations | |||
| { | |||
| public static OpDefLibrary _op_def_lib = new OpDefLibrary(); | |||
| public static Tensor conv2d(object parameters) | |||
| /// <summary> | |||
| /// Computes a 2-D convolution given 4-D `input` and `filter` tensors. | |||
| /// | |||
| /// Given an input tensor of shape `[batch, in_height, in_width, in_channels]` | |||
| /// and a filter / kernel tensor of shape | |||
| /// `[filter_height, filter_width, in_channels, out_channels]`, this op | |||
| /// performs the following: | |||
| /// | |||
| /// 1. Flattens the filter to a 2-D matrix with shape | |||
| /// `[filter_height * filter_width * in_channels, output_channels]`. | |||
| /// 2. Extracts image patches from the input tensor to form a *virtual* | |||
| /// tensor of shape `[batch, out_height, out_width, | |||
| /// filter_height * filter_width * in_channels]`. | |||
| /// 3. For each patch, right-multiplies the filter matrix and the image patch | |||
| /// vector. | |||
| /// </summary> | |||
| /// <param name="parameters"></param> | |||
| /// <returns></returns> | |||
| public static Tensor conv2d(Conv2dParams parameters) | |||
| { | |||
| var args = Python.ConvertToDict(parameters); | |||
| var input = args["input"]; | |||
| var filter = args["filter"]; | |||
| var strides = args["strides"]; | |||
| var padding = args["padding"]; | |||
| var name = args["name"]; | |||
| var data_format = args.ContainsKey("data_format") ? args["data_format"] : "NHWC"; | |||
| var use_cudnn_on_gpu = args.ContainsKey("use_cudnn_on_gpu") ? args["use_cudnn_on_gpu"] : true; | |||
| var dilations = args.ContainsKey("dilations") ? args["dilations"] : new int[] { 1, 1, 1, 1 }; | |||
| var _op = _op_def_lib._apply_op_helper("Conv2D", name: name?.ToString(), args: new | |||
| var _op = _op_def_lib._apply_op_helper("Conv2D", name: parameters.Name, args: new | |||
| { | |||
| input, | |||
| filter, | |||
| strides, | |||
| padding, | |||
| use_cudnn_on_gpu, | |||
| data_format, | |||
| dilations | |||
| input = parameters.Input, | |||
| filter = parameters.Filter, | |||
| strides = parameters.Strides, | |||
| padding = parameters.Padding, | |||
| use_cudnn_on_gpu = parameters.UseCudnnOnGpu, | |||
| explicit_paddings = parameters.ExplicitPaddings, | |||
| data_format = parameters.DataFormat, | |||
| dilations = parameters.Dilations | |||
| }); | |||
| return _op.outputs[0]; | |||
| @@ -37,6 +37,7 @@ namespace Tensorflow | |||
| { | |||
| return Python.with(ops.name_scope(name, "BiasAdd", new { value, bias }), scope => | |||
| { | |||
| name = scope; | |||
| value = ops.convert_to_tensor(value, name: "input"); | |||
| var bias_tensor = ops.convert_to_tensor(bias, dtype: value.dtype, name: "bias"); | |||
| return gen_nn_ops.bias_add(value, bias_tensor, data_format: data_format, name: name); | |||
| @@ -188,7 +188,7 @@ namespace Tensorflow | |||
| public Tensor _as_graph_element() => _variable; | |||
| public Tensor _TensorConversionFunction(bool as_ref = false) | |||
| public Tensor _TensorConversionFunction(TF_DataType dtype = TF_DataType.DtInvalid, string name = null, bool as_ref = false) | |||
| { | |||
| if (as_ref) | |||
| return _ref(); | |||
| @@ -40,7 +40,7 @@ namespace Tensorflow | |||
| VariableSynchronization synchronization = VariableSynchronization.Auto, | |||
| VariableAggregation aggregation= VariableAggregation.None) | |||
| { | |||
| string full_name = !string.IsNullOrEmpty(this._name) ? this._name + "/" + name : name; | |||
| string full_name = !string.IsNullOrEmpty(this.name) ? this.name + "/" + name : name; | |||
| return with(ops.name_scope(null), scope => | |||
| { | |||
| if (dtype == TF_DataType.DtInvalid) | |||
| @@ -473,7 +473,7 @@ namespace Tensorflow | |||
| case Tensor[] tensors: | |||
| return array_ops._autopacking_helper(tensors, dtype, name == null ? "packed" : name); | |||
| case RefVariable varVal: | |||
| return varVal._TensorConversionFunction(as_ref: as_ref); | |||
| return varVal._TensorConversionFunction(dtype: dtype, name: name, as_ref: as_ref); | |||
| case ResourceVariable varVal: | |||
| return null; | |||
| case object[] objects: | |||