MCPcopy Create free account
hub / github.com/tensorflow/tfjs / computeOutputShape

Function computeOutputShape

tfjs-layers/src/engine/container.ts:783–859  ·  view source on GitHub ↗

* Computes the output shape of the layer. * * Assumes that the layer will be built to match that input shape provided. * * @param inputShape A shape (tuple of integers) or a list of shape tuples * (one per output tensor of the layer). Shape tuples can include null for * free di

(inputShape: Shape|Shape[])

Source from the content-addressed store, hash-verified

781 * free dimensions, instead of an integer.
782 */
783 override computeOutputShape(inputShape: Shape|Shape[]): Shape|Shape[] {
784 const inputShapes = types_utils.normalizeShapeList(inputShape);
785 if (inputShapes.length !== this.inputLayers.length) {
786 throw new ValueError(
787 `Invalid inputShape argument ${inputShape}: ` +
788 `model has ${this.inputLayers.length} tensor inputs.`);
789 }
790
791 // TODO(michaelterry): Add caching
792 const layersToOutputShapes: {[shapeKey: string]: Shape} = {};
793 for (let i = 0; i < inputShapes.length; i++) {
794 const layer = this.inputLayers[i];
795 const inputShape = inputShapes[i];
796 // It's an input layer: computeOutputShape is identity,
797 // and there is only one node and one tensor output.
798 const shapeKey = layer.name + '_0_0';
799 layersToOutputShapes[shapeKey] = inputShape;
800 }
801
802 const depthKeys = Object.keys(this.nodesByDepth)
803 .map(x => parseInt(x, 10))
804 .sort(generic_utils.reverseNumberCompare);
805 // Iterate over nodes, by depth level.
806 if (depthKeys.length > 1) {
807 for (const depth of depthKeys) {
808 const nodes = this.nodesByDepth[depth];
809 for (const node of nodes) {
810 // This is always a single layer, never a list.
811 const layer = node.outboundLayer;
812 if (this.inputLayers.map(x => x.id).indexOf(layer.id) !== -1) {
813 // We've already covered the input layers a few lines above.
814 continue;
815 }
816 // Potentially redundant list, same size of node.inputTensors.
817 const inputShapes: Shape[] = [];
818 for (let j = 0; j < node.inboundLayers.length; j++) {
819 const inboundLayer = node.inboundLayers[j];
820 const nodeIndex = node.nodeIndices[j];
821 const tensorIndex = node.tensorIndices[j];
822 const shapeKey = `${inboundLayer.name}_${nodeIndex}_${tensorIndex}`;
823 const inputShape = layersToOutputShapes[shapeKey];
824 inputShapes.push(inputShape);
825 }
826
827 const outputShape = layer.computeOutputShape(
828 generic_utils.singletonOrArray(inputShapes));
829
830 const outputShapes = types_utils.normalizeShapeList(outputShape);
831 const nodeIndex = layer.inboundNodes.indexOf(node);
832 for (let j = 0; j < outputShapes.length; j++) {
833 const shapeKey = `${layer.name}_${nodeIndex}_${j}`;
834 layersToOutputShapes[shapeKey] = outputShapes[j];
835 }
836 }
837 }
838 }
839
840 // Read final output shapes from layersToOutputShapes.

Callers

nothing calls this directly

Calls 2

pushMethod · 0.45
computeOutputShapeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…