多模态动态融合模型 PDF 论文阅读与代码分析
一、理论
置信度
在机器学习中,置信度表示模型对其预测结果'有多确定'。它刻画的是模型认为自己预测是正确的程度。
例如,在分类任务中:'这是正类的概率是 0.92',那么 0.92 就可以视为模型对该预测的置信度。
在监督学习中,给定输入样本 x,模型预测类别为 ŷ,则置信度通常定义为模型对预测类别的后验概率估计。
置信度和不确定性
文中用熵来衡量整体不确定性,算是置信度的一种扩展。置信度高 <=> 熵低。
分类评价指标对比
| 指标 | 一句话解释 |
|---|---|
| Accuracy | 模型整体准不准 |
| Precision | 模型说'是'的时候靠谱吗 |
| Recall | 真正'是'的有没有被找全 |
| F1 | Precision 和 Recall 的折中 |
| ROC-AUC | 正样本排在负样本前面的能力 |
The Mono-Confidences and Holo-Confidences
该文的目的之一是为了解决模态权重融合的权重问题。多个模态分别从多个维度评价目标的状态,给出不一样的结果,需要融合这几个结果。
目前可以确定的是:融合权重 ω 应当与损失 l 呈负相关,并且与其他模态的损失呈正相关。也就是:当前模态越可靠 → 权重越大;其他模态越不可靠 → 当前模态权重越大。
对单个模态的模型,权重 ω 是要求的权重,损失 loss 定义如下:
- Mono-Confidences:当前模态本身有多可靠。
- Holo-Confidences:相对其他模态我有多可靠。
将他们统合为协同信度(Co-Belief):
Mono-Confidence 只看自己;Holo-Confidence 只看别人;但多模态融合需要既考虑自身可靠性,又考虑整体模态状态。
由协同信度确定该模态的权重。
二、代码
1、运行环境
代码训练环境建议使用 Linux 云服务器,Ubuntu 20.04 + Python 3.11 版本,GPU 配置根据需求选择。
论文附带代码只有 2mb,明显缺失了很多预训练结构与数据集文件。
2、数据集文件
这里选用了代码中可选的训练集 MVSA_Single,需要自行下载并准备到服务器目录中。训练集划分源代码已提供,按要求放到同一目录下即可。
3、词向量文件
源代码缺失了预训练好的词向量文件 glove.840B.300d,需要自行使用指令下载到指定目录。
wget https://nlp.stanford.edu/data/glove.840B.300d.zip
4、源代码逻辑错误
训练代码中的 forward 函数存在运行逻辑错误,文本和图像的 loss(txt_clf_loss 和 img_clf_loss)定义在了 if 之外,会导致运行不成功。修改后的代码如下:
def model_forward(i_epoch, model, args, criterion, optimizer, batch, mode='eval'):
txt, segment, mask, img, tgt, idx = batch
tgt = tgt.cuda()
clf_loss =
tcp_pred_loss =
args.model == :
txt = txt.cuda()
out = model(txt)
clf_loss = criterion(out, tgt)
args.model == :
img = img.cuda()
out = model(img)
clf_loss = criterion(out, tgt)
args.model == :
txt, img = txt.cuda(), img.cuda()
out = model(txt, img)
clf_loss = criterion(out, tgt)
args.model == :
txt, mask, segment = txt.cuda(), mask.cuda(), segment.cuda()
out = model(txt, mask, segment)
clf_loss = criterion(out, tgt)
args.model == :
txt, img = txt.cuda(), img.cuda()
mask, segment = mask.cuda(), segment.cuda()
out = model(txt, mask, segment, img)
clf_loss = criterion(out, tgt)
args.model == :
txt, img = txt.cuda(), img.cuda()
mask, segment = mask.cuda(), segment.cuda()
out, txt_logits, img_logits, txt_tcp_pred, img_tcp_pred = \
model(txt, mask, segment, img, )
txt_loss = criterion(txt_logits, tgt)
img_loss = criterion(img_logits, tgt)
clf_loss = txt_loss + img_loss
maeloss = nn.L1Loss(reduction=)
label = F.one_hot(tgt, num_classes=args.n_classes)
args.task_type == :
txt_pred = torch.sigmoid(txt_logits)
img_pred = torch.sigmoid(img_logits)
:
txt_pred = F.softmax(txt_logits, dim=)
img_pred = F.softmax(img_logits, dim=)
txt_tcp, _ = torch.(txt_pred * label, dim=, keepdim=)
img_tcp, _ = torch.(img_pred * label, dim=, keepdim=)
tcp_pred_loss = (maeloss(txt_tcp_pred, txt_tcp.detach()) + maeloss(img_tcp_pred, img_tcp.detach()))
:
args.model ==
txt, img = txt.cuda(), img.cuda()
mask, segment = mask.cuda(), segment.cuda()
out = model(txt, mask, segment, img)
clf_loss = criterion(out, tgt)
loss = clf_loss + tcp_pred_loss
loss, out, tgt


