練閉環(huán),一次講透度量學(xué)習(xí)模型評(píng)估)
pytorch-metric-learning Testers 完整指南從選型到訓(xùn)練閉環(huán)一次講透度量學(xué)習(xí)模型評(píng)估【免費(fèi)下載鏈接】ocpFAIR Chemistrys library of machine learning methods for chemistry項(xiàng)目地址: https://gitcode.com/GitHub_Trending/oc/ocppytorch-metric-learning 的 Testers評(píng)估器是度量學(xué)習(xí)鏈路里的考官拿到訓(xùn)練好的模型trunk embedder和數(shù)據(jù)集劃分后它為每個(gè)樣本批量算出嵌入向量可以理解為樣本指紋再基于最近鄰檢索給模型打出一組精度分?jǐn)?shù)。本文按先選型 → 走鏈路 → 讀結(jié)果 → 接閉環(huán)的順序展開覆蓋 Testers 的完整用法、指標(biāo)輸出解讀以及如何用 logging_presets 實(shí)現(xiàn)訓(xùn)練—驗(yàn)證—保存最佳模型的閉環(huán)。速覽評(píng)估器卡在數(shù)據(jù) → 嵌入 → 檢索 → 指標(biāo)的哪一環(huán)Testers 不參與梯度更新是純?cè)u(píng)估組件。它的內(nèi)部流程固定為四步嵌入生成把dataset_dict里每個(gè) split 的樣本過一遍模型eval()模式 無梯度得到高維嵌入檢索默認(rèn)用 faiss 后端FaissKNN在 reference 集合中為每條 query 做 k-NN指標(biāo)計(jì)算把 query/reference 的嵌入與標(biāo)簽交給AccuracyCalculator產(chǎn)出precision_at_1、r_precision、NMI 等指標(biāo)輸出結(jié)果寫入tester.all_accuracies嵌套字典split → 指標(biāo)名 → 數(shù)值并可觸發(fā)可視化與end_of_testing_hook。一句話總結(jié)你提供模型和數(shù)據(jù)它交回一張分?jǐn)?shù)表。下這張圖是模型評(píng)估對(duì)比圖的常見畫法一軸是誤差指標(biāo)、一軸是推理開銷理解 Testers 輸出時(shí)可以套用同樣的視角一張表里同時(shí)回答準(zhǔn)不準(zhǔn)和貴不貴。調(diào)用形態(tài)非常統(tǒng)一所有測(cè)試器都是這么用的from pytorch_metric_learning import testers t testers.GlobalEmbeddingSpaceTester() dataset_dict {train: train_ds, val: val_ds} all_accuracies t.test(dataset_dict, epoch, trunk, embedder) # embedder 可省略先選型我該用哪個(gè) Tester結(jié)論先行90% 的場(chǎng)景用GlobalEmbeddingSpaceTester只有當(dāng)標(biāo)簽帶層級(jí)、或你的損失函數(shù)是TwoStreamMetricLoss時(shí)才需要另外兩個(gè)。三者的邊界如下源碼位于 src/pytorch_metric_learning/testers/Tester適用場(chǎng)景數(shù)據(jù)要求關(guān)鍵限制GlobalEmbeddingSpaceTester通用評(píng)估看嵌入空間中所有點(diǎn)的最近鄰質(zhì)量__getitem__返回(data, labels)無特殊限制splits_to_eval任意組合WithSameParentLabelTester標(biāo)簽有層級(jí)如 animal → cat/dog只在與 query 同父類兄弟的樣本里檢索二維標(biāo)簽(num_samples, 層級(jí)數(shù))第L1維是父標(biāo)簽只能評(píng)估L 層級(jí)數(shù) - 1的層級(jí)否則斷言報(bào)錯(cuò)GlobalTwoStreamEmbeddingSpaceTester配合TwoStreamMetricLoss的配對(duì)式訓(xùn)練返回(anchor, positive, label)三元組僅支持splits_to_eval默認(rèn)值每個(gè) split 自查詢query/reference 必須同 split兩個(gè)容易踩的選型細(xì)節(jié)TwoStream 版內(nèi)部把每個(gè) batch 的 anchor 嵌入拼在前半段當(dāng) query、posneg 嵌入拼在后半段當(dāng) reference且ref_includes_query恒為False兩邊不是同一批樣本。它會(huì)在set_reference_and_query()里顯式斷言 query 與 reference 是同一個(gè) split傳自定義組合會(huì)直接失敗。WithSameParentLabel 版對(duì)每個(gè)唯一父標(biāo)簽篩出子集、在子集內(nèi)分別算指標(biāo)最后跨父標(biāo)簽取平均np.mean。它衡量的是細(xì)粒度類在粗粒度類內(nèi)部的可分性與全局視角回答的不是同一個(gè)問題。從配置到產(chǎn)出的完整鏈路第一步嵌入生成——指紋得先可比BaseTestersrc/pytorch_metric_learning/testers/base_tester.py的__init__參數(shù)決定了這一步的行為最常用的幾個(gè)參數(shù)默認(rèn)值作用normalize_embeddingsTrue檢索前對(duì)嵌入做 L2 單位化保證余弦/L2 距離口徑一致use_trunk_outputFalse為True時(shí)跳過 embedder直接用 trunk 輸出評(píng)估pcaNone先標(biāo)準(zhǔn)化、再經(jīng) faiss 的PCAMatrix降到 N 維在歸一化之前執(zhí)行batch_size/dataloader_num_workers32/2嵌入前向的批大小與加載進(jìn)程數(shù)data_device/dtypeNone設(shè)備自動(dòng)選 CUDA與數(shù)據(jù)類型如torch.float16data_and_label_getterNone自定義如何從__getitem__輸出中拆出(data, labels)兩點(diǎn)補(bǔ)充不傳embedder_model時(shí)源碼會(huì)把它替換成torch.nn.Identity()即無操作直接消費(fèi) trunk 輸出嵌入生成邏輯封裝在get_all_embeddings()里可脫離test()單獨(dú)調(diào)用——想自己導(dǎo)出嵌入做 t-SNE/UMAP用它就夠了。第二步query 與 reference 的組合技巧默認(rèn)行為是自查詢dataset_dict里每個(gè) split 既當(dāng) query 又當(dāng) reference。更靈活的組合通過test()的splits_to_eval參數(shù)指定它是(query_split, [reference_splits])元組的列表# 默認(rèn)等價(jià)于 [(dataset_a, [dataset_a]), (train, [train])] # query 用測(cè)試集reference 用訓(xùn)練集評(píng)估泛化 [(test, [train])] # reference 由多個(gè) split 合并 [(test, [test, train])]源碼在get_splits_to_compute_embeddings()中處理三件事query split 不允許重復(fù)出現(xiàn)query 與 reference 的并集才計(jì)算嵌入同一 split 只跑一次前向若 query 包含在 reference 列表中會(huì)被移到 reference 最前面——因?yàn)锳ccuracyCalculator.get_accuracy()要求ref_includes_queryTrue時(shí)reference 的前l(fā)en(query)個(gè)元素必須與 query 逐元素相等有torch.allclose顯式校驗(yàn)。經(jīng)驗(yàn)建議關(guān)心泛化能力時(shí)讓 query 來自測(cè)試集、reference 來自訓(xùn)練集避免自查詢帶來的樣本總能檢索到自身導(dǎo)致的指標(biāo)虛高。第三步kNN 檢索——faiss 是引擎檢索由 src/pytorch_metric_learning/utils/inference.py 中的FaissKNNk-NN與FaissKMeansNMI/AMI 用的聚類完成也是AccuracyCalculator的默認(rèn)后端因此faiss 是硬依賴。關(guān)鍵參數(shù)是k默認(rèn)kNone等價(jià)于 k reference 嵌入總數(shù)——數(shù)據(jù)集一大檢索就會(huì)很慢推薦顯式傳k1000或kmax_bin_count每個(gè)類別的最大樣本數(shù)顯著提速。裝faiss-gpu時(shí)只有k 1024CUDA 9.5或k 2048CUDA ≥ 9.5才走 GPU否則回退 CPU 并告警——小數(shù)據(jù)集上若發(fā)現(xiàn)檢索沒跑在 GPU 上多半是這個(gè)原因。第四步指標(biāo)計(jì)算——考官判分檢索結(jié)果交給 src/pytorch_metric_learning/utils/accuracy_calculator.py 中的AccuracyCalculator。默認(rèn)指標(biāo)速覽指標(biāo)回答的問題備注precision_at_1第 1 個(gè)最近鄰是否與 query 同標(biāo)簽最直觀的檢索命中率r_precision/mean_average_precision_at_r前 r 個(gè)鄰居中的檢索質(zhì)量r 每個(gè) query 的相關(guān)鄰居數(shù)要求kNone、kmax_bin_count或k max(bincount(reference_labels))否則失真會(huì)打警告NMI/AMI嵌入空間的聚類結(jié)構(gòu)質(zhì)量用FaissKMeans對(duì) query 嵌入聚類簇?cái)?shù) query 唯一標(biāo)簽數(shù)mean_average_precision、mean_reciprocal_rank可選補(bǔ)充指標(biāo)按需開啟一個(gè)細(xì)節(jié)若某些 query 標(biāo)簽根本沒出現(xiàn)在 reference 里這些樣本會(huì)被排除出 k-NN 類指標(biāo)——它們注定 0 分不能反映嵌入質(zhì)量排除后更公平。讀懂輸出keyname 規(guī)則、指標(biāo)值與自查詢虛高test()返回并緩存在tester.all_accuracies上的結(jié)構(gòu)是兩層字典{val: {precision_at_1_level0: 0.42, NMI_level0: 0.55, ...}}指標(biāo)名遵循固定拼裝規(guī)則accuracies_keyname()生成_levelL后綴L 是label_hierarchy_level參數(shù)選中的標(biāo)簽層級(jí)。單標(biāo)簽數(shù)據(jù)保持默認(rèn) 0 即可直接忽略后綴AVERAGE_前綴當(dāng)label_hierarchy_levelall或傳入層級(jí)列表時(shí)會(huì)對(duì)各層級(jí)額外匯總出AVERAGE_precision_at_1這類平均指標(biāo)_pcaN后綴設(shè)置了pca后自動(dòng)追加標(biāo)明該組指標(biāo)基于降維后的嵌入。關(guān)于自查詢虛高默認(rèn)自查詢模式下每個(gè)樣本的最近鄰大概率是自己precision_at_1天然偏高。這不是 bug而是口徑問題——對(duì)比不同模型時(shí)保證口徑一致即可單獨(dú)匯報(bào)泛化數(shù)字時(shí)則建議用test 查 train的組合見上文splits_to_eval示例。另外epoch參數(shù)只用于日志與歷史記錄寫入all_accuracies[split][epoch]不影響任何計(jì)算。接入訓(xùn)練閉環(huán)logging_presets 早停 保存最佳模型評(píng)估器的end_of_testing_hook最實(shí)用的去處是接上 docs/logging_presets.md 里的logging_presets把每輪驗(yàn)證 挑最佳模型 早停自動(dòng)化import pytorch_metric_learning.utils.logging_presets as LP rk, _, _ LP.get_record_keeper(logs, tensorboard_logs) hooks LP.get_hook_container(rk) dataset_dict {val: val_dataset} tester testers.GlobalEmbeddingSpaceTester(end_of_testing_hookhooks.end_of_testing_hook) end_of_epoch_hook hooks.end_of_epoch_hook(tester, dataset_dict, saved_models) trainer trainers.MetricLossOnly( models, optimizers, batch_size, loss_funcs, mining_funcs, train_dataset, samplersampler, end_of_iteration_hookhooks.end_of_iteration_hook, end_of_epoch_hookend_of_epoch_hook, ) trainer.train(num_epochsnum_epochs)要點(diǎn)HookContainer的primary_metric決定用哪個(gè)指標(biāo)挑最佳 checkpoint默認(rèn)mean_average_precision_at_r可選r_precision、precision_at_1、NMIend_of_epoch_hook返回真正的鉤子函數(shù)驗(yàn)證集鍵名默認(rèn)val還支持test_interval隔幾輪驗(yàn)證與patience早停耐心值歷史記錄同時(shí)落 csv、sqlite 與 tensorboard之后可用hooks.get_accuracy_history(tester, val, ...)回放任意指標(biāo)的歷史曲線。避坑與提速清單faiss 必裝FaissKNN/FaissKMeans/PCA 都?jí)涸谒砩嫌?conda 安裝faiss-cpu或faiss-gpu大集提速顯式設(shè)accuracy_calculatorAccuracyCalculator(k1000)或kmax_bin_count注意r_precision/mean_average_precision_at_r在 k 偏小時(shí)會(huì)失真字符串標(biāo)簽必須set_min_label_to_zeroTrue并同時(shí)傳dataset_labelsLabelMapper才會(huì)做重映射此時(shí)標(biāo)簽按集合內(nèi)排名變成連續(xù)整數(shù)雙流測(cè)試器的硬限制splits_to_eval只支持默認(rèn)值query 與 reference 必須是同一 split別嘗試傳自定義組合臨時(shí)數(shù)據(jù)別出 hookembeddings_and_labels在test()末尾被刪除釋放內(nèi)存需要在里面讀嵌入就放在end_of_testing_hook里做鉤子只調(diào)用一次end_of_testing_hook在所有 split 評(píng)估完之后觸發(fā)一次不是每個(gè) split 一次只算部分指標(biāo)AccuracyCalculator(include(precision_at_1,))可顯著加速評(píng)估。下一步跑一遍 examples/notebooks 下的示例 notebook如 TripletMarginLossMNIST觀察每個(gè) epoch 的驗(yàn)證指標(biāo)如何進(jìn)入all_accuracies并驅(qū)動(dòng)最佳模型保存細(xì)讀 tests/testers/ 下的三個(gè)測(cè)試文件splits_to_eval三種組合對(duì)precision_at_1數(shù)值的影響、PCA 分支的端到端行為、雙流測(cè)試器的斷言都在斷言里寫得明明白白深入指標(biāo)數(shù)學(xué)見 docs/accuracy_calculation.md參數(shù)總覽見 docs/testers.md?!久赓M(fèi)下載鏈接】ocpFAIR Chemistrys library of machine learning methods for chemistry項(xiàng)目地址: https://gitcode.com/GitHub_Trending/oc/ocp創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考