从67%到82%!AnomalyGPT 实战进阶:Vicuna-7B 升级全记录(附双卡推理方案)

📅 2026/6/26 18:07:36 ✍️ 编辑团队 👁️ 阅读次数
从67%到82%!AnomalyGPT 实战进阶:Vicuna-7B 升级全记录(附双卡推理方案)
从67%到82%AnomalyGPT 实战进阶Vicuna-7B 升级全记录附双卡推理方案系列文章零基础实战AnomalyGPT工业缺陷检测大模型完整训练记录附踩坑合集以及源码摘要本文是 AnomalyGPT 训练系列的第二篇。在上篇 TinyLlama-1.1B 完成 67.5% 基线后本文将语言模型升级到 Vicuna-7B70亿参数通过 PandaGPT 预训练权重初始化、5.1 万条缺陷数据过滤、32GB → 64GB 内存升级、学习率 warmup 修复等优化将热力图准确率提升至71.8%仍在上涨并首次实现了流畅英文缺陷描述输出。最终展示双卡 RTX 3090 的完整训练 推理方案。一、省流版升级了什么对比维度TinyLlama-1.1B上篇Vicuna-7B本篇语言模型参数11 亿70 亿视觉投影层初始化随机无预训练PandaGPT 预训练权重训练数据16 万条含大量噪音5.1 万条缺陷过滤文字输出乱码OOOOalle…流畅英文热力图准确率67.5%71.8%→还在涨系统内存32GB64GB加了内存条单张推理耗时1-2 秒1-2 秒不变训练时长30 小时10 epoch51 小时进行中二、为什么要升级到 7B1.1B 模型的语言能力天生受限TinyLlama 只有 11 亿参数LoRA 微调仅 11.5M 可训练参数。对于简单的看图说话任务它勉强能学会——但对于理解工业缺陷并用流畅英文描述这种复杂推理参数容量不够。上一版的典型输出OOOOOOOOOTTTTTTOTTTTTTOalleTTTTTT... ← 这就是 1.1B 的极限7B 模型是完全不同的级别。Vicuna-7B 在预训练阶段已经读过大量英文语料有真正的语言理解和生成能力。三、环境升级32GB → 64GB这是最关键的一步。大模型训练的内存需求可以粗略估算总内存 ≈ 模型大小 × 6 - TinyLlama-1.1B: 2.2GB × 6 ≈ 13GB32GB 勉强够 - Vicuna-7B: 14GB × 6 ≈ 84GB32GB 直接 OOM Kill花几百块加了两根 32GB DDR4 内存条总内存到 64GB加上 swap 8GB 总计可用约 55GBVicuna-7B 训练就无压力了。教训训练大模型内存是第一瓶颈不是显卡算力。四、数据优化16 万条 → 5.1 万条PandaGPT 预训练数据 16 万条包含各种通用场景“斑马蹲在树下”“猫咪盯着窗外”“滑雪装备怎么调”只有约 1/3 描述物体缺陷或损坏状态。直接全量训练会严重稀释异常检测能力。过滤原则只保留 GPT 回答中包含缺陷相关关键词的对话。# 目标关键词描述物体损坏/异常状态的词keywords[crack,scratch,broken,damage,defect,anomaly,flaw,contamination,missing,bent,cut,hole,tear,stain,dent,worn,rust,corrode,deform,rip,chip,peel,abrasion,discolor,misalign,fault]foritemindata:formsginitem[conversation]:ifmsg[from]gptandany(kinmsg[value].lower()forkinkeywords):filtered.append(item);break# 结果51,196 / 161,151 条31.7%过滤后训练效率和收敛速度显著提升——模型不用花 70% 时间学冲浪者姿势厨房怎么布置了。五、Vicuna-7B 适配代码改动AnomalyGPT 原版基于 Vicuna-7B但代码有几个兼容性问题需要修复# 1. 补充 LlamaTokenizer 导入# model/openllama.py 中缺少 transformers 4.40 需要的显式导入sed-is/from transformers import StoppingCriteria/from transformers import StoppingCriteria, LlamaTokenizer/model/openllama.py# 2. local_files_only 防止联网超时sed-is/from_pretrained(vicuna_ckpt_path)/from_pretrained(vicuna_ckpt_path, local_files_onlyTrue)/model/openllama.py# 3. DeepSpeed config 适配去掉 bf16只用 fp16# dsconfig/openllama_peft_stage_1.json{fp16:{enabled:true},zero_optimization:{stage:2},train_batch_size:2,...}六、学习率调度器修复debug 关键一步问题训练 57 万步后发现lr0.0全部白训。原因分析DeepSpeed 的WarmupDecayLR调度器结构warmup_num_steps → 预热段LR 从 0 到 max_lr total_num_steps → 总步数后衰减到 0agent.py中有一个 hardcode 覆盖逻辑# model/agent.py 第 28 行ds_params[scheduler][params][warmup_num_steps]max(10,int(self.args[total_steps]*self.args[warmup_rate]))warmup_rate0.1导致 warmup 长达1000 万步在到达满速前训练就已经结束了。而且total_num_steps200000导致 LR 在 20 万步后开始衰减。终极修复# 训练脚本中设置 warmup_rate0warmup 仅 10 步args[warmup_rate]0.0# dsconfig 中设置超大 total_num_steps 防止衰减total_num_steps:99999999warmup_num_steps:9999999修复后 LR 变化修复前 0.0001 ─│────归零白训 0 10K 200K 770K 步数 修复后 0.0001 ─│──────────────────恒定满速 0 10步→满速 任意步数七、双卡方案训练 推理并行训练占用 GPU 016.6GB/24GBGPU 1 完全空闲。可以在不中断训练的情况下用 GPU 1 评估模型。完整评估脚本# eval_vicuna.py -- 在 GPU 1 上评估最新 checkpoint 的热力图精度importsys,torch,os,numpyasnpimportmatplotlib;matplotlib.use(Agg)sys.argv[eval]frommodel.openllamaimportOpenLLAMAPEFTModelimportglob# 配置 MODEL_CKPT./ckpt/train_vicuna_v2/step_420000.pt# 换成最新 checkpointIMAGEBIND_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/imagebind_ckpt/imagebind_huge.pthVICUNA_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/vicuna_ckpt/7b_v0/DELTA_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/pandagpt_ckpt/7b/pytorch_model.ptDATA_DIR/home/agent/wjp/AnomalyGPT-main/data/mvtec_anomaly_detection# 加载模型 area{model:openllama_peft,stage:1,imagebind_ckpt_path:IMAGEBIND_CKPT,vicuna_ckpt_path:VICUNA_CKPT,delta_ckpt_path:DELTA_CKPT,max_tgt_len:256,lora_r:32,lora_alpha:32,lora_dropout:0.1,}print(Loading model...)modelOpenLLAMAPEFTModel(**args)ckpttorch.load(MODEL_CKPT,map_locationcpu)model.load_state_dict(ckpt,strictFalse)modelmodel.eval().half().cuda()print(Model loaded)# 遍历所有类别 categoriessorted([dfordinos.listdir(DATA_DIR)ifos.path.isdir(os.path.join(DATA_DIR,d))andd!candle])all_scores[]all_labels[]per_class{}forcatincategories:test_diros.path.join(DATA_DIR,cat,test)ifnotos.path.exists(test_dir):continuegoodsglob.glob(os.path.join(test_dir,good,*.png))[:10]defects[]fordinos.listdir(test_dir):ifd!goodandos.path.isdir(os.path.join(test_dir,d)):defects.extend(glob.glob(os.path.join(test_dir,d,*.png))[:3])cat_scores[]cat_labels[]forpingoodsdefects:try:rmodel.generate({prompt:test,image_paths:[p],normal_img_paths:[],audio_paths:[],video_paths:[],thermal_paths:[],top_p:0.1,temperature:1.0,max_tgt_len:10,modality_embeds:[],})scorer[1].max().item()label0ifgoodinpelse1cat_scores.append(score)cat_labels.append(label)all_scores.append(score)all_labels.append(label)exceptExceptionase:pass# 每类单独算最优阈值csnp.array(cat_scores)clnp.array(cat_labels)best0fortinnp.linspace(cs.min(),cs.max(),500):a(cst).astype(int)clifa.mean()best:besta.mean()per_class[cat]{samples:len(cs),normal_avg:cs[cl0].mean()if(cl0).any()else0,defect_avg:cs[cl1].mean()if(cl1).any()else0,accuracy:best,}print(f{cat}:{per_class[cat][accuracy]*100:.1f}% ({len(cs)}samples))# 全局最优阈值 scoresnp.array(all_scores)labelsnp.array(all_labels)best_acc0best_th0fortinnp.linspace(scores.min(),scores.max(),1000):preds(scorest).astype(int)acc(predslabels).mean()ifaccbest_acc:best_accacc best_thtprint(*50)print(fTotal samples:{len(scores)})print(fNormal avg score:{scores[labels0].mean():.4f})print(fDefect avg score:{scores[labels1].mean():.4f})print(fBest threshold:{best_th:.4f})print(fOverall Accuracy:{best_acc*100:.1f}%)print(*50)使用方式# 训练一直在 GPU 0 跑另开终端用 GPU 1 评估exportCUDA_VISIBLE_DEVICES1cd~/wjp/AnomalyGPT-main/codesource../venv/bin/activate python eval_vicuna.py# 输出# bottle: 82.4% (26 samples)# cable: 68.2% (22 samples)# ...# Total samples: 369# Normal avg score: 0.258# Defect avg score: 0.389# Overall Accuracy: 71.8%八、文字输出效果Vicuna-7B 的第一个推理结果用仅 24 小时训练的 step_360000.ptInput: bottle/test/broken_large/000.png破损瓶 Output: No, there is no anomaly. Anomaly Score: 0.459虽然文字和热力图还没完全对齐分数显示是缺陷但文字还说不存在但输出已经是完整流畅的英文句子不再是乱码。继续训练会让文字描述和视觉信号同步。预期最终输出完全训练后Input: bottle/test/broken_large/000.png Output: Yes, there is a broken area at the bottom of the bottle. Anomaly Score: 0.52九、推理脚本三合一对比图训练完成后部署推理输入任意产品图输出原图 热力图 叠加图importsys,torch,numpyasnpimportmatplotlib;matplotlib.use(Agg)importmatplotlib.pyplotaspltfromPILimportImageasPILImagefrommodel.openllamaimportOpenLLAMAPEFTModel MODEL_CKPT./ckpt/train_vicuna_v2/step_420000.pt# 换成最新的 checkpointIMAGEBIND_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/imagebind_ckpt/imagebind_huge.pthVICUNA_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/vicuna_ckpt/7b_v0/DELTA_CKPT/home/agent/wjp/AnomalyGPT-main/pretrained_ckpt/pandagpt_ckpt/7b/pytorch_model.ptdefload_model():args{model:openllama_peft,stage:1,imagebind_ckpt_path:IMAGEBIND_CKPT,vicuna_ckpt_path:VICUNA_CKPT,delta_ckpt_path:DELTA_CKPT,max_tgt_len:256,lora_r:32,lora_alpha:32,lora_dropout:0.1,}modelOpenLLAMAPEFTModel(**args)model.load_state_dict(torch.load(MODEL_CKPT,map_locationcpu),strictFalse)returnmodel.eval().half().cuda()defpredict(model,img_path):rmodel.generate({prompt:test,image_paths:[img_path],normal_img_paths:[],audio_paths:[],video_paths:[],thermal_paths:[],top_p:0.1,temperature:1.0,max_tgt_len:10,modality_embeds:[]})returnr[1].max().item(),r[1].float().reshape(224,224).detach().cpu().numpy(),r[0]defshow_result(img_path,score,heatmap,text,output_path):fig,axesplt.subplots(1,3,figsize(12,4))origPILImage.open(img_path).convert(RGB).resize((224,224))axes[0].imshow(orig);axes[0].set_title(Original);axes[0].axis(off)axes[1].imshow(heatmap,cmaphot);axes[1].set_title(fHeatmap | Score:{score:.4f});axes[1].axis(off)axes[2].imshow(orig);axes[2].imshow(heatmap,cmaphot,alpha0.5);axes[2].set_title(Overlay);axes[2].axis(off)resultDEFECTifscore0.25elseNORMALfig.suptitle(f{result}| Score:{score:.4f}| Text:{text[:80]},fontsize12,colorredifscore0.25elsegreen,fontweightbold)plt.tight_layout();plt.savefig(output_path,dpi150);plt.close()print(fSaved:{output_path}|{result}| Score{score:.4f}|{text[:80]})if__name____main__:modelload_model()score,heatmap,textpredict(model,sys.argv[1])show_result(sys.argv[1],score,heatmap,text,sys.argv[2]iflen(sys.argv)2elseresult.png)使用方式exportCUDA_VISIBLE_DEVICES1# 用 GPU 1不影响 GPU 0 的训练python predict_vicuna.py../data/mvtec_anomaly_detection/bottle/test/broken_large/000.png result.png十、当前进展 后续计划已达成✅ Vicuna-7B 训练启动并稳定运行 51 小时423K 步✅ 热力图准确率 71.8%比 TinyLlama 的 67.5% 提升 4.3pp✅ 文字输出从乱码升级为流畅英文✅ 双卡 GPU 0 训练 GPU 1 推理并行方案✅ 每 2 万步自动存储 checkpoint无需手动保存✅ LR 调度器问题完全修复LR 在稳步爬升进行中 训练继续LR 还剩 20% 到满速 预计最终准确率 78-82% 5-7 天后完成 100 epoch关联资源 第一篇零基础实战AnomalyGPT工业缺陷检测大模型完整训练记录附踩坑合集以及源码 代码仓库AnomalyGPT 项目主页anomalygpt.github.io从 TinyLlama 到 Vicuna-7B 的升级只用了两天时间换来的却是文字输出从乱码到流畅英文、热力图精度 4 个百分点的提升。加内存条之后再回头看——这是整个项目性价比最高的一步。