一、目录分层规则
统一目录结构tb_cls采用单一目标板分类工程结构配置、真实数据、模型和输出都直接放在根目录对应位置├── configs │ ├── README.md │ └── labels.txt ├── dataset │ ├── dataset.zip │ ├── supplies │ ├── vechicle │ └── weapon ├── models │ ├── README.md │ ├── best.bin │ ├── best.param │ ├── best.torchscript │ ├── best_model.pt │ ├── labels.txt │ └── metrics.json ├── outputs │ └── traintb_cls的标签来自文件夹名数据目录是ImageFolder结构。当前三类目录为dataset/ ├── supplies/ ├── vechicle/ └── weapon/类别顺序由torchvision.datasets.ImageFolder按文件夹名字典序生成训练结束后会写入labels.txt。当前labels.txt顺序为supplies vechicle weapon车端解析分类结果时必须使用同一份labels.txt。其中vechicle对应交通工具类。当前仓库中已有模型可能仍带有旧版labels.txt以重新训练后生成的models/labels.txt和configs/labels.txt为准。仓库提交时只需要保留dataset/dataset.zip解压后的图片目录由.gitignore忽略。训练脚本会在发现三类图片目录不存在时自动解压dataset/dataset.zip。回到顶部二、环境准备和已有模型2.1 Linux/WSL 训练环境requirements.txt是从conda env: loong导出的固定版本依赖建议使用Python 3.10的独立环境。不要直接使用系统自带的Python 3.14安装本文件因为numpy、torch等固定版本可能没有对应兼容包。如果系统还没有conda先安装Miniforgecd /tmp wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh bash Miniforge3-Linux-x86_64.sh -b -p $HOME/miniforge3 eval $($HOME/miniforge3/bin/conda shell.bash hook) conda init bash执行conda init bash后重新打开一个终端或者执行source ~/.bashrc如果安装后当前终端仍提示Command conda not found说明当前 shell 还没有加载conda先执行eval $($HOME/miniforge3/bin/conda shell.bash hook) conda --version确认能看到conda版本号后再继续创建环境。如果wget不存在先安装sudo apt update sudo apt install -y wget创建并进入loong环境conda create -n loong python3.10 conda activate loong cd /opt/2k0300/loongson_2k300_lib/tb_cls python -m pip install -r requirements.txtrequirements.txt已固定使用CUDA 12.8版PyTorchtorch2.11.0cu128 torchvision0.26.0cu128如果只做ncnn导出还需要额外安装pnnxpython -m pip install pnnx验证PyTorch环境python -c import torch, torchvision; print(torch.__version__); print(torchvision.__version__); print(torch.cuda.is_available())Linux/WSL没有配置NVIDIA GPU时输出False也可以训练只是会使用CPU。2.2 已有模型位置当前仓库只保留真实目标板分类数据dataset/下的数据就是后续训练使用的ImageFolder数据集。数据按三大类放置不需要目标框标注。已经训练或转换好的模型统一归档在models/best_model.pt models/best.torchscript models/best.param models/best.bin models/labels.txtconfigs/labels.txt是同一份类别顺序文件车端推理显示类别时必须按该顺序解析输出。回到顶部三、真实目标板数据集3.1 数据内容当前dataset/目录下的数据就是真实目标板数据。图片内容来自赛道中心目标板按业务含义分成三个大类当前训练集已经整理为64x64图片。weapon 武器枪支、爆炸物、匕首、警棍、消防斧 supplies 物资急救包、手电筒、对讲机、防弹背心、望远镜、头盔 vechicle 交通工具消防车、救护车、装甲车、摩托车所有图片都是无框图片不包含检测框标注。训练时只使用图片所在的大类文件夹作为分类标签不区分大类内部的小类编号。大类目录下的图片已经平铺文件名只作为样本编号不参与标签解析。3.2 输入边界TinyClassifier只做整图分类不做检测框定位。用于智能车目标板时建议输入已经裁剪好的目标板ROI而不是整张赛道图。可选裁剪方式目标板出现在固定区域时直接从摄像头画面裁剪固定ROI。目标板位置有轻微变化时先用颜色、边缘或几何规则定位候选区域再送入分类模型。如果目标板位置完全不稳定需要额外实现轻量定位或裁剪逻辑。3.3 数据目录当前压缩包解压后按三大类建立文件夹dataset/ ├── dataset.zip ├── supplies/ ├── vechicle/ └── weapon/如果提交仓库保留dataset/dataset.zip不要提交解压后的dataset/supplies/、dataset/vechicle/、dataset/weapon/图片目录。运行训练脚本时会自动检查并解压。回到顶部四、训练和导出4.1 模型结构TinyClassifier是轻量级卷积分类网络主体由普通卷积、深度可分离卷积、全局池化和全连接分类头组成。当前计划使用64x64输入训练输出类别数由dataset/下的三类目录自动决定。网络结构概览输入 1x3x64x64 Conv3x3 stride2 BN ReLU DWConvBlock stride1 DWConvBlock stride2 DWConvBlock stride1 DWConvBlock stride2 DWConvBlock stride1 Conv1x1 BN ReLU AdaptiveAvgPool2d(1) Linear(num_classes) 输出 1x3 logitsDWConvBlock内部结构为Depthwise Conv3x3 BN ReLU Pointwise Conv1x1 BN ReLU通道数由--width-mult控制默认0.6。基础通道序列为12 - 16 - 24 - 32 - 48 - 48 - 64实际通道数会乘以width_mult并保证最小通道数不低于8。增大width_mult会提高模型容量和计算量减小它会让模型更小但可能降低准确率。训练时使用AdamW优化器、CrossEntropyLoss损失函数和CosineAnnealingLR学习率调度。数据集按类别内随机划分为80%训练集、10%验证集、剩余10%测试集。训练增强包括Resize(64x64) RandomHorizontalFlip RandomRotation(10) ColorJitter ImageNet Normalize验证、测试和导出推理只使用Resize、ToTensor和ImageNet Normalize。4.2 训练并归档模型4.2.1 WSL/Linux GPU/CPU 训练WSL/Linux中可运行./scripts/train_classifier_host.sh --run-name exp_cls_64 --img-size 64常用参数示例./scripts/train_classifier_host.sh \ --run-name exp_cls_64 \ --img-size 64 \ --batch-size 64 \ --epochs 35 \ --width-mult 0.6 \ --target-acc 0.95训练源码会自动选择设备torch.cuda.is_available()为真时使用cuda否则使用cpu。首次从压缩包训练时脚本会先自动解压数据集再开始训练。正常日志示例[cls-train] Dataset class folders not found; extracting .../tb_cls/dataset/dataset.zip [cls-train] Python: python [cls-train] Dataset: .../tb_cls/dataset Using device: cuda Classes: [supplies, vechicle, weapon]4.2.2 训练输出训练输出先写入outputs/train/实验名/随后脚本会把关键产物复制到models/训练结束后原始输出位于outputs/train/实验名/ ├── best_model.pt ├── tiny_classifier.torchscript ├── labels.txt └── metrics.json包装脚本会把关键产物同步到models/best_model.pt models/best.torchscript models/labels.txt models/metrics.json configs/labels.txt4.2.3 训练脚本参数参数默认值说明--data-root DIRdatasetImageFolder数据集根目录。默认目录缺少三类文件夹时会自动解压dataset/dataset.zip。--run-name NAMEexp_cls实验名默认输出到outputs/train/实验名/。--out-dir DIRoutputs/train/实验名显式指定训练输出目录。--img-size N64输入图片尺寸。当前64x64数据训练时使用64训练、导出和板端推理必须保持一致。--batch-size N64批大小。显存不足或内存不足时调小。--epochs N35最大训练轮数。可能因达到目标准确率或早停提前结束。--lr VALUE1e-3AdamW初始学习率。--weight-decay V2e-4权重衰减系数。--num-workers N0数据加载线程数。WSL/Linux 可按机器性能调大。--seed N42数据划分和训练随机种子。--width-mult VALUE0.6网络宽度倍率控制通道数和参数量。--patience N8验证准确率连续N轮不提升时早停。--target-acc VALUE0.95验证准确率达到该值后提前停止训练。--python FILEpython3Linux/WSL训练脚本使用的Python可执行文件。4.3 本地验证单张图片识别结果训练结束并归档到models/后可以先在主机上拿一张图片做单图识别确认模型、标签顺序和预处理尺寸是否一致python vendor/lq_tiny_classifier/predict_image.py \ --checkpoint models/best_model.pt \ --image dataset/supplies/000001.jpg \ --img-size 64输出示例image: dataset/supplies/000001.jpg prediction: supplies (0.9821) topk: supplies: 0.9821 weapon: 0.0113 vechicle: 0.0066如果要验证其他类别替换--image即可例如python vendor/lq_tiny_classifier/predict_image.py \ --checkpoint models/best_model.pt \ --image dataset/weapon/000001.jpg \ --img-size 64这里使用的是训练 checkpointbest_model.pt预处理与训练/测试一致Resize(64x64)、ToTensor和ImageNet Normalize。如果单图预测类别明显不对优先检查三点图片是否来自正确的大类目录、--img-size是否和训练一致、models/labels.txt是否为本次训练生成。4.4 导出ncnn模型WSL/Linux主机中使用pnnx从TinyClassifier训练脚本导出的TorchScript转为ncnn./scripts/export_ncnn_host.sh --torchscript models/best.torchscript --img-size 64输出文件为models/best.param models/best.bin需要带到开发板的文件models/best.param models/best.bin models/labels.txt导出脚本参数