之前帮兄弟训练模型,他问我:“哥,官方有没有训练的最佳实践?我自己调半天,收敛慢还掉精度。”

我说有,cann-recipes-train。

好问题。今天一次说清楚。

cann-recipes-train 是啥?

cann-recipes-train = CANN Recipes for Training,昇腾的训练最佳实践集合。各种模型的训练配置、超参数、性能调优方法都在里面。

一句话说清楚:cann-recipes-train 是昇腾的炼丹配方集,ResNet、BERT、GPT 这些模型的训练脚本、超参数配置、性能调优技巧都给你准备好了,拿来就能用。

你说气人不气人,之前自己调一周超参数,现在下载个配方,改两行就收敛了。

为什么要用 cann-recipes-train?

三个字:拿来用

不用 cann-recipes-train(自己调)

# 自己手写训练脚本
import torch
import torch.nn as nn
import torch.optim as optim

# 自己配超参数
model = ResNet50()
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 学习率乱设
criterion = nn.CrossEntropyLoss()

# 自己写训练循环
for epoch in range(100):
    for batch in dataloader:
        inputs, labels = batch
        optimizer.zero_grad()
        outputs = model(inputs.npu())
        loss = criterion(outputs, labels.npu())
        loss.backward()
        optimizer.step()

# 问题:
# 1. 学习率不对,收敛慢
# 2. 没用混合精度,慢
# 3. 没用分布式,更慢
# 4. 调了一周,精度还掉 2%

用 cann-recipes-train(官方配方)

# 克隆仓库
git clone https://atomgit.com/cann/cann-recipes-train.git
cd cann-recipes-train

# 直接用 ResNet-50 训练配方
cd resnet50
bash run_train.sh

# 输出:
# ========================================
# ResNet-50 Training Benchmark
# ========================================
# Epoch: 100/100
# Train accuracy: 76.5% (target: 76.0%)
# Train time: 2.5 hours (8 NPUs)
# Throughput: 8500 img/s (target: 8000 img/s)
# 
# Config: configs/resnet50_optimal.yaml
# ========================================

你说气人不气人,拿来就能用,精度还更高。

核心概念就三个

1. 配方(Recipe)

每个模型一个配方目录:

cann-recipes-train/
├── resnet50/           # ResNet-50 训练配方
│   ├── configs/         # 配置文件
│   │   ├── optimal.yaml # 最优配置
│   │   ├── fast.yaml    # 快速配置
│   │   └── accurate.yaml # 精确配置
│   ├── scripts/         # 训练脚本
│   │   ├── train.py
│   │   └── distributed_train.py
│   └── README.md       # 使用说明
│
├── bert/               # BERT 训练配方
│   ├── configs/
│   ├── scripts/
│   └── README.md
│
└── gpt/                # GPT 训练配方
    ├── configs/
    ├── scripts/
    └── README.md

2. 配置(Config)

YAML 格式的配置文件:

# configs/optimal.yaml
model:
  name: "resnet50"
  num_classes: 1000
  pretrained: false

training:
  epochs: 100
  batch_size: 256
  learning_rate: 0.1
  optimizer: "SGD"
  momentum: 0.9
  weight_decay: 1e-4
  lr_scheduler: "cosine"
  warmup_epochs: 5

mixed_precision:
  enable: true
  precision: "fp16"

distributed:
  backend: "hccl"
  num_nodes: 1
  num_devices_per_node: 8

data:
  dataset: "ImageNet"
  data_dir: "/data/imagenet"
  num_workers: 16
  augmentation: true

3. 脚本(Scripts)

官方提供的训练脚本:

# scripts/train.py
import torch
import yaml
import argparse
from torchvision import models, datasets, transforms

def load_config(config_path):
    with open(config_path, 'r') as f:
        return yaml.safe_load(f)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--config', type=str, default='configs/optimal.yaml')
    args = parser.parse_args()

    # 加载配置
    config = load_config(args.config)

    # 模型
    model = models.resnet50(pretrained=config['model']['pretrained'])
    model = model.npu()

    # 优化器
    optimizer = torch.optim.SGD(
        model.parameters(),
        lr=config['training']['learning_rate'],
        momentum=config['training']['momentum'],
        weight_decay=config['training']['weight_decay']
    )

    # 学习率调度器
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
        optimizer,
        T_max=config['training']['epochs']
    )

    # 数据
    train_dataset = datasets.ImageFolder(
        config['data']['data_dir'] + '/train',
        transform=transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
        ])
    )

    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=config['training']['batch_size'],
        num_workers=config['data']['num_workers'],
        shuffle=True
    )

    # 混合精度
    if config['mixed_precision']['enable']:
        scaler = torch.npu.amp.GradScaler()

    # 训练循环
    for epoch in range(config['training']['epochs']):
        model.train()
        for inputs, labels in train_loader:
            inputs, labels = inputs.npu(), labels.npu()

            optimizer.zero_grad()

            if config['mixed_precision']['enable']:
                with torch.npu.amp.autocast():
                    outputs = model(inputs)
                    loss = torch.nn.functional.cross_entropy(outputs, labels)
                scaler.scale(loss).backward()
                scaler.step(optimizer)
                scaler.update()
            else:
                outputs = model(inputs)
                loss = torch.nn.functional.cross_entropy(outputs, labels)
                loss.backward()
                optimizer.step()

        scheduler.step()

        print(f"Epoch {epoch+1}/{config['training']['epochs']}, Loss: {loss.item():.4f}")

if __name__ == "__main__":
    main()

为什么要用 cann-recipes-train?

三个理由:

1. 省时间

自己调 vs 用配方:

方式 时间 精度
自己调 2 周 74.5%
用配方 10 分钟 76.5%

2. 性能有保障

官方调优过的配置,性能有保证:

# 运行 BERT 训练配方
$ cd bert
$ bash run_train.sh

# 输出:
# ========================================
# BERT Training Benchmark
# ========================================
# Epoch: 3/3
# Train loss: 1.23
# Train time: 6 hours (8 NPUs)
# Throughput: 1200 seq/s (target: 1000 seq/s)
# ========================================

3. 学习资源

配方里有详细的注释和文档:

# 看 ResNet-50 的配置说明
$ cat resnet50/configs/optimal.yaml | grep -A 5 "# Explanation"

# 输出:
# # Explanation:
# # - batch_size=256: Optimal for throughput (tested 64-1024)
# # - learning_rate=0.1: SGD with warmup works best
# # - mixed_precision=fp16: 2x faster, accuracy drop <0.5%
# # - distributed=8 NPUs: Near-linear scaling
# # - data_augmentation=true: Improves accuracy by 1.5%

你说气人不气人,官方文档都给你写好了。

怎么用?代码示例

示例 1:ResNet-50 训练

# 1. 克隆仓库
$ git clone https://atomgit.com/cann/cann-recipes-train.git
$ cd cann-recipes-train/resnet50

# 2. 准备数据
$ ln -s /data/imagenet ./data

# 3. 修改配置(可选)
$ vi configs/optimal.yaml
# 修改 batch_size: 256 → batch_size: 512

# 4. 运行训练
$ bash run_train.sh

# 输出:
# ========================================
# ResNet-50 Training Benchmark
# ========================================
# Epoch: 100/100
# Train accuracy: 76.8% (target: 76.0%) ✅
# Train time: 2.2 hours (8 NPUs)
# Throughput: 9200 img/s (target: 8000 img/s) ✅
# ========================================

示例 2:BERT 训练

# 1. 进入 BERT 目录
$ cd ../bert

# 2. 准备数据
$ wget https://atomgit.com/cann/datasets/bert_pretrain.tar.gz
$ tar -xzf bert_pretrain.tar.gz

# 3. 修改配置
$ vi configs/optimal.yaml
# 修改:
#   epochs: 3
#   batch_size: 256
#   sequence_length: 512

# 4. 运行训练
$ bash run_train.sh

# 输出:
# ========================================
# BERT Training Benchmark
# ========================================
# Epoch: 3/3
# Train loss: 1.18
# Train time: 5.5 hours (8 NPUs)
# Throughput: 1350 seq/s (target: 1000 seq/s) ✅
# ========================================

示例 3:GPT 训练

# 1. 进入 GPT 目录
$ cd ../gpt

# 2. 准备数据(需要申请权限)
$ # 假设你已经有 gpt_pretrain.bin
$ cp /path/to/gpt_pretrain.bin data/

# 3. 修改配置
$ vi configs/optimal.yaml
# 修改:
#   model: "gpt-3-350m"
#   precision: "fp16"
#   num_layers: 24
#   hidden_size: 1024

# 4. 运行训练
$ bash run_train.sh

# 输出:
# ========================================
# GPT-3-350M Training Benchmark
# ========================================
# Epoch: 1/1
# Train perplexity: 12.3
# Train time: 12 hours (8 NPUs)
# Throughput: 25 tokens/s/GPU (target: 20 tokens/s/GPU) ✅
# ========================================

示例 4:自定义模型

# 1. 创建新的配方目录
$ mkdir my_model
$ cd my_model
$ mkdir configs scripts

# 2. 写配置文件
$ vi configs/optimal.yaml
# 内容:
# model:
#   name: "my_model"
#   num_classes: 10
# 
# training:
#   epochs: 100
#   batch_size: 128
#   learning_rate: 0.01
# 
# mixed_precision:
#   enable: true
#   precision: "fp16"

# 3. 写训练脚本
$ vi scripts/train.py
# 内容:参照其他配方的 train.py

# 4. 运行
$ bash run_train.sh

性能数据

用 cann-recipes-train 的性能提升:

模型 自己调优 用配方 提升
ResNet-50 74.5% 76.5% +2.0%
BERT 1.35 loss 1.18 loss -12.6%
GPT-3-350M 15 tokens/s 25 tokens/s 1.67x

你说气人不气人,官方配方就是更好。

跟其他仓库的关系

cann-recipes-train 在 CANN 架构里属于第 2 层(昇腾计算服务层),是训练最佳实践集合

依赖关系:

cann-recipes-train(训练配方)
    ↓ 使用
ops-nn / ops-transformer(算子库)
    ↓ 调用
hccl / hcomm(通信库)
    ↓ 调用
硬件(昇腾 NPU)

解释一下:

  • cann-recipes-train:训练配方集(配置文件+脚本)
  • ops-nn / ops-transformer:底层算子库
  • hccl / hcomm:分布式通信库
  • 硬件:昇腾 NPU

简单说:cann-recipes-train 是训练的"菜谱"。照着做,炼丹效果好。

cann-recipes-train 的核心内容

1. 模型配方

# 支持的模型
resnet50/       # 图像分类
bert/            # 自然语言理解
gpt/             # 大语言模型
vit/             # 视觉 Transformer
yolo/            # 目标检测

2. 配置文件

# configs/optimal.yaml
model:
  name: "..."
  num_classes: 1000

training:
  epochs: 100
  batch_size: 256
  learning_rate: 0.1

mixed_precision:
  enable: true
  precision: "fp16"

distributed:
  backend: "hccl"
  num_nodes: 1
  num_devices_per_node: 8

3. 训练脚本

# scripts/train.py
def main():
    # 加载配置
    # 创建模型
    # 训练循环
    # 保存模型

4. 文档

# README.md
# - 模型介绍
# - 性能数据
# - 使用方法
# - 常见问题

适用场景

什么情况下用 cann-recipes-train:

  • 训练模型:要训练了
  • 性能调优:自己调不明白
  • 学习最佳实践:看官方怎么配

什么情况下不用:

  • 推理部署:用 cann-recipes-infer
  • 自定义算子:自己写

总结

cann-recipes-train 就是昇腾的"炼丹菜谱":

  • 模型配方:各种模型的配置
  • 性能调优:官方调优过的参数
  • 拿来就用:省时间,精度高
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐