Contents

BNNSFilterCreateLayerPooling(_:_:)

Returns a new pooling layer.

Declaration

func BNNSFilterCreateLayerPooling(_ layer_params: UnsafePointer<BNNSLayerParametersPooling>, _ filter_params: UnsafePointer<BNNSFilterParameters>?) -> BNNSFilter?

Parameters

  • layer_params:

    Layer parameters.

  • filter_params:

    The filter runtime parameters.

Discussion

Use a pooling layer to downsample an input, selecting, for example, the average or the maximum value in a specified kernel size. The following figure illustrates how a 2 x 2 maximum pooling kernel samples each 2 x 2 block of values of 4 x 4 source. The highlighted block contains the values [3, 4, 0, 0], so the maximum value passed to the destination element in output is 4.

[Image]

The following code shows how you apply pooling to the input in the above figure. Note that the input is a 2 x 2 x 1 BNNSDataLayoutImageCHW tensor. Definie x_padding and y_padding as 1 to add zero padding:

let input: [Float] = [1, 2,
                      3, 4]

var output = [Float](repeating: 0, count: 9)

let inDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                         layout: BNNSDataLayoutImageCHW,
                                         size: (2, 2, 1, 0, 0, 0, 0, 0),
                                         stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                         data: nil,
                                         data_type: .float,
                                         table_data: nil,
                                         table_data_type: .float,
                                         data_scale: 0,
                                         data_bias: 0)

let outDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                          layout: BNNSDataLayoutImageCHW,
                                          size: (3, 3, 1, 0, 0, 0, 0, 0),
                                          stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                          data: nil,
                                          data_type: .float,
                                          table_data: nil,
                                          table_data_type: .float,
                                          data_scale: 0,
                                          data_bias: 0)

var parameters = BNNSLayerParametersPooling(i_desc: inDescriptor,
                                            o_desc: outDescriptor,
                                            bias: BNNSNDArrayDescriptor(),
                                            activation: .identity,
                                            pooling_function: .max    ,
                                            k_width: 2,
                                            k_height: 2,
                                            x_stride: 1,
                                            y_stride: 1,
                                            x_dilation_stride: 0,
                                            y_dilation_stride: 0,
                                            x_padding: 1,
                                            y_padding: 1,
                                            pad: (0, 0, 0, 0))

let filter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(filter)
}

BNNSPoolingFilterApplyBatch(filter, 1,
                            input, input.count,
                            &output, output.count,
                            nil, 0)

On return, output contains the following values:

[ 1.0, 2.0, 2.0, 
  3.0, 4.0, 4.0, 
  3.0, 4.0, 4.0 ]

UnMax Pooling

Use BNNSPoolingFunctionUnMax in conjunction with the indices generated by BNNSPoolingFunctionMax to partially recreate the original data of a maximum pooling operation. UnMax pooling is a partial inverse of maximum pooling that sets all non-maximal values to zero.

For example, given the following input data:

let input: [Float] = [1, 1, 1, 9,
                      1, 9, 9, 1,
                      1, 1, 1, 1,
                      1, 9, 1, 9]

Use BNNSPoolingFilterApplyBatch(_:_:_:_:_:_:_:_:) to perform the maximum pooling and populate an indices array with positional information of maximum elements in each window:

var output = [Float](repeating: 0, count: 3 * 3)

let inDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                         layout: BNNSDataLayoutImageCHW,
                                         size: (4, 4, 1, 0, 0, 0, 0, 0),
                                         stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                         data: nil,
                                         data_type: .float,
                                         table_data: nil,
                                         table_data_type: .float,
                                         data_scale: 0,
                                         data_bias: 0)

let outDescriptor = BNNSNDArrayDescriptor(flags: BNNSNDArrayFlags(0),
                                          layout: BNNSDataLayoutImageCHW,
                                          size: (3, 3, 1, 0, 0, 0, 0, 0),
                                          stride: (0, 0, 0, 0, 0, 0, 0, 0),
                                          data: nil,
                                          data_type: .float,
                                          table_data: nil,
                                          table_data_type: .float,
                                          data_scale: 0,
                                          data_bias: 0)

var parameters = BNNSLayerParametersPooling(i_desc: inDescriptor,
                                            o_desc: outDescriptor,
                                            bias: BNNSNDArrayDescriptor(),
                                            activation: .identity,
                                            pooling_function: .max    ,
                                            k_width: 2,
                                            k_height: 2,
                                            x_stride: 1,
                                            y_stride: 1,
                                            x_dilation_stride: 0,
                                            y_dilation_stride: 0,
                                            x_padding: 0,
                                            y_padding: 0,
                                            pad: (0, 0, 0, 0))

let filter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(filter)
}

var indices = [Int](repeating: 0, count: input.count)

BNNSPoolingFilterApplyBatch(filter, 1,
                            input, input.count,
                            &output, output.count,
                            &indices, indices.count)

To perform the UnMax pooling, reuse the parameters structure, but swap the input and output descriptors:

var recreatedInput = [Float](repeating: 0, count: input.count)

parameters.i_desc = outDescriptor
parameters.o_desc = inDescriptor
parameters.pooling_function = BNNSPoolingFunctionUnMax

let unMaxFilter = BNNSFilterCreateLayerPooling(&parameters, nil)

defer {
    BNNSFilterDestroy(unMaxFilter)
}

BNNSPoolingFilterApplyBatch(unMaxFilter, 1,
                            output, output.count,
                            &recreatedInput, recreatedInput.count,
                            &indices, indices.count)

On return, recreatedInput is similar to input, but the non-maximal values are zero:

[ 0.0, 0.0, 0.0, 9.0,
  0.0, 9.0, 9.0, 0.0,
  0.0, 0.0, 0.0, 0.0,
  0.0, 9.0, 0.0, 9.0 ]

See Also

Pooling layers