Machine Learning Academy · 课时

torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT

您将加载在 ImageNet 上预训练的 ResNet-50,检查其架构,并对新图像进行推理,以验证预先学习的表示。

第 1 / 4 课12 个步骤

torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Why Use Pre-trained Models?

Training a deep neural network on ImageNet from scratch requires millions of labelled images and weeks of GPU compute. Pre-trained models have already learned general visual features — edges, textures, shapes, and high-level object parts — from this enormous dataset.

By reusing these weights, you benefit from the learning done on 1.2 million images without paying the training cost. This is the core idea of transfer learning: features learned on one large task transfer well to related smaller tasks. torchvision.models provides dozens of pre-trained architectures ready to download and use.

import torchvision.models as models

# List some available pre-trained models
print(dir(models))  # Shows resnet50, efficientnet_b0, vit_b_16, etc.

# Loading weights pre-trained on ImageNet-1k
resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)
print('ResNet-50 loaded, parameters:', sum(p.numel() for p in resnet.parameters()))

ResNet-50: Architecture Overview

ResNet-50 (Residual Network with 50 layers) introduced skip connections that add the input of a block directly to its output: output = F(x) + x. This allows gradients to flow directly through the addition, enabling training of very deep networks without vanishing gradients.

ResNet-50 has approximately 25 million parameters and consists of: one initial 7×7 convolutional layer, max pooling, four residual blocks (layer1–layer4), and a global average pooling layer followed by a 1000-class fully connected head for ImageNet classification. The final fc layer is what we replace for custom tasks.

import torchvision.models as models
import torch

resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)
print(resnet)  # Prints the full architecture

# Key layers
print('Final FC layer:', resnet.fc)  # Linear(2048, 1000)
print('Layer4 output channels:', 2048)  # Feature dimension before FC

Running Inference with ResNet-50

Before running inference, inputs must match the preprocessing used during ImageNet training: resize to at least 224×224, normalise with ImageNet mean and standard deviation. The torchvision.transforms API handles this. Always call model.eval() before inference to disable dropout and batch normalisation training mode.

The model outputs 1000 logits, one per ImageNet class. We apply softmax to get probabilities and pick the top-k classes. torchvision.models now includes category names in the weights metadata, eliminating the need for a separate labels file.

import torch
from torchvision import transforms
from PIL import Image
import torchvision.models as models

weights = models.ResNet50_Weights.IMAGENET1K_V1
resnet = models.resnet50(weights=weights)
resnet.eval()

# Preprocessing transforms from the weights metadata
preprocess = weights.transforms()

# Load and preprocess an image
img = Image.open('cat.jpg')
tensor = preprocess(img).unsqueeze(0)  # Add batch dimension

with torch.no_grad():
    logits = resnet(tensor)
    probs = torch.softmax(logits, dim=1)
    top5 = torch.topk(probs, 5)
print('Top-5 probabilities:', top5.values)

EfficientNet: Compound Scaling

EfficientNet (2019) introduced compound scaling: systematically scaling network width, depth, and input resolution together using a single compound coefficient. Instead of arbitrarily making networks wider or deeper, EfficientNet balances all three dimensions for optimal accuracy-efficiency trade-offs.

The EfficientNet family ranges from efficientnet_b0 (5M parameters) to efficientnet_b7 (66M parameters). EfficientNet-B0 achieves comparable accuracy to ResNet-50 while using 8× fewer parameters and 6× fewer FLOPs, making it ideal for mobile and edge deployment. PyTorch provides all eight variants.

import torchvision.models as models
import torch

# EfficientNet-B0: lightweight but accurate
eff_b0 = models.efficientnet_b0(weights=models.EfficientNet_B0_Weights.IMAGENET1K_V1)
print('EfficientNet-B0 params:', sum(p.numel() for p in eff_b0.parameters()))
print('EfficientNet-B0 classifier:', eff_b0.classifier)

# Compare with ResNet-50
resnet50 = models.resnet50(weights=None)  # No weights to count params only
print('ResNet-50 params:', sum(p.numel() for p in resnet50.parameters()))

Vision Transformer (ViT): Attention Without Convolutions

Vision Transformers (ViT) (2020) apply the transformer architecture directly to images, without any convolution. The image is split into a grid of fixed-size patches (e.g., 16×16 pixels), each flattened and projected to an embedding vector. These patch embeddings are treated like word tokens in NLP.

A CLS (classification) token is prepended to the patch sequence. After passing through multiple transformer encoder blocks with self-attention, the CLS token's output is used for classification. ViT requires large training datasets to outperform CNNs, but pre-trained ViT models from torchvision bring this power to your tasks immediately.

import torchvision.models as models
import torch

# ViT-B/16: Base model with 16x16 patches
vit = models.vit_b_16(weights=models.ViT_B_16_Weights.IMAGENET1K_V1)
print('ViT-B/16 params:', sum(p.numel() for p in vit.parameters()))
print('ViT patch size: 16x16 pixels')
print('ViT sequence length for 224x224 image:', (224 // 16) ** 2 + 1, '(196 patches + 1 CLS token)')
print('ViT head:', vit.heads)  # Linear(768, 1000)

Comparing ResNet, EfficientNet, and ViT

Choosing among these architectures depends on your constraints and task. ResNet-50 is the reliable default: well understood, strong baseline, many tutorials and implementations. EfficientNet-B0/B2 wins when inference speed and model size matter — mobile apps, real-time systems, or edge hardware.

ViT excels on large-scale tasks and benefits from self-supervised pre-training (DINO, CLIP). It requires more compute and memory than CNNs of similar accuracy. For most custom image classification tasks with moderate-sized datasets, start with EfficientNet-B2 or ResNet-50, then try ViT if you have the resources to fine-tune it.

# Rough comparison on ImageNet top-1 accuracy
comparison = {
    'ResNet-50':       {'params': '25M', 'top1': '76.1%', 'year': 2015},
    'EfficientNet-B0': {'params': '5M',  'top1': '77.7%', 'year': 2019},
    'EfficientNet-B4': {'params': '19M', 'top1': '83.4%', 'year': 2019},
    'ViT-B/16':        {'params': '86M', 'top1': '81.1%', 'year': 2020},
    'ViT-L/16':        {'params': '307M','top1': '85.1%', 'year': 2020},
}
for name, info in comparison.items():
    print(f'{name}: {info["params"]} params, {info["top1"]} top-1')

Inspecting Model Internals

Before modifying a pre-trained model for your task, inspect its architecture to understand which layers to replace. Use print(model) to see the layer tree, and named_modules() or named_children() to iterate programmatically.

The key insight: every torchvision model ends with a classification head sized for 1000 ImageNet classes. To adapt the model to your task with num_classes different from 1000, you replace this final layer. The feature extractor (everything before the head) retains ImageNet-learned features.

import torchvision.models as models

resnet = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)

# Find the names of top-level children
for name, module in resnet.named_children():
    print(name, '->', type(module).__name__)

# Output:
# conv1 -> Conv2d
# bn1 -> BatchNorm2d
# relu -> ReLU
# maxpool -> MaxPool2d
# layer1 -> Sequential  (Residual blocks)
# layer2 -> Sequential
# layer3 -> Sequential
# layer4 -> Sequential
# avgpool -> AdaptiveAvgPool2d
# fc -> Linear  <-- This is what we replace

Feature Vector Size for Each Architecture

When you replace the classification head, you need to know the feature dimension output by the backbone (everything except the final layer). This dimension is the input size of your new classification head.

Common backbone output dimensions: ResNet-50 outputs 2048, EfficientNet-B0 outputs 1280, and ViT-B/16 outputs 768. These feature vectors are computed by global average pooling over the spatial feature maps, producing a single vector per image. Your replacement head takes this vector as input.

import torch
import torchvision.models as models

# Feature dimensions before the classification head
feature_dims = {
    'resnet50':        2048,
    'efficientnet_b0': 1280,
    'efficientnet_b2': 1408,
    'efficientnet_b4': 1792,
    'vit_b_16':        768,
    'vit_l_16':        1024,
}

# Verify for ResNet-50 by running a dummy forward pass without the head
resnet = models.resnet50(weights=None)
resnet.fc = torch.nn.Identity()  # Remove FC layer
x = torch.randn(1, 3, 224, 224)
features = resnet(x)
print('ResNet-50 feature size:', features.shape)  # (1, 2048)

Checking Pre-trained Weight Quality

You can quickly verify that a pre-trained model's weights are correct by running it on a well-known test image and checking whether the top prediction matches the expected label. This sanity check ensures the weights loaded correctly and the preprocessing pipeline is correct.

Beyond this test, it is good practice to always check the expected input format from the weights metadata: input size (224×224 for most models), channel order (RGB, not BGR), and normalisation constants (ImageNet mean and std). Using wrong normalisation is a common bug that causes poor transfer learning results.

import torchvision.models as models

weights = models.ResNet50_Weights.IMAGENET1K_V1
print('Expected input size:', weights.meta['min_size'])  # (1, 1)
print('Transforms:', weights.transforms())
# Includes Resize(232), CenterCrop(224), Normalize(mean, std)

# ImageNet normalisation constants
IMAGENET_MEAN = [0.485, 0.456, 0.406]
IMAGENET_STD  = [0.229, 0.224, 0.225]
# Always use these EXACT values with ImageNet pre-trained models

Preparing for Fine-Tuning Your Own Task

The typical workflow for using pre-trained models on custom tasks is: (1) load the pre-trained model with weights=...IMAGENET1K..., (2) replace the final classification head with a new nn.Linear sized for your number of classes, (3) optionally freeze the backbone weights initially, and (4) train using a lower learning rate than you would use from scratch.

The new classification head starts with random weights and needs to learn from your data. The backbone starts with excellent features and needs only minor adjustments. This is why differential learning rates — a very low rate for the backbone and a higher rate for the head — often improve convergence speed and final accuracy.

import torchvision.models as models
import torch.nn as nn

# Example: Adapt ResNet-50 for 5-class flower classification
model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)

# Replace the final FC layer
num_classes = 5
model.fc = nn.Linear(model.fc.in_features, num_classes)

# Differential learning rates
optimizer = torch.optim.Adam([
    {'params': model.fc.parameters(), 'lr': 1e-3},      # High LR for new head
    {'params': [p for n, p in model.named_parameters() if 'fc' not in n], 'lr': 1e-5}  # Low LR for backbone
])

Quick Check

Test your understanding of pre-trained torchvision models from this lesson.

Lesson Recap

In this lesson you learned: ResNet-50 uses skip connections to train very deep networks and outputs 2048-dimensional features, EfficientNet achieves better accuracy-efficiency trade-offs through compound scaling of width, depth, and resolution, and ViT applies transformer self-attention to image patches without convolutions. Next up we learn feature extraction — freezing the pre-trained backbone and training only a new classification head on your custom dataset.

免费开始

用 AI 导师学习 Python — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
30
课程
120

常见问题解答

「torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT」课时是免费的吗?

是的 — 「torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。

「torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT」这节课中我会学到什么?

您将加载在 ImageNet 上预训练的 ResNet-50,检查其架构,并对新图像进行推理,以验证预先学习的表示。 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Machine Learning Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Machine Learning Academy 课中编写并运行代码吗?

能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. torchvision 中的预训练模型:ResNet、EfficientNet 与 ViT
  2. 特征提取:冻结骨干网络
  3. 微调:解冻网络与使用较低学习率
  4. 领域适应:标签稀缺的医学成像
← 返回 Machine Learning Academy