webmachinelearning / webnn-polyfill

🧠⚙️ Web Neural Network API polyfill based on TensorFlow.js
https://www.npmjs.com/package/@webmachinelearning/webnn-polyfill
Apache License 2.0
102 stars 18 forks source link

Support roundingType and outputSizes options for pool2d. #140

Closed BruceDai closed 2 years ago

BruceDai commented 3 years ago

Fix #135. Depend on https://github.com/tensorflow/tfjs/pull/5849.

@huningxin PTAL, thanks.

huningxin commented 3 years ago

Hi @BruceDai , thanks for the PR. You mentions it depends on a tfjs enhancement. May I know what is the gap? roundingType or outputSizes or both of them? If there is no gap to support roundingType. I would recommend to focus on that first without depending on the tfjs release.

BruceDai commented 3 years ago

Hi @huningxin.

Currently our pool2d implementation's invoked tf.pool() function doesn't support dimRoundingMode attributes which new option roundingType could be mapped to, and tf.pool() function either doesn't support outputSizes attribute, so I submitted the PR to enable/support these two attributes for tfjs pool.

If we invoked tf.avgPool() or tf.maxPool() functions to replace tf.pool(), we could support new option roundingType firstly. Thanks.

huningxin commented 3 years ago

If we invoked tf.avgPool() or tf.maxPool() functions to replace tf.pool(), we could support new option roundingType firstly. Thanks.

It sounds good to me.

BruceDai commented 3 years ago

If we invoked tf.avgPool() or tf.maxPool() functions to replace tf.pool(), we could support new option roundingType firstly.

@huningxin I'm sorry to deliver the wrong message, I missed considering the case of dilations. tf.avgPool() and tf.maxPool() functions could not support dilations directly, while tf.pool() function could do pre-processing with dilations, as below code, then pass that to tf.avgPool()andtf.maxPool()` functions

function pool_<T extends Tensor3D|Tensor4D>(
    input: T|TensorLike, windowShape: [number, number]|number,
    poolingType: 'avg'|'max',
    pad: 'valid'|'same'|number|conv_util.ExplicitPadding,
    dilations?: [number, number]|number, strides?: [number, number]|number,
    dimRoundingMode?: 'floor'|'round'|'ceil') {
  if (dilations == null) {
    dilations = [1, 1];
  }
  ...
  util.assert(
      conv_util.eitherStridesOrDilationsAreOne(strides, dilations),
      () => 'Error in pool: Either strides or dilations must be 1. ' +
          `Got strides ${strides} and dilations '${dilations}'`);

  const convInfo = conv_util.computePool2DInfo(
      x4D.shape, windowShape, strides, dilations, pad);
  const dilation: [number, number] =
      [convInfo.dilationHeight, convInfo.dilationWidth];

  let basePadding: number[][];
  if (pad === 'same') {
    basePadding = withSpaceToBatchBasePaddings(
        [convInfo.filterHeight, convInfo.filterWidth], dilation);
  } else {
    basePadding = [[0, 0], [0, 0]];
  }

  const isDilationOne = dilation[0] === 1 && dilation[1] === 1;
  const [adjustedPadding, adjustedCrops] = requiredSpaceToBatchPaddings(
      [convInfo.inHeight, convInfo.inWidth], dilation, basePadding);
  const convertedPad = isDilationOne ? pad : 'valid';
  const convertedX =
      isDilationOne ? x4D : spaceToBatchND(x4D, dilation, adjustedPadding);

  const forwardOp = poolingType === 'avg' ?
      () => avgPool(convertedX, windowShape, strides, convertedPad,
                    dimRoundingMode) :
      () => maxPool(convertedX, windowShape, strides, convertedPad,
                    dimRoundingMode);
...

So to enable these new two options, we still depend on tfjs implementation. Thanks

BruceDai commented 2 years ago

For outputSizes options, I referred to output shape calculation method of pool2d on WebNN-native repo by @mingmingtasd. @huningxin @mingmingtasd PTAL, thanks.

BruceDai commented 2 years ago

@mingmingtasd I updated code following your comments, please take another review, thanks.

mingmingtasd commented 2 years ago

@mingmingtasd I updated code following your comments, please take another review, thanks.

Thanks, LGTM! @BruceDai