← All courses ← Course home

Lesson 06 of 07

Training must give conversion a model it can use

Training sits before conversion, and conversion has limits. The dataset, the model design, the device you train on, and the saved weights all decide whether the runtime gets a stable graph.

Agent brief (llms.md)

Environment setup

Use Python 3.11 or newer on macOS. uv manages the project and virtual environment. The device check picks Apple Silicon MPS when it is available, and CPU if it is not.

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

Save the lesson code as train.py or the named script for this lesson. uv run uses the project environment, so you do not need a global pip install.

It is tempting to treat training as a side project and conversion as the real engineering. In this stack, conversion starts asking questions that training must answer: what is the input shape, which classes mean what, which operations appear in the graph, and can the weights be loaded on the Mac that does the export?

Start from the exported shape

Conversion needsfixed NCHW input
Model must giveClothingCNN shape
Training must giveFashion-MNIST transform

ToTensor() gives one grayscale channel with float values in 0...1. The small two-convolution, two-linear-layer ClothingCNN keeps the graph easy to follow and the exported input at [1, 1, 28, 28]. A fixed example tensor makes torch.export record the real interface. It does not hide a shape change until the app runs.

Keep the Mac path simple

Train with Apple Silicon MPS when it is available, or CPU if it is not. There is no CUDA step in this course. Before export, move the model to CPU, switch to evaluation mode, and save weights that the conversion environment can load. Do not save a device-specific file.

device = "mps" if torch.backends.mps.is_available() else "cpu"
model = ClothingCNN().to(device)
# train on Fashion-MNIST with ToTensor() and CrossEntropyLoss
# ...
model = model.to("cpu").eval()
torch.save(model.state_dict(), "clothing.pt")

This is a device-policy sketch. Use the complete training recipe in the original course. Keep the saved file portable. Never write a CUDA-only load path for an Apple-silicon Core AI project.

Class order is part of the graph's meaning

Datasetten ordered classes
Weightslogit positions
Assetlogits [1,10]
UIclothing label

The ten output positions only become labels through the fixed Fashion-MNIST order: T-shirt/top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag, Ankle boot. If the SwiftUI app changes the order, the runtime still succeeds, but the app shows the wrong label.

What training must give the layer below

Now you have the whole chain, so you can rebuild it from the bottom up. Meet the original pipeline again, then open lesson 01 of the original course with the reversed map in mind.

Key concepts

  • Conversion asks questions training must answer: shape, class order, ops, and portable weights.
  • Fashion-MNIST ToTensor() gives one grayscale channel, float32 0-1.
  • Train on MPS when available, else CPU. No CUDA. Save CPU weights in clothing.pt.
  • The ten output positions map to Fashion-MNIST order through training, conversion, and UI.

Takeaways

  • Move the model to CPU, call eval(), then save weights the export environment can load.
  • Class order is part of the graph's meaning, not a SwiftUI decoration.
  • Training preprocessing must match the app's float32 NCHW 0-1 tensor.