
# 准备训练代码、数据集和镜像
#### 步骤一：准备模型训练代码
训练代码包含训练文件，启动命令等内容。
- 启动命令开发规范可以参考[开发用于自定义镜像训练的代码](https://support.huaweicloud.com/develop-modelarts/develop-modelarts-1416.html)。
- 断点续训适配。
UniAD模型内部已经具备了断点续训的能力，无需修改代码。
其他框架中如果没有具备断点续训的能力，那么需要进行代码适配。
PyTorch框架适配断点续训的示例代码如下：
```
import torch 
import os  
# 假设你已经定义了模型 model 
# model = MyModel()  
# 判断输出路径中是否有模型文件。若无文件则默认从头训练，若有模型文件，则加载epoch值最大的ckpt文件，当做预训练模型
if os.listdir(train_url):
   print('> load last ckpt and continue training!!')    
   last_ckpt =sorted([fileforfilein os.listdir(train_url)
   if file.endswith(".pth")])[-1]    
   local_ckpt_file = os.path.join(train_url, last_ckpt)
   print('last_ckpt:', last_ckpt)
   # 加载断点    
   checkpoint = torch.load(local_ckpt_file)
   # 加载模型可学习参数    
   model.load_state_dict(checkpoint['net'])
   # 加载优化器参数    
   optimizer.load_state_dict(checkpoint['optimizer'])
   # 获取保存的epoch，模型会在此epoch的基础上继续训练    
    start_epoch = checkpoint['epoch'] 
# 训练循环中 
for epoch in range(num_epochs):    
# ... 你的训练代码 ...          
   # 例如：每个epoch结束后都保存一次     
   model_path = f"model_epoch_{epoch+1}.pth"    
   torch.save(model.state_dict(), model_path)    
   print(f"模型已保存: {model_path}")
```
#### 步骤二：准备模型训练镜像
1. 准备一套可以连接外部网络，装有Linux系统并安装18.09.7及以上版本，以及拥有昇腾资源的docker虚拟机或物理机用作镜像构建镜像。 可以通过执行docker pull、apt-get update/upgrade和pip install命令判断是否可正常访问外部可用的开源软件仓库，若可以正常访问表示环境已连接外部网络。
   
2. 建议使用官方提供的镜像部署训练服务。镜像地址{image_url}参见[表2 软件和镜像](https://support.huaweicloud.com/bestpractice-modelarts/modelarts_auto_train_911002.html#ZH-CN_TOPIC_0000002505814099__table1412351765111)获取。使用docker命令拉取镜像。
   ```
   docker pull {image_url}
   ```
   
3. 镜像获取完成后可通过如下命令进行查看。
   ```
   # docker 工具查看
   docker images
   ```
   
4. 由于DrivingSDK，mmcv，mmdet3d相关软件包需要在昇腾设备上才能安装。因此运行基础镜像，在基础环境中打出DrivingSDK，mmcv，mmdet3d相关软件包，在DockerFile中使用相关软件包进行安装 示例代码如下：
   ```
   # 通过驱动挂载运行基础镜像
   # 其中--device主要是将主机的设备文件挂载到容器内，让容器能够直接操作此设备
   # 其中-v主要是文件挂载
   docker run -itd -u root --privileged --device=/dev/davinci0 --device=/dev/davinci1 --device=/dev/davinci2 --device=/dev/davinci3 --device=/dev/davinci4 --device=/dev/davinci5 --device=/dev/davinci6 --device=/dev/davinci7 --device=/dev/davinci8 --device=/dev/davinci9 --device=/dev/davinci10 --device=/dev/davinci11 --device=/dev/davinci12 --device=/dev/davinci13 --device=/dev/davinci14 --device=/dev/davinci15  -v /etc/localtime:/etc/localtime -v /usr/local/Ascend/driver:/usr/local/Ascend/driver -v /etc/ascend_install.info:/etc/ascend_install.info --device=/dev/davinci_manager --device=/dev/devmm_svm --device=/dev/hisi_hdc -v /var/log/npu/:/usr/slog -v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /home/ma-user/valUniAD:/home/ma-user/valUniAD --shm-size 1024g --net=host --name uniad 基础镜像id /bin/bash
   # 构建DrivingSDK包
   cd /home/ma-user/valUniAD
   git config --global http.sslVerify false
   git clone https://gitcode.com/Ascend/DrivingSDK.git
   cd DrivingSDK
   git checkout 00be248b22395e02a950e7663399fdc3b28789f0 
   bash ci/build.sh --python=3.11
   # 补丁包移动
   cp /home/ma-user/valUniAD/DrivingSDK/model_examples/UniAD/mmcv.patch /home/ma-user/valUniAD
   cp /home/ma-user/valUniAD/DrivingSDK/model_examples/UniAD/mmdet3d.patch /home/ma-user/valUniAD
   # 构建mmcv whl包
   cd /home/ma-user/valUniAD
   pip uninstall -y mmcv
   git config --global http.sslVerify false
   git clone -b 1.x https://github.com/open-mmlab/mmcv.git
   cd mmcv
   cp -f ../mmcv.patch ./ 
   git apply --reject --whitespace=fix mmcv.patch 
   pip install --no-cache-dir -r requirements/runtime.txt
   export MMCV_WITH_OPS=1
   export FORCE_NPU=1
   python setup.py bdist_wheel --dist-dir /home/ma-user/valUniAD/mmcvwhl
   # 构建mmdet whl包
   cd /home/ma-user/valUniAD
   git clone -b v1.0.0rc6 https://github.com/open-mmlab/mmdetection3d.git 
   cp -f ./mmdet3d.patch  mmdetection3d/ 
   cd mmdetection3d 
   git apply --reject --whitespace=fix mmdet3d.patch
   pip install -r requirements/runtime.txt
   pip install setuptools==67.5.0 
   pip install numpy==1.26.4 
   sed -i 's/^\s*numpy==1\.22\.0$/# &/' requirements/runtime.txt 
   python setup.py bdist_wheel --dist-dir /home/ma-user/valUniAD/mmdetwhl
   ```
   
5. 编写Dockerfile文件。参考客户已有的python环境，补充基础镜像中所缺失的相关依赖。 UniAD模型的Dockerfile示例如下
   ```
   # 容器镜像构建主机需要连通公网
   FROM swr.cn-southwest-2.myhuaweicloud.com/atelier/pytorch_ascend:pytorch_2.5.1-cann_8.2.rc2-py_3.11-hce_2.0.2509-aarch64-snt9b23-20251106111344-87d9583
   # 设置工作目录
   WORKDIR /home/ma-user
   ENV WORK_HOME=/home/ma-user
   ENV MMCV_WITH_OPS=1
   ENV FORCE_NPU=1
   # 设置工作用户为root
   USER root
   # 安装DrivingSDK
   RUN git clone https://gitcode.com/Ascend/DrivingSDK.git \
       && cd DrivingSDK \
       && git checkout 00be248b22395e02a950e7663399fdc3b28789f0
   COPY valUniAD/DrivingSDK/dist/mx_driving-1.0.0+git00be248-cp311-cp311-linux_aarch64.whl /tmp/
   RUN pip install /tmp/mx_driving-1.0.0+git00be248-cp311-cp311-linux_aarch64.whl \
       && echo "DrivingSDK installed" \
       && echo "$WORK_HOME" \
       && cp $WORK_HOME/DrivingSDK/model_examples/UniAD/UniAD.patch $WORK_HOME \
       && cp -r $WORK_HOME/DrivingSDK/model_examples/UniAD/test $WORK_HOME \
       && echo "scripts has been copied"
   # 安装 mmcv
   RUN pip uninstall -y mmcv || true \
       && pip list | grep mmcv || echo "mmcv not installed"
   COPY valUniAD/mmcvwhl/*.whl /tmp/mmcv/
   RUN echo "begin install mmcv" \
       && ls /tmp/mmcv/ \
       && pip install /tmp/mmcv/*.whl \
       && echo "mmcv installed"
   # 安装 mmdet3d
   COPY valUniAD/mmdetwhl/*.whl /tmp/mmdet3d/
   RUN echo "begin install mmdet3d" \
       && ls /tmp/mmdet3d \
       && pip install /tmp/mmdet3d/*.whl \
       && pip install setuptools==67.5.0 \
       && pip install numpy==1.26.4
   # UniAD模型源码准备
   RUN cd $WORK_HOME \
       && git config --global http.sslVerify false \
       && git clone https://github.com/OpenDriveLab/UniAD.git \
       && cp -f UniAD.patch UniAD/ \
       && cp -r test UniAD/ \
       && cd UniAD \
       && git checkout 7b5bf15e0e49522b6553ddc48e67833e8f5f0f52 \
       && git apply --reject --whitespace=fix UniAD.patch \
       && pip install casadi==3.7.2 \
       && sed -i 's/^\s*casadi==3\.5\.5$/# &/' requirements.txt \
       && pip install -r requirements.txt
   # UniAD模型权重和数据准备,数据与镜像分离，采用挂载方式提供,数据集的获取方式见下方
   ENV UNIAD_HOME=/home/ma-user/UniAD
   RUN echo "$UNIAD_HOME"
   RUN  cd $UNIAD_HOME \
         && mkdir -p ckpts \
         && mkdir -p data \
         && cd data \
         && mkdir -p nuscenes \
         && mkdir -p infos \
         && mkdir -p others
   # 训练适配，包版本更新
   RUN pip install networkx==2.7.0 \
       && pip install motmetrics==1.4.0  \
       && pip install shapely==1.8.5.post1 \
       && ln -s /usr/lib64/libgeos_c.so /home/ma-user/anaconda3/envs/PyTorch-2.5.1/lib/libgeos_c.so \
       && echo 'install shapely ok' \
       && echo "$WORK_HOME" \
       && cd $WORK_HOME \
       && git config --global http.sslVerify false \
       && git clone -b v3.5.3 --depth 1 https://github.com/matplotlib/matplotlib.git \
       && cd matplotlib \
       && mkdir build \
       && cd build \
       && wget https://downloads.sourceforge.net/project/freetype/freetype2/2.6.1/freetype-2.6.1.tar.gz \
       && tar xzf freetype-2.6.1.tar.gz \
       && cd .. \
       && pip install . \
       && sed -i "s/^\s*plt.style.use('seaborn-v0_8-whitegrid')/# &/" /home/ma-user/anaconda3/envs/PyTorch-2.5.1/lib/python3.11/site-packages/nuscenes/map_expansion/map_api.py \
       && echo "train adapt finished"
   # 训练适配
   RUN cd $UNIAD_HOME
   ENV PYTHONPATH=$PYTHONPATH:$PWD
   ```
   
6. Dockerfile编写完成后，执行以下命令制作训练镜像。安装过程需要连接互联网git clone，请确保机器可以访问公网。
   下述命令在/home/ma-user文件夹的同级目录执行
   ```
   docker build  -f docker/Dockerfile -t <镜像名称>:<版本名称>  .
   ```
   - \<镜像名称\>:\<版本名称\>：定义镜像名称。示例：pytorch_3_11_ascend:20251110。
   
   - 记住使用Dockerfile创建的新镜像名称， 后续使用 ${dockerfile_image_name} 表示。
     
7. 镜像制作完成后，上传镜像至SWR服务，上传镜像的步骤参考相关链接：[如何登录并上传镜像到SWR](https://support.huaweicloud.com/modelarts_faq/docker-modelarts_0018.html)。
   自定义镜像制作参考：**[从0制作自定义镜像用于创建训练作业（Pytorch+Ascend）](https://support.huaweicloud.com/docker-modelarts/docker-modelarts_6031.html)**
   
 
#### 步骤三：准备训练数据
UniAD涉及的训练数据下载地址如下：
- checkpoints目录下的数据下载地址如下： https://github.com/OpenDriveLab/UniAD/releases/download/v1.0/uniad_base_track_map.pth
  https://github.com/OpenDriveLab/UniAD/releases/download/v1.0.1/uniad_base_e2e.pth
  https://github.com/zhiqi-li/storage/releases/download/v1.0/bevformer_r101_dcn_24ep.pth
  

- infos目录下的数据下载地址如下：https://github.com/OpenDriveLab/UniAD/releases/download/v1.0/nuscenes_infos_temporal_train.pklhttps://github.com/OpenDriveLab/UniAD/releases/download/v1.0/nuscenes_infos_temporal_val.pkl
- others目录下的数据下载地址如下：https://github.com/OpenDriveLab/UniAD/releases/download/v1.0/motion_anchor_infos_mode6.pkl
- nuscenes目录下的数据下载参考如下：https://github.com/OpenDriveLab/UniAD/blob/v2.0/docs/DATA_PREP.md
数据下载完成后保存到SFS，在SFS上进行挂载。数据挂载完成后UniAD的文件结构如下图展示。
![](https://support.huaweicloud.com/bestpractice-modelarts/figure/zh-cn_image_0000002525800629.png)
#### 步骤四：性能加速（可选）
请提工单咨询华为技术支持并提供专属资源池的名称，让技术支持人员使用昇腾云框架包中的脚本执行训练作业的性能加速。
脚本的执行命令如下，以下命令需要技术支持人员在后台执行。
- 绑核操作 宿主机绑核
  ```
  sh set_cpu_affinity.sh -m
  ```
  容器绑核
  ```
  sh set_cpu_affinity.sh -c
  ```
  
- 高性能内存库替换
  ```
  source set_turbo.sh all
  ```
  
 
