license import { backend_util , Dilation2DAttrs , Dilation2DBackpropFilter , Tensor3D , Tensor4D , TypedArray , util } from '@tensorflow/tfjs-core' ; import { KernelConfig } from '@tensorflow/tfjs-core' ; import { MathBackendCPU } from '../backend_cpu' ; export const dilation2DBackpropFilterConfig = { kernelName : Dilation2DBackpropFilter , backendName : 'cpu' , kernelFunc : ( { inputs , backend , attrs } ) => { const { x , filter , dy } = inputs as { x : Tensor4D ; filter : Tensor3D ; dy : Tensor4D ; } ; const { strides , pad , dilations } = attrs as { } as Dilation2DAttrs ; const cpuBackend = backend as MathBackendCPU ; const $x = util . toNestedArray ( x . shape , cpuBackend . data . get ( x . dataId ) . values as TypedArray ) as number [ ] [ ] [ ] [ ] ; const $filter = util . toNestedArray ( filter . shape , cpuBackend . data . get ( filter . dataId ) . values as TypedArray ) as number [ ] [ ] [ ] ; const { batchSize , inHeight , inWidth , inChannels , outHeight , outWidth , padInfo , strideHeight , strideWidth , filterHeight , filterWidth , dilationHeight , dilationWidth , outShape } = backend_util . computeDilation2DInfo ( x . shape as [ number , number , number , number ] , filter . shape as [ number , number , number ] , strides , pad , 'NHWC' , dilations ) ; util . assert ( dy . rank === outShape . length , ( ) => `Error in ${ Dilation2DBackpropFilter }, dy ` + `must have the same rank as output ${ outShape . length }, but got ` + `${ dy . rank }` ) ; const $dy = util . toNestedArray ( outShape , cpuBackend . data . get ( dy . dataId ) . values as TypedArray ) as number [ ] [ ] [ ] [ ] ; const gradients = util . makeZerosNestedTypedArray ( filter . shape , filter . dtype ) as number [ ] [ ] [ ] ; for ( let b = 0 ; b < batchSize ; ++ b ) { for ( let hOut = 0 ; hOut < outHeight ; ++ hOut ) { const hBeg = hOut * strideHeight - padInfo . top ; for ( let wOut = 0 ; wOut < outWidth ; ++ wOut ) { const wBeg = wOut * strideWidth - padInfo . left ; for ( let d = 0 ; d < inChannels ; ++ d ) { let curVal = Number . MIN_SAFE_INTEGER ; let hMax = 0 ; let wMax = 0 ; for ( let h = 0 ; h < filterHeight ; ++ h ) { const hIn = hBeg + h * dilationHeight ; if ( hIn >= 0 && hIn < inHeight ) { for ( let w = 0 ; w < filterWidth ; ++ w ) { const wIn = wBeg + w * dilationWidth ; if ( wIn >= 0 && wIn < inWidth ) { const val = $x [ b ] [ hIn ] [ wIn ] [ d ] + $filter [ h ] [ w ] [ d ] ; if ( val > curVal ) { curVal = val ; hMax = h ; wMax = w ; } } } } } gradients [ hMax ] [ wMax ] [ d ] += $dy [ b ] [ hOut ] [ wOut ] [ d ] ; } } } } const dataId = cpuBackend . write ( util . toTypedArray ( gradients , x . dtype ) , filter . shape , filter . dtype ) ; return { dataId , shape : filter . shape , dtype : filter . dtype } ; } } ;