1. 环境搭建:从零搞定LSKNet依赖
第一次在服务器上部署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文件才是王道。关键是要找对版本组合:
- CUDA 11.6 → 选cu116
- PyTorch 1.13 → 选torch1.13
- Python 3.9 → 选cp39
比如我用的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
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据准备:遥感图像的定制化处理
遥感目标检测最头疼的就是数据格式转换。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'
3. 模型训练:单卡与多卡的生存指南
当我在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的遥感图,我的最佳实践是:
- 初始学习率设为0.0025(batch_size=16时)
- 使用
CosineAnnealing调度器 - warmup_iters设为500
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)
4. 避坑大全:那些官方没说的Error解决方案
遇到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])
5. 推理部署:让模型真正用起来
训练完的模型转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)
]
