目录
1.3.1 key_fc1: self.resnet.fn = nn.Identity() # 移除ResNet模型的最后一层全连接层
Background
concept
多任务学习和多模态学习是CV领域的两个热门研究方向。
- 多任务学习 (Multi-Task Learning, MTL)是一种将多个相关任务学习到一个模型中的方法,以提高模型的泛化能力和学习效率。在CV领域,多任务学习常用于图像分类、目标检测、语义分割等任务的联合学习。
- 多模态学习 (Multi-Modal Learning, MML)是一种将多种类型的数据(e.g. image, text, audio, v ideo等)作为输入的学习方法,以提高模型的表现力和泛化能力。
区别与联系
区别:
- 多任务学习MTL,是将多个相关任务学习到一个模型中。
- 多模态学习MML,是将多种数据类型作为输入input。
联系:MTL和MML在多种数据类型上进行多任务学习!
算法原理
- 多任务学习MTL,是通过共享底层特征,提高模型泛化能力和学习效率,如torch.nn.ModuleList; torch.nn.ModuleDict。
- 多模态学习MML,是将多种类型数据输入,如torch.nn.Sequential; torch.nn.ModuleList。
1. Multi-Modal 多模态
1.1 4种跨模态特征融合方法
1.1.1 SumFusion,相加
将多个单模态output embeddings相加
import torch
import torch.nn as nn
#------------------------------------------#
# SumFusion的定义,为两者过全连接层后进行直接相加
#------------------------------------------#
class SumFusion(nn.Module):
def __init__(self, input_dim=512, output_dim=100):
super(SumFusion, self).__init__()
#---------------------------------------#
# 针对x以及y两个特征张量,分别定义了两个全连接层
#---------------------------------------#
self.fc_x = nn.Linear(input_dim, output_dim)
self.fc_y = nn.Linear(input_dim, output_dim)
def forward(self, x, y):
output = self.fc_x(x) + self.fc_y(y)
1.1.2 ConcatFusion,拼接
将多个单模态output embeddings拼接起来 -> 全连接层
#------------------------------------------#
# ConcatFusion的定义,只定义一个全连接层
# 首先将两者堆叠,之后再将堆叠后的向量送入至全连接层
#------------------------------------------#
class ConcatFusion(nn.Module):
def __init__(self, input_dim=1024, output_dim=100):
super(ConcatFusion, self).__init__()
self.fc_out = nn.Linear(input_dim, output_dim)
def forward(self, x, y):
output = torch.cat((x, y), dim=1)
output = self.fc_out(output)
return x, y, output
1.1.3 FiLM,Clip相乘
将一个单模态output embedding切分后,与另一个单模态output embedding相乘相加。
-
torch.split()函数,将tensor按特定维度dim切分成若干块,每块大小为dim_size。
#------------------------------------------#
# FiLM融合方法的定义,只定义一个全连接层
#------------------------------------------#
class FiLM(nn.Module):
"""
FiLM: Visual Reasoning with a General Conditioning Layer,
https://arxiv.org/pdf/1709.07871.pdf.
"""
def __init__(self, input_dim=512, dim=512, output_dim=100, x_film=True):
super(FiLM, self).__init__()
self.dim = input_dim
self.fc = nn.Linear(input_dim, 2 * dim)
self.fc_out = nn.Linear(dim, output_dim)
self.x_film = x_film
def forward(self, x, y):
if self.x_film:
film = x
to_be_film = y
else:
film = y
to_be_film = x
gamma, beta = torch.split(self.fc(film), self.dim, 1)
output = gamma * to_be_film + beta
output = self.fc_out(output)
return x, y, output
1.1.4 GatedFusion,Gated相乘
将一个单模态output embedding gated激活后,与另一个单模态output embedding相乘 -> 输出
#------------------------------------------#
# GatedFusion方法的定义
#------------------------------------------#
class GatedFusion(nn.Module):
"""
Efficient Large-Scale Multi-Modal Classification,
https://arxiv.org/pdf/1802.02892.pdf.
"""
def __init__(self, input_dim=512, dim=512, output_dim=100, x_gate=True):
super(GatedFusion, self).__init__()
self.fc_x = nn.Linear(input_dim, dim)
self.fc_y = nn.Linear(input_dim, dim)
self.fc_out = nn.Linear(dim, output_dim)
self.x_gate = x_gate # whether to choose the x to obtain the gate
self.sigmoid = nn.Sigmoid()
def forward(self, x, y):
out_x = self.fc_x(x)
out_y = self.fc_y(y)
if self.x_gate:
gate = self.sigmoid(out_x)
output = self.fc_out(torch.mul(gate, out_y))
else:
gate = self.sigmoid(out_y)
output = self.fc_out(torch.mul(out_x, gate))
return out_x, out_y, output
1.2 TorchMultiModal 库
Facebook AI Research (FAIR) 开发的TorchMultiModal库是一个用于多模态学习的库,继承了多模态数据处理和模型训练流程,旨在简化多模态任务的开发。
其他的多模态模型:
- Meta -> CM3
- google -> Parti
- OpenAI -> CLIP,clip component是一个在学习text和image表征方面非常有效的model。
1.3 多模态implementation
1.3.1 key_fc1: self.resnet.fn = nn.Identity() # 移除ResNet模型的最后一层全连接层
self.resnet.fn = nn.Identity() # 移除ResNet模型的最后一层全连接层
'''
ResNet模型的最后一层通常是一个全连接层,用于分类任务。对于pretrained ResNet-50模型,这个全连接层的的作用是讲ResNet的output features (通常是一个2048维的向量)映射到一个指定数量的类别上。例如,Rest在ImageNet数据集上预训练,最后一层全连接层输出维度是1000,对应于ImageNet的1000个类别。在多模态学习中,我们通常不需要最后一层的分类器,而是需要获取iamge embeddings,以便与其他模态(i.e. text)特征进行融合。
这种情况下,我们需要移除最后一层全连接层,只保留ResNet的特征提取部分。
nn.Identity作用是torch的一个占位符层,它不改变输入的值,只是简单地返回输入。使用nn.Identity可以方便地移除某一层而不改变模型地其他部分!!!
'''
self.resnet.fn = nn.Identity() # 移除ResNet模型的最后一层全连接层
'''
ResNet模型的最后一层通常是一个全连接层,用于分类任务。对于pretrained ResNet-50模型,这个全连接层的的作用是讲ResNet的output features (通常是一个2048维的向量)映射到一个指定数量的类别上。例如,Rest在ImageNet数据集上预训练,最后一层全连接层输出维度是1000,对应于ImageNet的1000个类别。在多模态学习中,我们通常不需要最后一层的分类器,而是需要获取iamge embeddings,以便与其他模态(i.e. text)特征进行融合。
这种情况下,我们需要移除最后一层全连接层,只保留ResNet的特征提取部分。
nn.Identity作用是torch的一个占位符层,它不改变输入的值,只是简单地返回输入。使用nn.Identity可以方便地移除某一层而不改变模型地其他部分!!!
'''
1.3.2 key_fc2: Bert_output.last_hidden_state
text_features = text_outputs.last_hidden_state
'''
transformers.BertModel默认输出是BaseModelOutputWithPoolingAndCrossAttention,这是一个包含多个字段命名元组NamedTuple。
last_hidden_state是bert_model最后一层的隐藏状态, 是一个shape=(batch_size, seq_len, hidden_size)的tensor。
NamedTuple还包括的其他参数:
- pooler_output,表示池化后的输出,这个输出可以用于分类任务。
- attention_weights,
'''
1.3.3 implementation codes
My github repository: GitHub - yuyongsheng1990/Multi_Modal_Models
- Multi_Modal_01: GPT Generated Codes.
- Multi_Modal_02: Cross-Attention: image to text.