{
  "schemaVersion": 1,
  "slug": "small-cnn",
  "title": "From pixels to features",
  "className": "SmallCNN",
  "question": "Where does an image become a classifier input?",
  "description": "Watch the spatial dimensions shrink, unfold the feature maps, and connect the resulting width to a linear head.",
  "category": "Tensor shapes",
  "tags": [
    "CNN",
    "Pooling",
    "Flatten"
  ],
  "curator": "TensorViz",
  "attribution": "Original TensorViz teaching example. PyTorch provides the underlying operators.",
  "license": "No separate redistribution license has been declared for these project examples.",
  "limitations": "An untrained 32 × 32 image classifier. The 1,024-feature head is specific to this input size. Validation covers one CPU forward; it does not measure classification accuracy.",
  "openingStep": "flatten",
  "provenance": {
    "capturedAt": "2026-09-17T01:50:56.417230+00:00",
    "productRevision": "cf0ab1c9c58c1dc640235b742fa032cade00b43c",
    "sourceSha256": "72f6cc2f4436625415acf24ab27f94a83bd1cbe6b4977466ac6cea1b0f0ebf83",
    "python": "3.13.13",
    "torch": "2.7.1",
    "execution": {
      "inputs": {
        "args": [
          {
            "shape": [
              1,
              3,
              32,
              32
            ],
            "dtype": "float32",
            "fill": "ones"
          }
        ]
      },
      "device": "cpu",
      "mode": "eval",
      "seed": 0,
      "deterministic": true
    },
    "outcome": "passed",
    "outputShape": [
      1,
      10
    ],
    "method": "TensorViz multifile projection and isolated execution worker",
    "scope": "One CPU forward with float32 ones; untrained example, no accuracy claim. Installed VS Code workflow not separately verified for this example."
  },
  "layers": [
    {
      "id": "input",
      "label": "input",
      "op": "Input",
      "kind": "input",
      "parent": null,
      "params": {
        "shape": "1,3,32,32"
      }
    },
    {
      "id": "features",
      "label": "features",
      "op": "Module",
      "kind": "module",
      "parent": null,
      "params": {},
      "source": {
        "line": 29,
        "endLine": 29
      }
    },
    {
      "id": "flatten",
      "label": "flatten",
      "op": "Flatten",
      "kind": "layer",
      "parent": null,
      "params": {},
      "source": {
        "line": 30,
        "endLine": 30
      }
    },
    {
      "id": "head",
      "label": "head",
      "op": "Linear",
      "kind": "layer",
      "parent": null,
      "params": {
        "in_features": 1024,
        "out_features": 10
      },
      "source": {
        "line": 31,
        "endLine": 31
      }
    },
    {
      "id": "output",
      "label": "output",
      "op": "Output",
      "kind": "output",
      "parent": null,
      "params": {}
    },
    {
      "id": "features.conv1",
      "label": "features.conv1",
      "op": "Conv2d",
      "kind": "layer",
      "parent": "features",
      "params": {
        "in_channels": 3,
        "out_channels": 8,
        "kernel_size": 3,
        "padding": 1
      },
      "source": {
        "line": 9,
        "endLine": 9
      }
    },
    {
      "id": "features.relu1",
      "label": "features.relu1",
      "op": "ReLU",
      "kind": "layer",
      "parent": "features",
      "params": {},
      "source": {
        "line": 10,
        "endLine": 10
      }
    },
    {
      "id": "features.pool1",
      "label": "features.pool1",
      "op": "MaxPool2d",
      "kind": "layer",
      "parent": "features",
      "params": {
        "kernel_size": 2
      },
      "source": {
        "line": 11,
        "endLine": 11
      }
    },
    {
      "id": "features.conv2",
      "label": "features.conv2",
      "op": "Conv2d",
      "kind": "layer",
      "parent": "features",
      "params": {
        "in_channels": 8,
        "out_channels": 16,
        "kernel_size": 3,
        "padding": 1
      },
      "source": {
        "line": 12,
        "endLine": 12
      }
    },
    {
      "id": "features.relu2",
      "label": "features.relu2",
      "op": "ReLU",
      "kind": "layer",
      "parent": "features",
      "params": {},
      "source": {
        "line": 13,
        "endLine": 13
      }
    },
    {
      "id": "features.pool2",
      "label": "features.pool2",
      "op": "MaxPool2d",
      "kind": "layer",
      "parent": "features",
      "params": {
        "kernel_size": 2
      },
      "source": {
        "line": 14,
        "endLine": 14
      }
    }
  ],
  "connections": [
    {
      "id": "edge-1",
      "source": "features.conv1",
      "target": "features.relu1",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-2",
      "source": "features.relu1",
      "target": "features.pool1",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-3",
      "source": "features.pool1",
      "target": "features.conv2",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-4",
      "source": "features.conv2",
      "target": "features.relu2",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-5",
      "source": "features.relu2",
      "target": "features.pool2",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-6",
      "source": "input",
      "target": "features.conv1",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-7",
      "source": "input",
      "target": "features",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-8",
      "source": "features.pool2",
      "target": "flatten",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-9",
      "source": "features",
      "target": "flatten",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-10",
      "source": "flatten",
      "target": "head",
      "sourcePort": null,
      "targetPort": null
    },
    {
      "id": "edge-11",
      "source": "head",
      "target": "output",
      "sourcePort": null,
      "targetPort": null
    }
  ],
  "steps": [
    {
      "id": "local-features",
      "target": "features.conv1",
      "title": "Look at a small neighborhood",
      "note": "A 3 × 3 convolution turns three color channels into eight feature maps. Padding keeps the input's 32 × 32 spatial size."
    },
    {
      "id": "downsample",
      "target": "features.pool2",
      "title": "Trade spatial size for features",
      "note": "Two 2 × 2 pooling layers reduce 32 × 32 to 16 × 16, then 8 × 8. The second convolution supplies 16 channels."
    },
    {
      "id": "flatten",
      "target": "flatten",
      "title": "Turn the maps into one vector",
      "note": "Flatten preserves the batch dimension and joins 16 × 8 × 8 values into 1,024 features per image. This is the bridge from spatial processing to classification."
    },
    {
      "id": "classifier",
      "target": "head",
      "title": "Connect the dimensions",
      "note": "The linear head accepts those 1,024 features and returns 10 outputs. Changing the input image size would also change the required flattened width."
    }
  ],
  "revision": "8b970fa1941344b3",
  "files": {
    "graph.tensorviz.json": {
      "url": "/models/small-cnn/8b970fa1941344b3/graph.tensorviz.json",
      "sha256": "588369bfadfe295401d97b564417cb5709c6c17f7ae307f9fc2265933ea31956",
      "bytes": 33903
    },
    "model.py": {
      "url": "/models/small-cnn/8b970fa1941344b3/model.py",
      "sha256": "72f6cc2f4436625415acf24ab27f94a83bd1cbe6b4977466ac6cea1b0f0ebf83",
      "bytes": 1200
    },
    "run.py": {
      "url": "/models/small-cnn/8b970fa1941344b3/run.py",
      "sha256": "2756945254c8e00f5c5b85bd6fb86c6ad84803304b5eb4e9f4071c17b0a99b94",
      "bytes": 400
    },
    "requirements.txt": {
      "url": "/models/small-cnn/8b970fa1941344b3/requirements.txt",
      "sha256": "edb86016b42cb3cc6cdc0c490aab929d3bb098ced4515394f0b55766033e0daf",
      "bytes": 91
    },
    "preview.svg": {
      "url": "/models/small-cnn/8b970fa1941344b3/preview.svg",
      "sha256": "cb88522d3fba3c6140da4a4f5443ebe61b608f8ec0f9ada6325fa04f70eb5da6",
      "bytes": 2238
    }
  }
}
