_calcOutputShape(inputShape) {
    if (this.outputShape && this.outputPadding) {
      return
    }

    const inputRows = inputShape[0]
    const inputCols = inputShape[1]
    const [nbFilter, nbRow, nbCol] = this.kernelShape

    const outputRows =
      this.padding === 'same'
        ? inputRows * this.strides[0]
        : inputRows * this.strides[0] + Math.max(nbRow - this.strides[0], 0)
    const outputCols =
      this.padding === 'same'
        ? inputCols * this.strides[1]
        : inputCols * this.strides[1] + Math.max(nbCol - this.strides[1], 0)
    const outputChannels = nbFilter

    const paddingRow =
      this.padding === 'same' ? Math.max(0, Math.floor((inputRows - 1) * this.strides[0] + nbRow - outputRows)) : 0
    const paddingCol =
      this.padding === 'same' ? Math.max(0, Math.floor((inputCols - 1) * this.strides[1] + nbCol - outputCols)) : 0
    const paddingRowBefore = Math.floor(paddingRow / 2)
    const paddingRowAfter = paddingRow - paddingRowBefore
    const paddingColBefore = Math.floor(paddingCol / 2)
    const paddingColAfter = paddingCol - paddingColBefore

    this.outputShape = [outputRows, outputCols, outputChannels]
    this.outputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]
  }
Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode.

For tensorflow implementation of padding, see:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc

For deconvolution, we will "take away" padding from the output rather than add padding to the input.

For more details on calculating output shapes and padding for transposed convolutions (deconvolution here), see:
https://arxiv.org/pdf/1603.07285v1.pdf

@param {number[]} inputShape