AI Development Framework · Topic 2 of 2

PyTorch and AI Application Development

Learn PyTorch nn.Module, losses, optimizers, DataLoader, the training loop, evaluation and saving, and the AI application development process for H13-311.

  • 5 min
In a nutshell
  • Models inherit from nn.Module; layers go in __init__, computation in forward().
  • Training order per batch: zero_grad(), forward pass, loss, backward(), step().
  • DataLoader batches and shuffles a Dataset; one pass over all data is an epoch.

What it is

PyTorch is an open source deep learning framework in Python, created by Meta and now hosted by the PyTorch Foundation. It uses dynamic computational graphs and is the framework used throughout the HCIA-AI V4.0 course.

The AI application development process is the sequence of steps that turns a business need into a working model: define the problem, prepare data, build and train a model, evaluate it, deploy it and keep improving it.

Requirement analysisData preparationModel buildingTrainingEvaluationDeploymentMonitoring and iteration

How it works

Main PyTorch modules

ModuleRoleCommon items
torchTensors and mathtorch.tensor, torch.randn, torch.matmul
torch.autogradAutomatic differentiationrequires_grad, backward()
torch.nnLayers, activations, lossesnn.Module, nn.Linear, nn.Conv2d, nn.ReLU, nn.CrossEntropyLoss
torch.optimOptimizersoptim.SGD, optim.Adam
torch.utils.dataData loadingDataset, DataLoader

Every model is a class that inherits from nn.Module. Layers are created in __init__, and the computation is written in forward(). You normally do not call forward() directly; you call the model, model(x), which also runs any registered hooks.

A complete training loop

This network classifies 28 x 28 handwritten digits (flattened to 784 values) into 10 classes.

import torch
from torch import nn
from torch.utils.data import DataLoader

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        return self.fc2(torch.relu(self.fc1(x)))

model = Net()
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
loader = DataLoader(train_set, batch_size=64, shuffle=True)

model.train()
for images, labels in loader:
    optimizer.zero_grad()                        # clear old gradients
    loss = loss_fn(model(images.view(-1, 784)), labels)
    loss.backward()                              # compute gradients
    optimizer.step()                             # update weights

train_set is any Dataset; the DataLoader splits it into shuffled batches of 64. One full pass over the data is an epoch, and real training repeats this loop for several epochs.

Batch from DataLoaderForward passmodel of imagesLossCrossEntropyLossloss.backwardgradientsoptimizer.stepnew weights

Why the order matters

PyTorch accumulates gradients: each backward() adds to the existing .grad values. If you skip optimizer.zero_grad(), the gradients of earlier batches pile up and the updates are wrong.

backward() must come before step(), because the optimizer needs gradients to update the weights.

Evaluation, devices and saving

TaskCodeWhy
Switch to evaluationmodel.eval()Dropout is turned off and batch normalization uses its stored statistics
Stop gradient trackingwith torch.no_grad():Saves memory and time during inference
Use a GPUmodel.to("cuda") and x.to("cuda")Model and data must be on the same device
Save weightstorch.save(model.state_dict(), "model.pth")Stores the learned parameters
Load weightsmodel.load_state_dict(torch.load("model.pth"))Restores them into a model of the same structure
model.eval()
with torch.no_grad():
    preds = model(test_images.view(-1, 784)).argmax(dim=1)

On Huawei Ascend NPUs, PyTorch runs through the torch_npu adapter (Ascend Extension for PyTorch), so the same training code can target Ascend hardware.

The AI application development process

StepWhat happens
Requirement analysisDefine the business problem, the task type (classification, regression, detection) and the success metric
Data preparationCollect, clean and label data; split it into training, validation and test sets
Model buildingChoose or design an architecture, or start from a pretrained model
TrainingRun the training loop and tune hyperparameters such as learning rate and batch size on the validation set
EvaluationMeasure the model on the untouched test set with metrics such as accuracy, precision and recall
DeploymentServe the model in the cloud, at the edge or on a device, often after export or compression
Monitoring and iterationWatch real performance, collect new data and retrain when accuracy drops

The process is a loop, not a straight line. Poor evaluation results send you back to the data or the model.

A worked example

Count the trainable parameters of Net above. An nn.Linear(in, out) layer has in x out weights plus out biases.

  • fc1: 784 x 128 + 128 = 100,352 + 128 = 100,480
  • fc2: 128 x 10 + 10 = 1,280 + 10 = 1,290
  • Total: 100,480 + 1,290 = 101,770

PyTorch confirms it with sum(p.numel() for p in model.parameters()).

How the exam asks about this

  • "Which base class must a custom PyTorch model inherit from?" → torch.nn.Module.
  • "Which call clears the gradients left by the previous batch?" → optimizer.zero_grad().
  • "Which dataset is used for the final, unbiased estimate of model performance?" → The test set.

What to remember for the exam

  • Models inherit from nn.Module; layers go in __init__, computation in forward().
  • Training order per batch: zero_grad(), forward pass, loss, backward(), step().
  • DataLoader batches and shuffles a Dataset; one pass over all data is an epoch.
  • For inference use model.eval() and torch.no_grad().
  • Process: requirements, data, model, training, evaluation, deployment, monitoring and iteration.
Watch out

nn.CrossEntropyLoss expects raw scores (logits) and applies log softmax internally. Adding your own softmax layer before it is a classic bug: the loss is computed on doubly normalized scores and training suffers.

Common mistakes

Thinking model.eval() stops gradient computation. It only changes the behavior of layers such as dropout and batch normalization. Gradient tracking is turned off with torch.no_grad() (or torch.inference_mode()).

Tuning on the test set. Hyperparameters are chosen with the validation set. If the test set guides your choices, its score is no longer an honest estimate.

Treating deployment as the last step. Data in production changes over time. Models must be monitored and retrained, so the process loops back to data preparation.

Check yourself

  • What happens if optimizer.zero_grad() is never called?

    Gradients accumulate across batches, because backward() adds to existing gradients, so each update uses the wrong values.

  • How many parameters does nn.Linear(100, 10) have?

    1,010: 100 x 10 = 1,000 weights plus 10 biases.

  • Why is the validation set separate from the test set?

    The validation set is used to tune hyperparameters and choose models, while the test set is kept untouched for the final unbiased performance estimate.

Topic 2 of 2 in AI Development Framework

Test yourself on AI Development Framework

The full Huawei HCIA-AI H13-311 question bank has 600 questions, with timed practice exams and an explanation for every answer.

This study guide is independent and is not affiliated with, endorsed by, or sponsored by Huawei. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.