InternVL(Internal Vision-Language model)是一个开源的多模态大型模型项目,由上海人工智能实验室(OpenGVLab)开发。InternVL 1是该项目的第一个主要版本,它通过创新的视觉-语言融合方法,实现了强大的图像理解和多模态对话能力。本文将深入分析InternVL 1的技术架构、关键特性和创新点,以提供对该模型的全面了解。
InternVL 1采用了经典的视觉-语言双塔架构,主要由以下几个关键部分组成:
┌───────────────────┐ │ InternVLChat │ └───────────────────┘ │ ┌────────────────┴────────────────┐ ▼ ▼ ┌───────────────────┐ ┌───────────────────┐ │ Vision Model │───────┬────►│ Language Model │ │ (InternVision) │ │ │ (LLaMA等) │ └───────────────────┘ │ └───────────────────┘ ▼ ┌───────────────────┐ │ Visual-LLM │ │ Projection MLP │ └───────────────────┘
InternVL 1主要由以下几个组件构成:
InternVL 1在原始配置中主要有两种规模变体:
InternVL 1的视觉部分采用了基于Vision Transformer (ViT)改进的InternVision模型,具有以下特点:
关键代码实现:
pythonclass InternVisionModel(PreTrainedModel):
# ...
def __init__(self, config: InternVisionConfig):
super().__init__(config)
self.config = config
self.embeddings = InternVisionEmbeddings(config)
self.encoder = InternVisionEncoder(config)
self.post_layernorm = NORM2FN[config.norm_type](config.hidden_size, eps=config.norm_eps)
self.post_init()
def forward(self, pixel_values=None, output_hidden_states=None,
return_dict=None, pixel_embeds=None):
# 图像处理和特征提取
# ...
值得注意的是,InternVisionModel实现了位置编码的动态适应能力:
pythondef _get_pos_embed(self, pos_embed, H, W):
target_dtype = pos_embed.dtype
pos_embed = pos_embed.float().reshape(
1, self.image_size // self.patch_size, self.image_size // self.patch_size, -1).permute(0, 3, 1, 2)
pos_embed = F.interpolate(pos_embed, size=(H, W), mode='bicubic', align_corners=False). \
reshape(1, -1, H * W).permute(0, 2, 1).to(target_dtype)
return pos_embed
这种实现允许模型处理不同尺寸的图像,增强了模型的适应性。
InternVL 1的一个关键创新是其视觉-语言投影层,它解决了视觉特征和语言特征之间的模态差异:
pythonself.mlp1 = nn.Sequential(
nn.LayerNorm(vit_hidden_size * int(1 / self.downsample_ratio) ** 2),
nn.Linear(vit_hidden_size * int(1 / self.downsample_ratio) ** 2, llm_hidden_size),
nn.GELU(),
nn.Linear(llm_hidden_size, llm_hidden_size)
)
这个MLP模块实现了以下功能:
InternVL 1实现了像素混洗(Pixel Shuffle)技术来对视觉特征进行下采样处理,有效减少图像特征的序列长度,提高模型效率:
pythondef pixel_shuffle(self, x, scale_factor=0.5):
"""
基于PixelShuffle技术的特征下采样
"""
B, N, C = x.shape
H = W = int(math.sqrt(N))
# 重排特征
x = x.reshape(B, H, W, C)
if self.ps_version == 'v1':
# v1版本实现
factor = int(1 / scale_factor)
x = F.pixel_unshuffle(x.permute(0, 3, 1, 2), downscale_factor=factor)
_, _, h, w = x.shape
x = x.reshape(B, -1, h * w).transpose(1, 2)
else:
# v2版本实现(区域聚合)
step = int(1 / scale_factor)
new_h, new_w = H // step, W // step
new_c = C * step * step
x = x.reshape(B, new_h, step, new_w, step, C).permute(0, 1, 3, 2, 4, 5)
x = x.reshape(B, new_h, new_w, -1)
x = x.reshape(B, -1, new_c).contiguous()
return x
这种像素混洗技术允许模型在保留关键视觉信息的同时,显著减少了需要处理的token数量,提高了推理效率。通过调整scale_factor
参数,可以灵活控制压缩率,在效率和信息保留之间取得平衡。
InternVL 1实现了高效的多模态交互模式,主要通过以下方式:
<img>
和<IMG_CONTEXT>
)在文本中标记图像位置关键代码:
pythondef forward(self, pixel_values, input_ids=None, attention_mask=None, ...):
# ...
# 提取视觉特征
vit_embeds = self.extract_feature(pixel_values)
vit_embeds = vit_embeds[image_flags == 1]
# 获取语言模型的输入嵌入
input_embeds = self.language_model.get_input_embeddings()(input_ids).clone()
# 识别图像标记位置并替换为视觉特征
selected = (input_ids == self.img_context_token_id)
input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)
# 将混合嵌入输入到语言模型
outputs = self.language_model(
inputs_embeds=input_embeds,
attention_mask=attention_mask,
# ...
)
# ...
通过这种优雅的设计,InternVL 1能够将视觉信息无缝集成到文本生成过程中,实现高质量的多模态交互。
InternVL 1的一个主要创新点是其高效的视觉-语言融合方法。与其他多模态模型相比,InternVL 1采用以下创新策略:
在模型代码中,这种灵活性体现在语言模型的加载和配置上:
pythonif config.llm_config.architectures[0] == 'LlamaForCausalLM':
self.language_model = LlamaForCausalLM(config.llm_config)
elif config.llm_config.architectures[0] == 'InternLM2ForCausalLM':
self.language_model = InternLM2ForCausalLM(config.llm_config)
elif config.llm_config.architectures[0] == 'Phi3ForCausalLM':
self.language_model = Phi3ForCausalLM(config.llm_config)
elif config.llm_config.architectures[0] == 'Qwen2ForCausalLM':
self.language_model = Qwen2ForCausalLM(config.llm_config)
else:
raise NotImplementedError(f'{config.llm_config.architectures[0]} is not implemented.')
InternVL 1采用了高效的训练策略,包括:
分阶段训练:
LoRA(低秩适应)技术支持:
pythondef wrap_backbone_lora(self, r=128, lora_alpha=256, lora_dropout=0.05):
lora_config = LoraConfig(
r=r,
target_modules=['attn.qkv', 'attn.proj', 'mlp.fc1', 'mlp.fc2'],
lora_alpha=lora_alpha,
lora_dropout=lora_dropout,
)
self.vision_model = get_peft_model(self.vision_model, lora_config)
self.vision_model.print_trainable_parameters()
类似地,语言模型也支持LoRA微调:
pythondef wrap_llm_lora(self, r=128, lora_alpha=256, lora_dropout=0.05):
# 根据语言模型架构确定目标模块
if self.llm_arch_name == 'InternLM2ForCausalLM':
target_modules = ['attention.wqkv', 'attention.wo', 'feed_forward.w1',
'feed_forward.w2', 'feed_forward.w3']
elif self.llm_arch_name == 'Phi3ForCausalLM':
target_modules = ['mlp.down_proj', 'mlp.gate_up_proj', 'self_attn.o_proj',
'self_attn.qkv_proj']
elif self.llm_arch_name in ['Qwen2ForCausalLM', 'LlamaForCausalLM']:
target_modules = ['self_attn.q_proj', 'self_attn.k_proj', 'self_attn.v_proj',
'self_attn.o_proj', 'mlp.gate_proj', 'mlp.down_proj', 'mlp.up_proj']
else:
raise NotImplemented
lora_config = LoraConfig(
r=r,
target_modules=target_modules,
lora_alpha=lora_alpha,
lora_dropout=lora_dropout,
task_type='CAUSAL_LM'
)
self.language_model = get_peft_model(self.language_model, lora_config)
self.language_model.enable_input_require_grads()
self.language_model.print_trainable_parameters()
分布式训练优化:支持DeepSpeed、混合精度训练等技术,加速大规模模型训练
InternVL 1支持动态图像处理,可以根据输入图像的特性动态调整处理方式:
dynamic_image_size
配置支持处理不同尺寸的图像min_dynamic_patch
和max_dynamic_patch
配置,可以根据图像内容复杂度动态调整处理的patch数量use_thumbnail
配置支持缩略图处理模式,提高处理效率这些参数在配置文件中可以看到:
python# 从InternVLChatConfig类
self.dynamic_image_size = dynamic_image_size
self.use_thumbnail = use_thumbnail
self.ps_version = ps_version # pixel shuffle version
self.min_dynamic_patch = min_dynamic_patch
self.max_dynamic_patch = max_dynamic_patch
InternVL 1中的核心注意力计算可以表示为:
其中,、、分别是查询、键和值矩阵,是键的维度。
在InternVL的实现中,特别是使用了FlashAttention优化时,注意力计算变得更加高效:
pythondef _flash_attn(self, x, key_padding_mask=None, need_weights=False):
b, n, three_h_d = x.shape
x = rearrange(x, 'b n (three h d) -> b n three h d', three=3, h=self.num_heads)
context, attn_weights = self.flash_attn(x, key_padding_mask=key_padding_mask,
need_weights=need_weights)
context = rearrange(context, 'b n h d -> b n (h d)')
return context
像素混洗(Pixel Shuffle)技术的数学表示为:
其中,是原始特征,是下采样因子,、、分别表示通道数、高度和宽度。
在InternVL中,像素混洗有两种实现版本(v1和v2),提供了不同的特征压缩方式,二者的主要区别在于特征重排的方式:
pixel_unshuffle
操作视觉特征到语言空间的映射可以表示为:
具体来说:
其中,、是权重矩阵,是偏置项,是层归一化,是激活函数。
对于处理不同尺寸的图像输入,InternVL使用二维插值方法调整位置编码:
这种方法的具体实现如下:
pythonpos_embed = F.interpolate(pos_embed, size=(H, W), mode='bicubic', align_corners=False)
通过双三次插值(bicubic interpolation),位置编码能够平滑地适应不同尺寸的输入。
InternVL 1在多个多模态基准测试上表现出色:
InternVL 1可以应用于各种实际场景:
事实上,InternVL团队已经在后续版本中实现了许多这些改进:
InternVL 1作为一个开源的多模态大模型,在视觉-语言理解和交互方面展现了强大的能力。其创新的架构设计、高效的视觉-语言融合机制和灵活的训练策略,为开源社区提供了一个强大而灵活的多模态基础模型。
InternVL 1的核心价值在于:
随着后续版本(如InternVL 1.5、InternVL 2.0等)的推出,模型的性能和能力将进一步提升,为多模态人工智能的发展做出更大贡献。作为开源领域的一个里程碑项目,InternVL展示了开源社区在多模态AI领域的强大创新能力。
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!