(inputs: Tensor|Tensor[], kwargs: Kwargs)
| 569 | } |
| 570 | |
| 571 | override call(inputs: Tensor|Tensor[], kwargs: Kwargs): Tensor|Tensor[] { |
| 572 | const input = getExactlyOneTensor(inputs); |
| 573 | const inputShape = input.shape; |
| 574 | const nDims = inputShape.length; |
| 575 | |
| 576 | return tidy(() => { |
| 577 | const keepDims = true; |
| 578 | let {mean, variance} = moments(input, this.axis, keepDims); |
| 579 | const broadcastShape = generic_utils.pyListRepeat(1, nDims); |
| 580 | for (const dim of this.axis as number[]) { |
| 581 | broadcastShape[dim] = inputShape[dim]; |
| 582 | } |
| 583 | |
| 584 | const broadcast = (v: Tensor) => { |
| 585 | if (v != null && v.shape.length !== nDims) { |
| 586 | return tfc.reshape(v, broadcastShape); |
| 587 | } else { |
| 588 | return v; |
| 589 | } |
| 590 | }; |
| 591 | |
| 592 | let scale = this.scale ? broadcast(this.gamma.read()) : null; |
| 593 | let offset = this.center ? broadcast(this.beta.read()) : null; |
| 594 | |
| 595 | // TODO(https://github.com/tensorflow/tfjs/issues/2120): The tiling below |
| 596 | // is a workaround for the limitation of core's batchNormalization?d don't |
| 597 | // support broadcasting in their gradients. In addition, the tiling is |
| 598 | // necessary to ensure correctness on the browser CPU backend regardless |
| 599 | // of forward or backward computation. Remove this workaround once the |
| 600 | // limitation is addressed. See . |
| 601 | const momentsTiling: number[] = []; |
| 602 | const scaleOffsetTiling: number[] = []; |
| 603 | for (let i = 0; i < nDims; ++i) { |
| 604 | if ((this.axis as number[]).indexOf(i) !== -1) { |
| 605 | momentsTiling.push(inputShape[i]); |
| 606 | scaleOffsetTiling.push(1); |
| 607 | } else { |
| 608 | momentsTiling.push(1); |
| 609 | scaleOffsetTiling.push(inputShape[i]); |
| 610 | } |
| 611 | } |
| 612 | mean = tfc.tile(mean, momentsTiling); |
| 613 | variance = tfc.tile(variance, momentsTiling); |
| 614 | if (scale != null) { |
| 615 | scale = tfc.tile(scale, scaleOffsetTiling); |
| 616 | } |
| 617 | if (offset != null) { |
| 618 | offset = tfc.tile(offset, scaleOffsetTiling); |
| 619 | } |
| 620 | |
| 621 | return batchNormalization( |
| 622 | input, mean, variance, offset, scale, this.epsilon); |
| 623 | }); |
| 624 | } |
| 625 | |
| 626 | override getConfig(): serialization.ConfigDict { |
| 627 | const config: serialization.ConfigDict = { |
nothing calls this directly
no test coverage detected