---
name: Build a Fashion-MNIST clothing classifier with PyTorch and Core AI
description: >-
  A full Mac guide for training ClothingCNN on Fashion-MNIST, converting it
  with coreai-torch into clothing.aimodel, running it through Core AI in Xcode,
  showing the top label in SwiftUI, and measuring the real-device path.
---
# Build the clothing classifier end to end

Use this guide to build the full project on a Mac. Train with Apple Silicon MPS when you have it, and CPU when you do not. **Do not use CUDA**. This course uses Apple's **Core AI**, not Core ML. Keep both model files: `clothing.pt` is the PyTorch weights file, and `clothing.aimodel` is the portable Core AI file you add to Xcode. The app should show the top Fashion-MNIST clothing label in SwiftUI. Then inspect the finished run with the Xcode Core AI gauge and the Core AI Instruments template.

## Fixed contract

These rules must stay the same from training to the app.

- Training transform is `ToTensor()`: grayscale float32 pixels in 0–1.
- Model input is NCHW `[1, 1, 28, 28]` float32, named `image`.
- Model output is `[1, 10]` float32 logits, named `logits`; apply softmax only for display.
- Class order is: `T-shirt/top`, `Trouser`, `Pullover`, `Dress`, `Coat`, `Sandal`, `Shirt`, `Sneaker`, `Bag`, `Ankle boot`.
- Keep the `ClothingCNN` architecture and `main` function name from the lessons.
- Prepare (load and specialise) the model once when the app starts, then reuse the loaded function for every image.

## Ordered build map

1. [The pipeline: human lesson](01-the-pipeline.html) · [agent brief](01-the-pipeline.llms.md)
2. [Train ClothingCNN on Fashion-MNIST: human lesson](02-pytorch-from-scratch.html) · [agent brief](02-pytorch-from-scratch.llms.md)
3. [Convert with coreai-torch: human lesson](03-convert-with-coreai-torch.html) · [agent brief](03-convert-with-coreai-torch.llms.md)
4. [Add the model to Xcode and run NDArray: human lesson](04-xcode-and-core-ai.html) · [agent brief](04-xcode-and-core-ai.llms.md)
5. [Build the SwiftUI clothing app: human lesson](05-swiftui-clothing-app.html) · [agent brief](05-swiftui-clothing-app.llms.md)
6. [Profile in Xcode and Instruments](06-profile-in-xcode.html) · [agent brief](06-profile-in-xcode.llms.md)
7. [Evaluate the clothing classifier](07-evaluate-classifier.html) · [agent brief](07-evaluate-classifier.llms.md)
8. [Run the end-to-end checklist](08-end-to-end-checklist.html) · [agent brief](08-end-to-end-checklist.llms.md)

## End-to-end execution

1. On the Mac, create a Python environment with compatible `torch`, `torchvision`, and `coreai-torch` packages. Confirm `torch.backends.mps.is_available()` and choose `mps` or `cpu`. Never add a CUDA dependency or device path.
2. Download Fashion-MNIST with `torchvision.datasets.FashionMNIST`, use `transforms.ToTensor()`, define the two-convolution/two-linear-layer `ClothingCNN`, and train with cross-entropy. Evaluate a test sample, move the model to CPU, and save `clothing.pt`.
3. Reload `clothing.pt` into the same `ClothingCNN`, export a CPU example `torch.zeros(1, 1, 28, 28, dtype=torch.float32)` with `torch.export.export`, then run `run_decompositions(get_decomp_table())` before conversion.
4. Call `TorchConverter().add_exported_program(..., input_names=["image"], output_names=["logits"]).to_coreai()`, optimise, and save `clothing.aimodel`. Inspect its function and tensor descriptors.
5. In Xcode 27, install the Metal Toolchain, add `clothing.aimodel` to the target, load `AIModel`, load function `main`, and construct an `NDArray` matching the fixed contract. Confirm names and signatures in the model viewer and installed SDK docs.
6. Build the SwiftUI app with `PhotosPicker` plus an optional bundled `fashion-sample`. Decode the image, resize/draw to 28×28 grayscale, scale bytes to float32 0–1, run under input key `image`, read `logits`, softmax/argmax, and display the label in the fixed class order.
7. Put preparation in `.task` or app setup rather than the picker callback. Run the same bundled sample first, then a picked photo. Use a real device for timing, the Core AI debug gauge for load/specialisation, and Instruments' Core AI template for later inference runs.
8. Evaluate labels separately from Instruments. Print held-out Fashion-MNIST accuracy and a confusion matrix from `ClothingCNN`, open-code misclassified photos (write short notes, then group them into a few problem types), compare Mac versus Core AI top labels in JSONL, and apply a yes/no top-label-acceptable rule.

## Key concepts

- Train `ClothingCNN` on Fashion-MNIST on a Mac with MPS or CPU. Never CUDA.
- Save `clothing.pt`, export, then convert with `coreai-torch` to `clothing.aimodel`.
- Fixed contract: input `image` is NCHW `[1, 1, 28, 28]` float32. Output `logits` is `[1, 10]` float32.
- Xcode 27 loads function `main`. Prepare once. Softmax is for display only.

## Takeaways

- You can train, convert, and show a clothing label in a SwiftUI Core AI app.
- You can profile load, specialisation, and inference on a real device.
- You can check held-out accuracy, Mac versus Core AI labels, and a yes or no top-label rule.

## Completion standard

You are done when the source weights `clothing.pt` and the portable file `clothing.aimodel` both exist, the Xcode target builds, and a sample shows a clothing label in SwiftUI. Check the tensor names, shapes, types, and the fixed class order. Load the model once. On a real device, the first setup should look different from later inference. Lesson 07 should record held-out accuracy, open-coded mistakes, and matching Mac versus Core AI labels. Use the [final checklist brief](08-end-to-end-checklist.llms.md) before you call the project complete. Every human lesson HTML has **Key concepts** and **Takeaways** sections before lesson-nav. The course home has the same two headings for the whole course.

## Environment setup

Use macOS with Python 3.11+ and `uv`:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
mkdir -p clothing-coreai && cd clothing-coreai
uv init --python 3.11
uv venv
uv add torch torchvision coreai-torch
uv run python -c "import torch, torchvision; print(torch.__version__, torchvision.__version__); print('MPS:', torch.backends.mps.is_available())"
uv run python train.py
```

Run lesson scripts with `uv run`. Prefer MPS on Apple silicon. Use CPU if MPS is missing. Do not add CUDA.

## Environment setup

Use Xcode 27 on macOS. Create an iOS or macOS SwiftUI App target, add the exported `.aimodel` to the target's model/resources build phase, add the **Core AI** framework under Frameworks, Libraries, and Embedded Content, and install the **Metal Toolchain** in Xcode Settings > Components. Confirm the installed toolchain with:

```bash
xcode-select --install
xcodebuild -version
```

Build the bundled model once before you add UI. Core AI and `NDArray` names can change between SDK versions, so check the exact names in the Xcode docs you have installed.
