第一次在服务器上部署LSKNet时,我花了整整三天时间解决各种环境冲突。这玩意儿对PyTorch和CUDA的版本要求简直像俄罗斯套娃——每个组件都有自己的一套规矩。先说说我的硬件配置:一台搭载NVIDIA Tesla V100(32GB显存)的服务器,CUDA 11.6驱动。如果你的环境和我类似,跟着我的步骤能少走80%的弯路。
Python虚拟环境是保命符。千万别直接往系统环境里装,否则后期版本冲突能让你怀疑人生。我用的conda创建环境,这里有个隐藏坑点:官方文档推荐Python 3.8,但实测3.9更稳定:
bash复制conda create --name lsknet python=3.9 -y
conda activate lsknet
PyTorch安装是第一个拦路虎。服务器没外网权限时,用清华镜像源能救命:
bash复制conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.6 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/linux-64/
接下来是MMCV-full这个硬骨头。当mim install mmcv-full卡在下载环节时,手动下载whl文件才是王道。关键是要找对版本组合:
比如我用的mmcv_full-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl,下载后用pip install mmcv_full-xxx.whl本地安装。这时候如果报GLIBCXX_3.4.29 not found错误,需要先升级gcc:
bash复制sudo apt-get install gcc-11 g++-11
export CC=/usr/bin/gcc-11
export CXX=/usr/bin/g++-11
遥感目标检测最头疼的就是数据格式转换。DOTA数据集用的四边形标注(x1,y1,x2,y2,x3,y3,x4,y4),而FAIR1M则是多边形顶点。我处理过的农业大棚数据集更奇葩——标注文件用GeoJSON存储。这时候需要自己写转换脚本:
python复制import json
with open('fields.geojson') as f:
data = json.load(f)
annotations = []
for feature in data['features']:
coords = feature['geometry']['coordinates'][0]
# 将多边形转为四边形
x_min = min(p[0] for p in coords)
x_max = max(p[0] for p in coords)
y_min = min(p[1] for p in coords)
y_max = max(p[1] for p in coords)
annotations.append(f"{x_min},{y_min},{x_max},{y_min},{x_max},{y_max},{x_min},{y_max},greenhouse")
类别映射是新手最容易翻车的地方。LSKNet默认用DOTA的15个类别(plane, ship...),如果你的数据只有"建筑"、"道路"两类,需要修改两处:
mmrotate/datasets/dota.py里的CLASSES元组num_classes参数实测发现图片格式也影响训练。PNG图片用cv2.imread()读取时会带alpha通道,导致张量维度不对。建议统一转成JPEG:
bash复制find ./images -name "*.png" | parallel -j 8 'convert {} -background white -alpha remove {.}.jpg'
当我在8卡V100上第一次跑train.py时,遇到的分布式训练报错足以写本错题集。关键修改点在tools/train.py开头加入:
python复制import os
os.environ['MASTER_ADDR'] = '192.168.1.100' # 主节点IP
os.environ['MASTER_PORT'] = '29500'
os.environ['RANK'] = str(os.getenv('SLURM_PROCID', 0))
os.environ['WORLD_SIZE'] = str(os.getenv('SLURM_NTASKS', 1))
单卡用户注意!必须修改三处配置:
norm_cfg=dict(type='SyncBN')改为type='BN'data=dict(samples_per_gpu=4, workers_per_gpu=2)--gpu-ids 0参数学习率调整是门玄学。对于512x512的遥感图,我的最佳实践是:
CosineAnnealing调度器python复制optimizer = dict(type='SGD', lr=0.0025, momentum=0.9, weight_decay=0.0001)
lr_config = dict(
policy='CosineAnnealing',
warmup='linear',
warmup_iters=500,
warmup_ratio=0.001,
min_lr=1e-07)
遇到IndexError: list index out of range?八成是标注文件少了difficulty字段。快速修复方案是在dota.py的load_annotations方法里加默认值:
python复制def load_annotations(self, ann_file):
for line in ann_file:
parts = line.split()
if len(parts) == 9: # 没有difficulty的情况
parts.append('0') # 补默认值
RuntimeError: CUDA out of memory这个经典错误,除了调小batch_size,还有两个妙招:
fp16=True混合精度训练optimizer_config=dict(grad_clip=dict(max_norm=35, norm_type=2))最让人崩溃的KeyError: 'acc'其实是因为验证集没设对。检查配置里的val_evaluator:
python复制val_evaluator = dict(
type='DOTAMetric',
metric='mAP',
iou_thrs=[0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95])
训练完的模型转ONNX时,这个命令能避开99%的坑:
bash复制python tools/deployment/pytorch2onnx.py \
configs/lsknet/lsk_s_fpn_1x_dota_le90.py \
work_dirs/lsk_s_fpn_1x_dota_le90/epoch_12.pth \
--output-file model.onnx \
--shape 512 512 \
--dynamic-export
TensorRT加速实测:在Jetson AGX Xavier上,FP16模式能使推理速度从23FPS提升到41FPS。关键是要重新编译MMCV的Custom Ops:
dockerfile复制FROM nvcr.io/nvidia/pytorch:22.07-py3
RUN git clone https://github.com/open-mmlab/mmcv.git && \
cd mmcv && \
MMCV_WITH_OPS=1 pip install -e .
最后提醒:遥感目标检测最吃显存的是大尺寸图像。如果遇到RuntimeError: tile cannot extend outside image,试试在配置里加随机裁剪:
python复制train_pipeline = [
dict(type='RandomRotate', prob=0.5, degree=45),
dict(type='RandomCrop', crop_size=(800, 800)), # 根据显存调整
dict(type='Resize', img_scale=(1024, 1024), keep_ratio=True)
]