多模態(tài)雙 Transformer(MMBT)分類模型實(shí)戰(zhàn)指南)
推理引擎大模型【免費(fèi)下載鏈接】FlexGenRunning large language models on a single GPU for throughput-oriented scenarios.項(xiàng)目地址https://gitcode.com/gh_mirrors/fl/FlexGen點(diǎn)擊查看免費(fèi)下載本文以當(dāng)前倉(cāng)庫(kù)中 mm-imdb 示例目錄 的官方 README 為核心骨架完整講解如何利用run_mmimdb.py在 MM-IMDb 多模態(tài)數(shù)據(jù)集上訓(xùn)練與評(píng)估一個(gè)融合「電影海報(bào)圖像 劇情文本」的 MMBTMultimodal Bitransformer多標(biāo)簽分類模型。讀完本文你將掌握 MM-IMDb 數(shù)據(jù)集的構(gòu)成、MMBT 的模態(tài)融合原理、完整可復(fù)制的訓(xùn)練命令與全部參數(shù)含義并能結(jié)合倉(cāng)庫(kù)源碼理解從數(shù)據(jù)加載、圖像編碼到早停評(píng)估的整條調(diào)用鏈。一、MM-IMDb 數(shù)據(jù)集與 MMBT 模型簡(jiǎn)介MM-IMDb 是一個(gè)多模態(tài)Multimodal數(shù)據(jù)集包含約 26,000 部電影每部電影同時(shí)攜帶海報(bào)圖像、劇情簡(jiǎn)介plots以及其他元數(shù)據(jù)metadata。它天然適合訓(xùn)練一個(gè)「看圖 讀文」的聯(lián)合分類模型模型需要同時(shí)利用電影海報(bào)的視覺(jué)信息與劇情文本的語(yǔ)義信息為電影打上類型標(biāo)簽。在 run_mmimdb.py 對(duì)應(yīng)的研究項(xiàng)目中采用的模型是 MMBTSupervised Multimodal Bitransformer。從 modeling_mmbt.py 的模型說(shuō)明可以看到MMBT 是一種有監(jiān)督的多模態(tài)雙 Transformer 模型它把文本編碼器如 BERT與另一個(gè)模態(tài)此處為圖像的編碼器輸出的特征融合起來(lái)再送入同一個(gè) Transformer 編碼器進(jìn)行聯(lián)合建模從而在多模態(tài)分類基準(zhǔn)上取得當(dāng)時(shí)領(lǐng)先的效果。在 MM-IMDb 場(chǎng)景中兩個(gè)編碼器分別是文本編碼器bert-base-uncased等預(yù)訓(xùn)練 BERT由--model_name_or_path指定圖像編碼器ResNet-152詳見下文「圖像編碼器」小節(jié)。二、訓(xùn)練環(huán)境準(zhǔn)備本示例位于倉(cāng)庫(kù)的第三方依賴目錄下屬于 Hugging Face Transformers 的研究型示例research_projects。運(yùn)行腳本前需要確認(rèn) Python 環(huán)境已安裝 PyTorch 與 Transformers 相關(guān)依賴安裝倉(cāng)庫(kù)維護(hù)的 Transformers fork。根據(jù) benchmark/third_party/README.md 的說(shuō)明當(dāng)前倉(cāng)庫(kù)維護(hù)的是 huggingface/transformers v4.24.0 的 fork可按如下方式安裝cd FlexGen/benchmark/third_party/transformers pip3 install -e . pip3 install accelerate0.15.0腳本還依賴sklearn用于 F1 指標(biāo)計(jì)算、torchvision用于 ResNet-152 圖像編碼器、Pillow用于圖像讀取以及 TensorBoardtorch.utils.tensorboard缺失時(shí)腳本會(huì)回退到tensorboardX見 run_mmimdb.py。注意本示例腳本是為研究實(shí)驗(yàn)設(shè)計(jì)的并不依賴 GPU 加速以外的特殊硬件CPU 亦可運(yùn)行但訓(xùn)練速度會(huì)顯著變慢。三、在 MM-IMDb 上訓(xùn)練與評(píng)估的完整命令README 給出了一個(gè)可直接復(fù)制的訓(xùn)練命令模板。請(qǐng)將其中的路徑替換為你本機(jī)的真實(shí)路徑python run_mmimdb.py \ --data_dir /path/to/mmimdb/dataset/ \ --model_type bert \ --model_name_or_path bert-base-uncased \ --output_dir /path/to/save/dir/ \ --do_train \ --do_eval \ --max_seq_len 512 \ --gradient_accumulation_steps 20 \ --num_image_embeds 3 \ --num_train_epochs 100 \ --patience 5對(duì)上述命令的解讀與源碼中的參數(shù)定義逐一對(duì)應(yīng)命令行參數(shù)源碼默認(rèn)值作用說(shuō)明--data_dir無(wú)必填MM-IMDb 數(shù)據(jù)目錄內(nèi)部應(yīng)包含train.jsonl與dev.jsonl兩個(gè) JSONL 文件源碼在 load_examples 中按evaluate標(biāo)志拼接文件名讀取--model_name_or_path無(wú)必填預(yù)訓(xùn)練模型路徑或 huggingface.co 上的模型標(biāo)識(shí)如bert-base-uncased--output_dir無(wú)必填模型預(yù)測(cè)結(jié)果與檢查點(diǎn)checkpoint的輸出目錄--do_trainFalse是否執(zhí)行訓(xùn)練--do_evalFalse是否在 dev 集上執(zhí)行評(píng)估--max_seq_lenmax_seq_length128文本 token 化的最大序列長(zhǎng)度注意 README 中寫作max_seq_len而源碼參數(shù)名實(shí)際為max_seq_length見 run_mmimdb.py使用時(shí)以源碼參數(shù)名為準(zhǔn)--gradient_accumulation_steps1梯度累積步數(shù)即累積多少步更新后再執(zhí)行一次反向/更新--num_image_embeds1圖像編碼器輸出的圖像嵌入數(shù)量決定后續(xù) AdaptiveAvgPool2d 的池化尺寸--num_train_epochs3.0訓(xùn)練總輪數(shù)README 示例中用 100 配合早停使用--patience5早停Early Stopping耐心值連續(xù)多少個(gè) epoch 的 micro-F1 未創(chuàng)新高則提前終止訓(xùn)練只要保證--data_dir下存在train.jsonl/dev.jsonl并把--output_dir指向一個(gè)當(dāng)前為空或不存在的可寫目錄上述命令即可完成「訓(xùn)練 評(píng)估」全流程。四、核心代碼路徑與關(guān)鍵調(diào)用鏈解析README 雖短但其背后是兩條彼此獨(dú)立、可分別復(fù)用的代碼路徑。理解它們有助于你調(diào)試或把該多模態(tài)方案遷移到自己的數(shù)據(jù)上。4.1 數(shù)據(jù)加載與多模態(tài)樣本構(gòu)造訓(xùn)練與評(píng)估共用同一套數(shù)據(jù)管道入口是 load_examples()def load_examples(args, tokenizer, evaluateFalse): path os.path.join(args.data_dir, dev.jsonl if evaluate else train.jsonl) transforms get_image_transforms() labels get_mmimdb_labels() dataset JsonlDataset(path, tokenizer, transforms, labels, args.max_seq_length - args.num_image_embeds - 2)這里有一個(gè)值得注意的細(xì)節(jié)傳給數(shù)據(jù)集的文本最大長(zhǎng)度是args.max_seq_length - args.num_image_embeds - 2。減法中的- 2是因?yàn)?JsonlDataset.getitem會(huì)把 tokenize 后句子的首 token通常是[CLS]和尾 token通常是[SEP]拆出來(lái)分別作為「圖像起始 token」與「圖像結(jié)束 token」而- num_image_embeds是為拼接在前的圖像嵌入預(yù)留的序列長(zhǎng)度。這樣拼接后的總序列長(zhǎng)度恰好不超過(guò)max_seq_length。具體的數(shù)據(jù)結(jié)構(gòu)由 utils_mmimdb.py 定義JsonlDataset讀取 JSONL 文件每行是一個(gè)電影樣本字段至少包含text劇情文本、img相對(duì)data_dir的圖像路徑與label類型標(biāo)簽列表。__getitem__返回image_start_token、image_end_token、sentence、image、label五個(gè)字段。collate_fn把一批樣本整理成定長(zhǎng)張量返回順序?yàn)?text_tensor, mask_tensor, img_tensor, img_start_token, img_end_token, tgt_tensor)——這與訓(xùn)練/評(píng)估循環(huán)中batch[0]~batch[5]的取用方式一一對(duì)應(yīng)見 run_mmimdb.py 的 train。get_mmimdb_labels()返回 23 個(gè)電影類型標(biāo)簽Crime、Drama、Thriller、Action、Comedy、Romance、Documentary、Short、Mystery、History、Family、Adventure、Fantasy、Sci-Fi、Western、Horror、Sport、War、Music、Musical、Animation、Biography、Film-Noir標(biāo)簽以 one-hot 多標(biāo)簽形式編碼。4.2 圖像編碼器ResNet-152 自適應(yīng)平均池化ImageEncoder是圖像模態(tài)的核心組件model torchvision.models.resnet152(pretrainedTrue) modules list(model.children())[:-2] # 去掉最后的 avgpool 與全連接層 self.model nn.Sequential(*modules) self.pool nn.AdaptiveAvgPool2d(POOLING_BREAKDOWN[args.num_image_embeds])其 forward 的維度變換注釋為Bx3x224x224 - Bx2048x7x7 - Bx2048xN - BxNx2048即輸入3×224×224的 RGB 海報(bào)圖像224 來(lái)自 get_image_transforms 中的 Resize(256) CenterCrop(224) 預(yù)處理并做了針對(duì)該數(shù)據(jù)集的均值/方差歸一化經(jīng)過(guò) ResNet-152 骨干輸出2048×7×7特征圖由AdaptiveAvgPool2d池化到N個(gè)位置N --num_image_embeds展平并轉(zhuǎn)置為B×N×2048其中2048正是MMBTConfig中modal_hidden_size的默認(rèn)值。POOLING_BREAKDOWN表見 utils_mmimdb.py規(guī)定了不同num_image_embeds對(duì)應(yīng)的池化網(wǎng)格num_image_embeds池化尺寸1(1, 1)2(2, 1)3(3, 1)4(2, 2)5(5, 1)6(3, 2)7(7, 1)8(4, 2)9(3, 3)4.3 MMBT 模態(tài)融合文本與圖像在 Embedding 層拼接模型的組裝發(fā)生在 run_mmimdb.py 的 main() 中transformer_config AutoConfig.from_pretrained(...) tokenizer AutoTokenizer.from_pretrained(...) transformer AutoModel.from_pretrained(...) img_encoder ImageEncoder(args) config MMBTConfig(transformer_config, num_labelsnum_labels) model MMBTForClassification(config, transformer, img_encoder)其中MMBTConfig會(huì)把文本 Transformer 的全部配置屬性拷貝過(guò)來(lái)并追加modal_hidden_size2048與num_labels見 configuration_mmbt.py。本任務(wù)中num_labels 23對(duì)應(yīng) 23 個(gè)電影類型標(biāo)簽。從 modeling_mmbt.py 的 MMBTModel 可以看到融合方式ModalEmbeddings先把圖像編碼器的輸出B×N×2048經(jīng)一個(gè)線性層投影到 BERT 的hidden_size768再在序列最前面拼接start_token[CLS]的 word embedding、在末尾拼接end_token[SEP]的 word embedding并加上位置與 token type 嵌入文本側(cè)按正常流程取 BERT 的 word 嵌入兩者沿序列維torch.cat成一個(gè)完整的嵌入序列送入 BERT 的 Transformer encoder 做聯(lián)合自注意力建模MMBTForClassification取池化輸出經(jīng)過(guò) Dropout 與一個(gè)nn.Linear(hidden_size, num_labels)分類頭得到 logits見 modeling_mmbt.py。也就是說(shuō)MMBT 并沒(méi)有在 Transformer 之后做簡(jiǎn)單的向量拼接而是讓圖像特征以「虛擬 token」的身份進(jìn)入 BERT 的注意力層與文本 token 進(jìn)行深度交互——這正是它被稱為 Bitransformer 的原因。五、訓(xùn)練循環(huán)、損失函數(shù)與早停機(jī)制5.1 多標(biāo)簽損失與類別不均衡處理由于電影可以同時(shí)屬于多個(gè)類型腳本沒(méi)有使用交叉熵而是在 main() 中構(gòu)造了帶正樣本權(quán)重pos_weight的二元交叉熵label_frequences train_dataset.get_label_frequencies() label_frequences [label_frequences[l] for l in labels] label_weights (torch.tensor(label_frequences) / len(train_dataset)) ** -1 criterion nn.BCEWithLogitsLoss(pos_weightlabel_weights)get_label_frequencies()統(tǒng)計(jì)每個(gè)類型在訓(xùn)練集中的出現(xiàn)次數(shù)見 utils_mmimdb.py罕見類別的pos_weight更大從而緩解類型分布不均帶來(lái)的訓(xùn)練偏向。5.2 訓(xùn)練循環(huán)的關(guān)鍵步驟train()實(shí)現(xiàn)了完整的訓(xùn)練管線要點(diǎn)包括優(yōu)化器與調(diào)度器使用AdamW且對(duì)bias與LayerNorm.weight不施加 weight decay配合get_linear_schedule_with_warmup線性預(yù)熱與衰減默認(rèn)learning_rate5e-5、weight_decay0.0、warmup_steps0梯度累積loss 除以gradient_accumulation_steps后再反向滿足 README 示例中「小 batch 大累積」的訓(xùn)練策略混合精度通過(guò)--fp16啟用 NVIDIA Apex AMPfp16_opt_level默認(rèn)O1分布式與多卡單卡多 GPU 時(shí)自動(dòng)套nn.DataParallel多機(jī)時(shí)通過(guò)--local_rank走DistributedDataParallelfind_unused_parametersTrue檢查點(diǎn)保存每--save_steps默認(rèn) 50步保存checkpoint-{global_step}內(nèi)含pytorch_model.bin與training_args.binTensorBoard 日志主進(jìn)程記錄 loss 與學(xué)習(xí)率等標(biāo)量按--logging_steps默認(rèn) 50輸出。5.3 基于 micro-F1 的早停每個(gè) epoch 結(jié)束后腳本都會(huì)在 dev 集上評(píng)估一次并以 micro-F1 作為早停指標(biāo)見 run_mmimdb.pyresults evaluate(args, model, tokenizer, criterion) if results[micro_f1] best_f1: best_f1 results[micro_f1] n_no_improve 0 else: n_no_improve 1 if n_no_improve args.patience: train_iterator.close() break這正是 README 示例中把--num_train_epochs設(shè)為 100、--patience設(shè)為 5 的原因模型最多訓(xùn)練 100 輪但一旦連續(xù) 5 輪 micro-F1 沒(méi)有提升就提前停止兼顧效果與時(shí)間成本。5.4 評(píng)估指標(biāo)evaluate()在 dev 集上以sigmoid(logits) 0.5作為多標(biāo)簽判定閾值并計(jì)算三個(gè)指標(biāo)loss平均二元交叉熵?fù)p失macro_f1每個(gè)類型 F1 的算術(shù)平均averagemacromicro_f1按樣本-標(biāo)簽對(duì)整體統(tǒng)計(jì)的 F1averagemicro是早停與最優(yōu)模型選擇的核心指標(biāo)。結(jié)果會(huì)寫入output_dir/{prefix}/eval_results.txt訓(xùn)練結(jié)束后若--do_eval開啟腳本還會(huì)對(duì)output_dir下保存的模型權(quán)重做最終評(píng)估若加--eval_all_checkpoints則逐一評(píng)估所有 checkpoint見 run_mmimdb.py。六、其他常用訓(xùn)練參數(shù)速查除上述命令涉及的參數(shù)外腳本還支持一系列常用的微調(diào)參數(shù)默認(rèn)值與含義均來(lái)自 run_mmimdb.py 的 argparse 定義參數(shù)默認(rèn)值說(shuō)明--config_name/--tokenizer_name與模型名不同的配置/分詞器名稱或路徑--cache_dirNone預(yù)訓(xùn)練模型下載緩存目錄--per_gpu_train_batch_size8每 GPU 訓(xùn)練 batch 大小--per_gpu_eval_batch_size8每 GPU 評(píng)估 batch 大小--learning_rate5e-5Adam 初始學(xué)習(xí)率--weight_decay0.0權(quán)重衰減系數(shù)--adam_epsilon1e-8Adam 優(yōu)化器 epsilon--max_grad_norm1.0梯度裁剪范數(shù)上限--max_steps-1若大于 0則覆蓋num_train_epochs限定總訓(xùn)練步數(shù)--warmup_steps0線性預(yù)熱步數(shù)--logging_steps50每多少更新步記錄一次日志--save_steps50每多少更新步保存一次 checkpoint--evaluate_during_trainingFalse訓(xùn)練過(guò)程中是否在每個(gè)日志步執(zhí)行評(píng)估--eval_all_checkpointsFalse評(píng)估所有 checkpoint--no_cudaFalse強(qiáng)制不使用 CUDA--num_workers8DataLoader 數(shù)據(jù)加載線程數(shù)--overwrite_output_dirFalse允許覆蓋非空的輸出目錄否則訓(xùn)練前會(huì)報(bào)錯(cuò)退出--overwrite_cacheFalse覆蓋緩存的數(shù)據(jù)集--seed42隨機(jī)種子腳本在訓(xùn)練前通過(guò)set_seed固定--fp16/--fp16_opt_levelFalse/O1是否啟用 Apex 混合精度及其 AMP 優(yōu)化級(jí)別--local_rank-1分布式訓(xùn)練的 local_rank-1 表示單進(jìn)程--server_ip/--server_port遠(yuǎn)程調(diào)試ptvsd附加地址一個(gè)值得強(qiáng)調(diào)的坑README 示例中的--max_seq_len與源碼 argparse 定義的--max_seq_length不一致。若直接照抄 README程序會(huì)因未知參數(shù)報(bào)錯(cuò)實(shí)際運(yùn)行時(shí)應(yīng)使用--max_seq_length 512。七、進(jìn)階把多模態(tài)方案遷移到自己的數(shù)據(jù)若希望復(fù)用這套代碼處理自己的「圖像 文本」多標(biāo)簽任務(wù)可以遵循以下最小改造路徑當(dāng)前倉(cāng)庫(kù)為只讀請(qǐng)?jiān)诒镜亓斫ǜ北拘薷臏?zhǔn)備 JSONL 數(shù)據(jù)仿照 MM-IMDb 格式每行包含text文本內(nèi)容、img相對(duì)數(shù)據(jù)目錄的圖像路徑、label標(biāo)簽名列表并拆分為train.jsonl與dev.jsonl替換標(biāo)簽表修改get_mmimdb_labels()返回你自己的標(biāo)簽列表適配圖像統(tǒng)計(jì)量若圖像內(nèi)容差異大可重新統(tǒng)計(jì)均值/方差并修改get_image_transforms()中的 Normalize 參數(shù)調(diào)整池化--num_image_embeds控制圖像特征 token 數(shù)若圖像分辨率或語(yǔ)義粒度不同可通過(guò)POOLING_BREAKDOWN表格重新映射更換文本底座--model_name_or_path支持任何 AutoModel 兼容的預(yù)訓(xùn)練文本模型如bert-base-uncasedMMBT 會(huì)自動(dòng)把其 hidden size 作為融合維度。八、總結(jié)MM-IMDb 示例是理解 MMBT 多模態(tài)建模范式的絕佳入口。其 README 雖然簡(jiǎn)短但背后由 run_mmimdb.py 與 utils_mmimdb.py 構(gòu)成了一個(gè)完整、可復(fù)現(xiàn)的實(shí)驗(yàn)閉環(huán)JSONL 多模態(tài)數(shù)據(jù)加載 → ResNet-152 圖像編碼 → MMBT 嵌入級(jí)模態(tài)融合 → 帶類別權(quán)重的多標(biāo)簽 BCE 訓(xùn)練 → 基于 micro-F1 的早停與評(píng)估。掌握它之后無(wú)論是復(fù)現(xiàn) MM-IMDb 基準(zhǔn)、實(shí)驗(yàn)不同num_image_embeds的圖像特征粒度還是遷移到自定義多模態(tài)分類任務(wù)你都能快速上手。贊分享推理引擎大模型【免費(fèi)下載鏈接】FlexGenRunning large language models on a single GPU for throughput-oriented scenarios.項(xiàng)目地址https://gitcode.com/gh_mirrors/fl/FlexGen點(diǎn)擊查看免費(fèi)下載相關(guān)推薦使用 Flower 與 Hugging Face Transformers 聯(lián)邦微調(diào)大語(yǔ)言模型IMDB 情感分類快速入門指南使用 Flower 與 Hugging Face Transformers 聯(lián)邦微調(diào)大語(yǔ)言模型IMDB 情感分類快速入門指南 本指南基于 Flower 官方人工智能聯(lián)邦學(xué)習(xí)機(jī)器學(xué)習(xí)深度學(xué)習(xí)CANN/asc-devkitAscend C SIMD API存儲(chǔ)非對(duì)齊數(shù)據(jù)接口asc_storeunalign_post_postupdate 產(chǎn)品支持情況 | 產(chǎn)品 | 是否支持 | | : | : :| | Ascend 950PR/人工智能深度學(xué)習(xí)算子庫(kù)CANNAscendHugging Face課程Transformer模型調(diào)試實(shí)戰(zhàn)指南Hugging Face課程Transformer模型調(diào)試實(shí)戰(zhàn)指南 引言 在自然語(yǔ)言處理 NLP 項(xiàng)目中使用預(yù)訓(xùn)練Transformer模型進(jìn)行微調(diào)和推理時(shí)文檔教程人工智能NLP深度學(xué)習(xí)上一篇PluginEval 錨定評(píng)分標(biāo)準(zhǔn)全解judge 四維 Rubrics 的分級(jí)細(xì)則與源碼實(shí)現(xiàn)下一篇RuView homecore-server 運(yùn)維評(píng)審清單從 homecore metaharness 的 operate-server playbook 到服務(wù)器源碼的逐項(xiàng)印證創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考