Segearth-R2-06

继续。下面进入 第 6 讲:评估、推理、LoRA 合并与复现闭环

这一讲解决一个实际问题:

训练完成后,怎么把模型真正跑起来?
怎么合并 LoRA?
怎么测试 LaSeRS?
怎么得到 mask?
怎么判断复现是否成功?

第 6 讲总目标

前面我们已经吃透了训练链路:

train.sh
    ↓
train.py
    ↓
dataset.py
    ↓
llava_phi.py forward
    ↓
loss 训练

现在进入推理链路:

训练 checkpoint
    ↓
merge_lora_weights.sh
    ↓
合并后的 HF 模型
    ↓
test.sh / eval.py
    ↓
model.inference()
    ↓
eval_seg()
    ↓
pred mask
    ↓
IoU / gIoU

官方测试脚本使用 deepspeed --include localhost:0 --master_port=29500 segearth_r2/eval/eval.py 启动,并需要传入 base_data_pathmodel_pathvision_tower_maskmask_configoutput_dir。(GitHub)


一、先理解训练后为什么要合并 LoRA

你训练时不是全量微调整个大模型,而是:

基础模型 Mipha-3B
    +
LoRA adapter
    +
训练后的分割模块参数

训练完后,checkpoint 里通常不是一个完整可直接部署的 HuggingFace 模型,而是包含 LoRA、DeepSpeed 分片、部分可训练模块权重。

所以需要:

merge_lora_weights.sh

它的作用是:

读取训练 checkpoint
    ↓
重新构建 SegEarthR2
    ↓
加载 LoRA 配置
    ↓
从 DeepSpeed ZeRO checkpoint 恢复 fp32 权重
    ↓
merge_and_unload()
    ↓
保存成完整 HuggingFace 模型目录

官方 merge_lora_weights.sh 调用的是 segearth_r2/train/merge_lora_weights_and_save_hf_model.py,参数包括 model_pathvision_towervision_tower_maskmask_configsave_pathlora_r。(GitHub)


二、merge_lora_weights.sh 逐项解释

官方脚本核心形式是:

CUDA_VISIBLE_DEVICES=0 python segearth_r2/train/merge_lora_weights_and_save_hf_model.py \
  --model_path=your_model_path \
  --vision_tower=pretrained_model/CLIP/siglip-so400m-patch14-384 \
  --vision_tower_mask=pretrained_model/mask2former/model_final_54b88a.pkl \
  --mask_config=segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml \
  --save_path=your_save_path \
  --lora_r=4

1. CUDA_VISIBLE_DEVICES=0

只使用第 0 张 GPU。

RTX 5090 单卡复现时保留即可。


2. --model_path

这是你训练输出的 checkpoint 目录,例如:

--model_path=outputs/debug_5090_lora_r4

或者如果你训练到了某个 checkpoint:

--model_path=outputs/debug_5090_lora_r4/checkpoint-5000

这个路径必须包含 DeepSpeed / LoRA 训练保存出来的权重。


3. --vision_tower

这是 SigLIP 路径:

--vision_tower=pretrained_model/CLIP/siglip-so400m-patch14-384

注意,它虽然叫 vision tower,但这是给多模态语言模型使用的视觉塔,不是 Mask2Former 分割视觉骨干。


4. --vision_tower_mask

这是 Mask2Former / Swin 分割分支权重:

--vision_tower_mask=pretrained_model/mask2former/model_final_54b88a.pkl

如果这个路径错了,合并时初始化分割模块就可能失败。


5. --mask_config

这是分割头配置:

--mask_config=segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml

它必须和训练时一致。

如果训练时用的是 Swin-B 配置,合并时不能突然换成 Swin-L 配置,否则 predictor、pixel decoder、hidden dim 都可能不匹配。


6. --save_path

合并后的完整模型保存目录,例如:

--save_path=outputs/merged_segearth_r2_lasers

后续 eval.py 的:

--model_path

就应该指向这个目录。


7. --lora_r

必须和训练时一致。

如果训练时:

--lora_r 4

合并时也要:

--lora_r=4

如果不一致,LoRA 层 shape 可能不匹配。


三、合并脚本内部做了什么

merge_lora_weights_and_save_hf_model.py 里有几个关键步骤。


1. 重新构建模型

脚本会:

model = SegEarthR2.from_pretrained(...)

然后:

model.initial_mask_module(mask2former_ckpt, model_args)
model.get_model().initialize_vision_modules(model_args)

也就是说,它不是简单读取权重,而是先按模型结构把 SegEarthR2 重新搭起来。源码里 load_pretrained_model() 会读取 mask config,构建 SegEarthR2,初始化 mask module,再初始化视觉模块。(GitHub)


2. 重新注入 LoRA

脚本里也会调用:

find_linear_layers()
LoraConfig()
get_peft_model()

这一步必须和训练时的 LoRA 目标层一致。

它默认还是找:

q_proj
v_proj

并排除:

vision_tower
vision_tower_mask
lm_head
pixel_decoder
predictor
SEG_token_projector

这和训练时逻辑一致。


3. 从 DeepSpeed ZeRO checkpoint 恢复

核心代码是:

from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
model = load_state_dict_from_zero_checkpoint(model, model_path)

意思是:

DeepSpeed ZeRO 保存的分片权重
    ↓
恢复成完整 fp32 state_dict

这是使用 ZeRO-2 / ZeRO-3 后必须理解的一步。源码中合并脚本明确调用 load_state_dict_from_zero_checkpoint(),然后执行 model.merge_and_unload()。(GitHub)


4. 合并 LoRA

核心代码:

model = model.merge_and_unload()

含义:

基础权重 W
    +
LoRA 增量 ΔW
    ↓
合并成新的 W'

合并后就不再需要 LoRA adapter 单独存在。


5. 保存完整模型

最后:

model.save_pretrained(args.save_path, state_dict=state_dict)
tokenizer.save_pretrained(args.save_path)

这一步会保存成 HuggingFace 格式模型目录。

最终你应该得到类似:

outputs/merged_segearth_r2_lasers/
├── config.json
├── generation_config.json
├── model-00001-of-000xx.safetensors 或 pytorch_model.bin
├── tokenizer_config.json
├── tokenizer.model / tokenizer.json
├── special_tokens_map.json
└── ...

四、合并阶段最容易错的地方

错误 1:lora_r 不一致

表现:

size mismatch
shape mismatch

解决:

训练时 lora_r 是多少,合并时就是多少。

错误 2:model_path 指错

如果你传的是空目录,或者不是 DeepSpeed checkpoint 目录,会报:

checkpoint not found
latest file not found
zero checkpoint not found

解决:检查目录里是否有类似:

global_step*
zero_pp_rank*
mp_rank*
latest
checkpoint-*

错误 3:mask_config 和训练时不一致

表现:

pixel_decoder key mismatch
predictor key mismatch
hidden dim mismatch

解决:

合并、训练、评估三阶段必须使用同一个 mask_config。

错误 4:vision_tower_mask 权重版本不匹配

表现:

unexpected key
missing key
load_state_dict error

官方代码初始化分割模块时使用 strict=False 加载部分模块,但如果权重结构差异太大,仍会影响效果。合并脚本会传入 vision_tower_mask 并调用 initial_mask_module()。(GitHub)


五、合并后的测试命令

官方 test.sh 是:

deepspeed --include localhost:0 --master_port=29500 segearth_r2/eval/eval.py \
  --base_data_path data_path \
  --model_path model_path \
  --vision_tower_mask pretrained_model/mask2former/model_final_54b88a.pkl \
  --mask_config segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml \
  --output_dir output/res

其中 model_path 应该指向合并后的模型目录,而不是原始 Mipha-3B,也不是未合并的 LoRA adapter。官方评估文档同样要求运行 segearth_r2/eval/eval.py,并修改 base_data_pathmask_configmodel_pathoutput_dir 等路径。(GitHub)

你可以改成:

deepspeed --include localhost:0 --master_port=29500 segearth_r2/eval/eval.py \
  --base_data_path /your/path/LaSeRS \
  --model_path outputs/merged_segearth_r2_lasers \
  --vision_tower pretrained_model/CLIP/siglip-so400m-patch14-384 \
  --vision_tower_mask pretrained_model/mask2former/model_final_54b88a.pkl \
  --mask_config segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml \
  --output_dir outputs/eval_res

注意:官方 test.sh 没有显式传 --vision_tower,但 eval.pyArguments 里有默认 vision_tower="pretrained_model/CLIP"。如果你的 SigLIP 不在这个默认路径,一定要自己传 --vision_tower。(GitHub)


六、eval.py 总体流程

eval.py 可以分成 5 段:

1. 解析 Arguments
2. load_pretrained_model() 加载模型
3. 构造 SigLIP image processor 和 DataCollator
4. 遍历 LaSeRS test annotations
5. do_eval() 逐样本推理并计算 IoU

源码中 main() 会调用 load_pretrained_model() 加载 tokenizer、model、image processor 和 context length,然后设置 conversation template,构造 SiglipImageProcessorDataCollatorForCOCODatasetV2,再遍历 base_data_path/rs_reason_seg/LaSeRS/test/annotations 下的各个 split。(GitHub)


七、Arguments 参数类解释

eval.py 中定义了:

@dataclass
class Arguments:
    local_rank: int = 0
    vision_tower: str = "pretrained_model/CLIP"
    vision_tower_mask: str = "pretrained_model/mask2former/model_final_54b88a.pkl"
    base_data_path: Optional[str] = field(default='your_data_path')
    model_path: Optional[str] = field(default="SegEarthR2_LaSeRS/hfweights-50000")
    mask_config: Optional[str] = field(default="...")
    model_map_name: str = 'segearth_r2'
    version: str = 'llava_phi'
    temperature: float = 0.2
    num_beams: int = 1
    max_new_tokens: int = 128
    do_sample: bool = True
    output_dir: str = 'save_folder'
    dataloader_num_workers: int = 8

重点参数:

参数含义
vision_towerSigLIP 路径
vision_tower_maskMask2Former / Swin 权重路径
base_data_path数据集根目录
model_path合并后的 SegEarth-R2 模型路径
mask_configMask2Former 配置
temperature生成随机性
num_beamsbeam search 数量
max_new_tokens最大生成 token 数
do_sample是否采样生成
output_dir输出目录

这里有个小细节:官方 docs/Evaluation.md 命令里写了 --eval_batch_size 1,但当前 eval.pyArguments 片段中没有看到 eval_batch_size 字段,而代码里 dataloader 的 batch size 是固定写成 1。因此如果你运行时发现 --eval_batch_size 被识别为未知参数,就把这个参数删掉,按源码当前逻辑使用 batch size 1。(GitHub)


八、preprocess_input() 推理输入构造

eval.py 推理时并不是直接使用 dataloader 里的 input_ids,而是重新构造了一次输入。

核心函数:

preprocess_input(text, image_path, tokenizer, clip_image_processor)

它返回:

input_ids
images
images_clip

也就是和训练时一样,仍然有两路图像:

images      → Swin / Mask2Former 分割分支
images_clip → SigLIP / LLM 视觉塔

源码中 preprocess_input() 会先调用 preprocess_image(image_path) 构造主分割图像,并用 ImageNet mean/std 归一化;然后调用 preprocess_instruction() 构造文本 input_ids;最后调用 preprocess_image_clip() 构造 SigLIP 输入图像。(GitHub)


九、preprocess_instruction() 做了什么

推理时的 prompt 结构是:

sources = [[
    {'from': 'human', 'value': prefix_inst + '\n' + text},
    {'from': 'gpt', 'value': ''}
]]

其中 prefix_inst 是:

This is an image

, please doing Reasoning Segmentation according to the following instruction:

然后把用户指令 text 拼进去。

这说明推理时模型输入是:

Human:
This is an image, please doing Reasoning Segmentation according to the following instruction:
{遥感分割指令}

GPT:

模型需要继续生成 answer,并在生成过程中产生 [SEG]。源码中 preprocess_instruction() 使用 conversation template 拼接 prompt,并调用 tokenizer_special_tokens() 保留图像和 refer 特殊 token。(GitHub)


十、do_eval() 推理主循环

do_eval() 是评估核心。

主流程是:

model.eval()
torch.no_grad()
    ↓
获取 SEG_token_id
    ↓
遍历 eval_dataloader
    ↓
读取 text 和 image_path
    ↓
preprocess_input()
    ↓
model.inference()
    ↓
得到 output_ids 和 masks_pred
    ↓
读取 gt mask
    ↓
对齐 pred / gt 数量
    ↓
计算 IoU
    ↓
输出 split gIoU

源码中 do_eval() 会从 inputs['seg_info'][0]['instruction'] 取文本,从 inputs['seg_info'][0]['image_path'] 取图像路径,然后调用 model.inference(...) 得到 output_idsmasks_pred。(GitHub)


十一、model.inference() 关键理解

虽然我们这次重点看 eval.py,但你要把它和 llava_phi.py 接上。

推理阶段大致是:

input_ids + images_clip
    ↓
LLM generate
    ↓
生成 output_ids
    ↓
找到 output_ids 中的 [SEG]
    ↓
重新或同步取 [SEG] hidden state
    ↓
eval_seg()
    ↓
输出 masks_pred

训练时 [SEG] 来自 ground truth answer。

推理时 [SEG] 来自模型自己生成的 answer。

这就是训练和推理最大的区别:

训练:
answer 已知,里面本来就有 [SEG]

推理:
answer 未知,模型必须自己生成 [SEG]

如果推理时模型没有生成 [SEG],那就没有 mask query,最终 masks_pred 可能为空。


十二、为什么评估里要处理 masks_pred is None

源码中有这样的逻辑:

if masks_pred is None:
    H, W = images.shape[-2], images.shape[-1]
    masks_pred = np.zeros((n_gt, 1, H, W), dtype=np.uint8)

含义是:

如果模型没有预测出 mask,
就用全 0 mask 作为预测结果,
避免评估程序崩溃。

这也说明一个重要问题:

模型如果没有生成 [SEG],评估不一定报错,但 IoU 会很差。

所以复现时不能只看程序能跑完,还要看模型输出是否真的包含 [SEG]

源码中原本有打印模型输入和输出文本的代码,但被注释掉了。它会把生成文本中的 [SEG] 用颜色标出来。(GitHub)

你调试时建议把这段打开:

input_token_len = input_ids.shape[1]
generated_ids = output_ids[0][input_token_len:]
output_text = tokenizer.decode(generated_ids, skip_special_tokens=True)
print("Model Input:", text)
print("Model Output:", output_text)

你要确认输出里有:

[SEG]

十三、IoU 是怎么计算的

源码中每个预测 mask 和 GT mask 做:

inter = np.logical_and(pred_bin, gt_bin).sum()
union = np.logical_or(pred_bin, gt_bin).sum()
IoU += (inter / union) if union > 0 else 1.0

最后:

print(f"{split} gIoU: {IoU / overall_mask_num}")

也就是说这里的 gIoU 不是严格意义上目标检测里的 generalized IoU,而是所有 mask 的平均 IoU。源码中 do_eval() 会累计 overall_mask_numIUIoU,最后打印 split gIoU。(GitHub)

你可以理解为:

每个 mask 计算一个 IoU
    ↓
所有 mask 求平均
    ↓
输出 split gIoU

十四、评估时 pred 和 gt 数量如何对齐

源码中有一段很实用:

n_gt = len(gt_masks)

if masks_pred is None:
    masks_pred = zeros

n_pred = masks_pred.shape[0]

if n_pred < n_gt:
    masks_pred = np.concatenate([...], axis=0)
elif n_pred > n_gt:
    masks_pred = masks_pred[:n_gt]

含义:

如果预测 mask 少于 GT,就复制最后一个预测补齐;
如果预测 mask 多于 GT,就截断。

这让评估程序更加稳健,但从研究严谨性看,你要注意:

预测 mask 数量不等于 GT mask 数量,本身就说明模型生成 [SEG] 数量不稳定。

所以你复现时除了看 IoU,还应该统计:

生成 [SEG] 数量
预测 mask 数量
GT mask 数量
三者是否一致

十五、复现评估前的检查清单

在正式跑 eval.py 前,按下面顺序检查。

1. 合并模型目录是否完整

ls outputs/merged_segearth_r2_lasers

至少应该有:

config.json
tokenizer_config.json
special_tokens_map.json
模型权重文件

2. [SEG] token 是否存在

运行:

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("outputs/merged_segearth_r2_lasers")
print(tokenizer.encode("[SEG]", add_special_tokens=False))
print(tokenizer.convert_tokens_to_ids("[SEG]"))

你希望看到一个有效 id,而不是 unknown token。


3. 数据路径是否符合代码预期

eval.py 当前写死查找:

json_folders = os.path.join(
    data_args.base_data_path,
    'rs_reason_seg/LaSeRS/test/annotations'
)

也就是说你的实际目录应该类似:

base_data_path/
└── rs_reason_seg/
    └── LaSeRS/
        └── test/
            ├── annotations/
            └── images/

这一点和有些文档里直接写 train/imagestest/images 的理解可能不同。以当前 eval.py 源码为准。源码中 main() 明确使用 base_data_path/rs_reason_seg/LaSeRS/test/annotations 获取测试 split。(GitHub)


4. vision_tower 路径是否正确

如果你的 SigLIP 放在:

pretrained_model/CLIP/siglip-so400m-patch14-384

评估命令必须传:

--vision_tower pretrained_model/CLIP/siglip-so400m-patch14-384

否则 SiglipImageProcessor.from_pretrained(data_args.vision_tower) 可能找不到正确配置。源码中 main() 会用 data_args.vision_tower 初始化 SiglipImageProcessor。(GitHub)


5. batch size 先保持 1

评估代码中 dataloader batch size 固定为 1。不要一开始改 batch size,因为当前推理代码大量使用:

inputs['seg_info'][0]
inputs['mask_num'][0]

说明作者默认逐样本评估。源码中 dataloader_paramsbatch_size 固定为 1。(GitHub)


十六、建议你修改 eval.py 的几个调试点

为了真正吃透项目,我建议你临时加这些打印。


1. 打印输入文本

do_eval() 里:

print("instruction:", text)
print("image_path:", image_path)

确认模型看到的是正确指令。


2. 打印生成文本

取消官方注释,或者加:

input_token_len = input_ids.shape[1]
generated_ids = output_ids[0][input_token_len:]
output_text = tokenizer.decode(generated_ids, skip_special_tokens=False)
print("output_text:", output_text)
print("[SEG] count:", output_text.count("[SEG]"))

重点看:

output_text 是否包含 [SEG]
[SEG] 数量是否等于 gt mask 数量

3. 打印 mask 数量

print("n_gt:", n_gt)
print("n_pred:", None if masks_pred is None else masks_pred.shape[0])

如果长期 masks_pred is None,说明模型没有生成 [SEG]model.inference()[SEG] 解析失败。


4. 保存预测 mask 可视化

官方评估当前主要计算 IoU,没有明显保存彩色可视化结果。你可以在 do_eval() 中加:

save_dir = os.path.join(data_args.output_dir, split)
os.makedirs(save_dir, exist_ok=True)

pred_vis = (pred_bin * 255).astype(np.uint8)
cv2.imwrite(os.path.join(save_dir, f"{idx}_pred.png"), pred_vis)

gt_vis = (gt_bin * 255).astype(np.uint8)
cv2.imwrite(os.path.join(save_dir, f"{idx}_gt.png"), gt_vis)

这样你能直观看到:

模型到底分割了哪里
是完全空白
还是偏移
还是边界粗糙
还是目标类别错了

十七、完整复现闭环建议

你不要直接从全量训练开始,而是按下面做。


第一步:只验证模型能加载

python - <<'PY'
from segearth_r2.utils.builder import load_pretrained_model

model_path = "outputs/merged_segearth_r2_lasers"
mask_config = "segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml"

print("start load")
# 这里按项目 builder 的实际参数补齐
print("load ok")
PY

先不跑数据,确认模型权重没问题。


第二步:只取一张图推理

临时改 eval.py

if idx >= 1:
    break

确认:

能读图
能读文本
能生成 answer
能生成 [SEG]
能得到 masks_pred

第三步:跑一个 split

例如只跑一个测试 annotation 文件。

如果 test/annotations 下有多个 split,不要一开始全部跑。


第四步:跑完整测试集

完整跑:

deepspeed --include localhost:0 --master_port=29500 segearth_r2/eval/eval.py \
  --base_data_path /your/path \
  --model_path outputs/merged_segearth_r2_lasers \
  --vision_tower pretrained_model/CLIP/siglip-so400m-patch14-384 \
  --vision_tower_mask pretrained_model/mask2former/model_final_54b88a.pkl \
  --mask_config segearth_r2/model/mask_decoder/mask_config/maskformer2_swin_base_384_bs16_50ep.yaml \
  --output_dir outputs/eval_res \
  --dataloader_num_workers 2

十八、评估常见报错与解决

报错 1:unrecognized arguments: --eval_batch_size

原因:官方文档命令提到 --eval_batch_size 1,但当前 eval.py 的 dataclass 里没有该字段。(GitHub)

解决:删掉这个参数。


报错 2:FileNotFoundError: rs_reason_seg/LaSeRS/test/annotations

原因:base_data_path 指错。

解决:让路径满足:

base_data_path/rs_reason_seg/LaSeRS/test/annotations

或者改 eval.py 里的 json_folders 路径。


报错 3:SiglipImageProcessor 找不到配置

原因:--vision_tower 默认是 pretrained_model/CLIP,但你的 SigLIP 可能在更深目录。

解决:

--vision_tower pretrained_model/CLIP/siglip-so400m-patch14-384

报错 4:masks_pred is None 很多

可能原因:

模型没有生成 [SEG]
[SEG] token 没有正确加入 tokenizer
LoRA 没有合并好
推理 prompt 和训练 prompt 不一致
训练步数太少

优先检查:

print(output_text)
print(output_text.count("[SEG]"))

报错 5:IoU 很低但程序正常

可能原因:

mask 和 [SEG] 顺序错位
GT mask resize 有问题
模型只学会生成 [SEG] 但 mask decoder 没学好
Mask2Former 权重没正确加载
训练步数太少

检查:

pred mask 可视化
gt mask 可视化
[SEG] 数量
pred mask 数量
gt mask 数量

十九、训练、合并、评估三阶段参数必须一致

这是复现的铁律。

参数训练合并评估
model_name_or_path / model_pathMipha-3B训练 checkpoint合并后模型
vision_towerSigLIPSigLIPSigLIP
vision_tower_maskMask2Former 权重Mask2Former 权重Mask2Former 权重
mask_config同一个 yaml同一个 yaml同一个 yaml
lora_r例如 4必须 4合并后无需传
[SEG] tokenizer添加保存必须存在

如果你只记一句话:

训练、合并、评估的 mask_config、vision_tower、vision_tower_mask 必须一致。

二十、到目前为止的完整复现路线

现在我们已经把项目主线串起来了。

1. 安装环境
   ↓
2. 准备 Mipha-3B / SigLIP / Mask2Former / LaSeRS
   ↓
3. 修改 train.sh
   ↓
4. 跑 debug 20 steps
   ↓
5. 确认 loss_llm / loss_mask / loss_dice / loss_attention 正常
   ↓
6. 跑完整训练
   ↓
7. merge_lora_weights.sh 合并 LoRA
   ↓
8. 检查 tokenizer 中 [SEG]
   ↓
9. 修改 test.sh / eval.py 路径
   ↓
10. 单样本推理
   ↓
11. 可视化 pred mask
   ↓
12. 跑完整 test split
   ↓
13. 得到 IoU / gIoU

二十一、你现在应该掌握的核心结论

到这一讲为止,你应该能讲清楚:

1. 为什么训练后不能直接 eval,要先合并 LoRA。
2. merge_lora_weights.sh 如何恢复 ZeRO checkpoint。
3. 合并时 lora_r 必须和训练一致。
4. eval.py 重新构造 input_ids、images、images_clip。
5. 推理时 [SEG] 是模型自己生成的。
6. 如果没有生成 [SEG],masks_pred 可能是 None。
7. eval.py 当前默认 batch size 是 1。
8. IoU 是逐 mask 计算后平均。
9. 评估时必须检查生成文本里的 [SEG] 数量。
10. 训练、合并、评估的 vision_tower、vision_tower_mask、mask_config 必须一致。

下一讲:进入 RTX 5090 复现环境与编译问题

下一讲建议专门解决你最可能遇到的问题:

第 7 讲:RTX 5090 上复现 SegEarth-R2

重点:
1. CUDA 12.8 / PyTorch cu128 选择
2. Detectron2 编译
3. MSDeformAttn 编译
4. flash-attn 是否能装
5. DeepSpeed 安装
6. BF16 / TF32 设置
7. 常见 nvcc、sm_120、gcc、CUDA_HOME 报错
8. 单卡 RTX 5090 的推荐 train.sh

这部分非常关键,因为 SegEarth-R2 不是纯 Python 项目,真正卡人的地方往往不是模型逻辑,而是 Detectron2 + Mask2Former + MSDeformAttn + RTX 5090 编译环境

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值