源码解读:InternVL 1.5

源码地址:https://github.com/OpenGVLab/InternVL/tree/main/internvl_chat/internvl/model/internvl_chat

配置

在internvl_chat/internvl/model/internvl_chat/configuration_intern_vit.py

用InternVisionConfig类来设置类,用于初始化模型

			num_channels=3,patch_size=14,image_size=224,qkv_bias=False,hidden_size=3200,num_attention_heads=25,intermediate_size=12800,qk_normalization=True,num_hidden_layers=48,use_flash_attn=True,hidden_act='gelu',norm_type='rms_norm',layer_norm_eps=1e-6,dropout=0.0,drop_path_rate=0.0,attention_dropout=0.0,initializer_range=0.02,initializer_factor=0.1,**kwargs,

重要的参数:
1.num_channels:输入图像的颜色通道数量。这是一个与图像数据格式相关的重要参数。不同的图像格式具有不同的颜色通道数量。

以下是一些常见的分类和解释:

  1. RGB 图像

    • 通道数:3
    • 描述:RGB 图像使用三个颜色通道来表示颜色信息,即红色(Red)、绿色(Green)和蓝色(Blue)。这是最常见的图像格式,用于大多数彩色图像。
    • 如何处理:RGB 图像中的每个像素由三个值组成,分别表示红、绿、蓝的强度。这三个值通常在 0 到 255 之间(对于 8 位图像)。
  2. 灰度图像

    • 通道数:1
    • 描述:灰度图像只有一个通道,用于表示亮度信息,没有颜色信息。每个像素的值表示该点的灰度强度。
    • 如何处理:灰度图像中的每个像素通常在 0 到 255 之间,0 表示黑色,255 表示白色。
  3. RGBA 图像

    • 通道数:4
    • 描述:RGBA 图像在 RGB 的基础上增加了一个透明度通道(Alpha 通道),用于表示像素的透明度。
    • 如何处理:RGBA 图像中的每个像素由四个值组成,分别表示红、绿、蓝的强度和透明度。这四个值通常在 0 到 255 之间。
  4. 其他多通道图像

    • 通道数:任意数量
    • 描述:某些专业领域(如医学成像、遥感)可能使用超过三个或四个通道的图像。例如,多光谱图像和超光谱图像可以有数十个甚至数百个通道,每个通道对应不同波段的光谱信息。
    • 如何处理:这些图像中的每个像素由多个值组成,每个值表示在不同光谱波段的强度。处理这类图像通常需要特定的算法和工具。

2.patch_size:定义了输入图像被划分成的小块(patch)的大小。

patch_size 指的是将图像划分成的小块(patch)的边长。例如,如果 patch_size 设置为 16,那么每个
patch 的大小就是 16x16 像素。

为什么使用 Patch?

在基于 Transformer 的视觉模型中,输入图像会被划分成若干个不重叠的 patch,这些 patch
会被展平并线性嵌入到较高维度的向量中,随后作为 Transformer
的输入。这样做是为了将图像转换成类似于自然语言处理(NLP)中的词嵌入(word embedding)的形式,使得图像数据可以用
Transformer 模型进行处理。

Patch Size 的影响

  1. Patch 数量

    • 图像的分辨率是固定的,例如 224x224 像素。如果 patch_size 设置为 16,那么整个图像会被划分成 (224/16) x (224/16) = 14 x 14 = 196 个 patch。
    • 较小的 patch size 会导致更多的 patch,从而提供更细粒度的图像信息。
    • 较大的 patch size 会导致较少的 patch,从而减少模型的计算复杂度,但可能丢失一些细节信息。
  2. 计算复杂度

    • 较大的 patch size 通常会降低模型的计算复杂度,因为需要处理的 patch 数量减少了。
    • 较小的 patch size 会增加计算复杂度,但可能提高模型的细节捕捉能力。
  3. 特征提取

    • 较小的 patch size 可以更好地捕捉图像中的细微特征和局部模式。
    • 较大的 patch size 更关注全局信息和较大范围的特征。

3.qk_normalization:指在自注意力机制中对查询(queries)和键(keys)进行归一化处理。

归一化 Queries 和 Keys 的原因

  1. 稳定数值计算

    • 在没有归一化的情况下,( Q ) 和 ( K ) 的值可能会很大,导致 ( QK^T ) 的值也会很大。这样,经过 softmax 后的值会变得非常尖锐(即,大部分权重集中在几个元素上)。
    • 归一化可以将 ( Q ) 和 ( K ) 的值缩小到较小的范围,从而避免数值计算中的溢出问题,使计算更加稳定。
  2. 提高模型的性能和收敛速度

    • 归一化后的 ( Q ) 和 ( K ) 可以使注意力权重更加平滑和稳定,避免过度依赖某些特定的查询或键。
    • 这有助于模型在训练过程中更快地收敛,并可能提高模型的整体性能。
  3. 避免极端权重

    • 未归一化的情况下,某些查询和键的点积可能会非常大,导致 softmax 函数在这些位置生成接近 1 的值,而在其他位置生成接近 0 的值。这样会导致模型的注意力机制过于集中在某些位置,忽略了其他重要的信息。
    • 归一化有助于避免这种极端权重的情况,使得注意力机制更加平衡和合理。

归一化的实现

常见的归一化方法包括:

  • 标准化:将每个向量减去其均值,并除以其标准差,使得数据符合标准正态分布。
  • 单位向量归一化:将向量除以其 L2 范数,使其长度为 1。这种方法通常用于 self-attention 机制。

总结

对查询和键进行归一化可以稳定数值计算,提高模型的性能和收敛速度,并避免极端权重情况的发生。这种归一化处理在实际应用中已经证明是有效的,可以帮助模型在复杂的任务中表现得更好。

from_pretrained函数接受cls和pretrained_model_name_or_path参数,用于从预训练模型的路径或名称加载配置。
cls 是一个用于类方法中的通用参数名,指代调用该方法的类本身。

同级的chat文件配置

继承了上个VFM的配置,然后配置了LLM的参数。
1.use_backbone_lora:指定是否在模型的骨干网络中使用 LoRA(Low-Rank Adaptation)技术。
2.pad2square:是否将输入图像填充成正方形。
3.force_image_size:指定一个固定的图像尺寸。
4.downsample_ratio:在处理图像时,输入图像可以通过下采样来减少尺寸。这个参数指定下采样的比例,例如 0.5 表示将图像尺寸减半。
5.use_thumbnail:是否使用缩略图。
6.ps_version:像素混洗(pixel shuffle)的版本。

PixelShuffle 的基本概念

PixelShuffle
是一种将低分辨率特征图转换为高分辨率图像的上采样方法。它通过重新排列低分辨率特征图中的元素来生成高分辨率图像。这个过程通常用于图像超分辨率任务,即从低分辨率图像生成高分辨率图像。

工作原理

PixelShuffle 的核心思想是将特征图的通道维度转换为空间维度。具体步骤如下:

  1. 低分辨率特征图

    • 输入一个形状为 ((N, C \times r^2, H, W)) 的低分辨率特征图,其中 (N) 是批量大小,(C) 是通道数,(H) 和 (W) 是特征图的高度和宽度,(r) 是上采样倍数。
  2. 通道转换

    • 将通道数 (C \times r^2) 拆分为 (r \times r) 个小块,每个小块的通道数为 (C)。
  3. 重新排列

    • 将这些小块重新排列到空间维度,生成一个新的特征图,形状为 ((N, C, H \times r, W \times r))。

通过这个过程,特征图的分辨率从 ((H, W)) 增加到 ((H \times r, W \times r)),实现上采样。

应用场景

PixelShuffle 主要用于以下场景:

  1. 图像超分辨率:提高图像分辨率,从低分辨率图像生成高分辨率图像。
  2. 上采样:在生成模型(如生成对抗网络,GAN)中用于生成高分辨率图像。
  3. 视频处理:提高视频帧的分辨率,实现视频的超分辨率。

视觉模型类

modeling_intern_vit.py文件

InternVisionEmbeddings 视觉嵌入类
InternAttention 注意力机制
InternMLP MLP实现
InternVisionEncoderLayer 单层的encoder
InternVisionEncoder 完整的encoder
InternVisionModel 视觉模型类

直接给出模型类的注释

# 视觉模型类
class InternVisionModel(PreTrainedModel):main_input_name = 'pixel_values'config_class = InternVisionConfig_no_split_modules = ['InternVisionEncoderLayer']# 参数定义,从预定义的嵌入类和encoder类加载def __init__(self, config: InternVisionConfig):super().__init__(config)self.config = configself.embeddings = InternVisionEmbeddings(config)self.encoder = InternVisionEncoder(config)# 调整位置嵌入,适应不同尺寸的图像def resize_pos_embeddings(self, old_size, new_size, patch_size):# 从嵌入类获取位置嵌入pos_emb = self.embeddings.position_embedding_, num_positions, embed_dim = pos_emb.shape # 获取位置数量、嵌入维度cls_emb = pos_emb[:, :1, :] # 取出第一个位置的嵌入,是分类嵌入,表示图像整体的信息# 针对其他位置的嵌入,调整形状,变为(1, embed_dim, old_size // patch_size, old_size // patch_size)pos_emb = pos_emb[:, 1:, :].reshape(1, old_size // patch_size, old_size // patch_size, -1).permute(0, 3, 1, 2)# 使用 F.interpolate 函数对位置嵌入进行双三次插值,将其尺寸调整为 (new_size // patch_size, new_size // patch_size)pos_emb = F.interpolate(pos_emb.float(), size=new_size // patch_size, mode='bicubic', align_corners=False) # 上采样或下采样# 还原位置嵌入形状pos_emb = pos_emb.to(cls_emb.dtype).reshape(1, embed_dim, -1).permute(0, 2, 1)# 拼接分类嵌入和位置嵌入pos_emb = torch.cat([cls_emb, pos_emb], dim=1)# 将新的位置嵌入赋值给模型的嵌入参数,并更新图像尺寸self.embeddings.position_embedding = nn.Parameter(pos_emb) # 将一个张量转换为模型的可学习参数self.embeddings.image_size = new_sizelogger.info('Resized position embeddings from {} to {}'.format(old_size, new_size))# 返回图像嵌入def get_input_embeddings(self):return self.embeddings# 将输入图像数据转换为特征表示def forward(self,pixel_values: Optional[torch.FloatTensor] = None, # 输入图像的像素值,形状为 (batch_size, channels, height, width)output_hidden_states: Optional[bool] = None, # 是否输出所有层的隐藏状态return_dict: Optional[bool] = None, # 是否返回字典格式的输出pixel_embeds: Optional[torch.FloatTensor] = None, # 预先计算好的图像嵌入特征,形状为 (batch_size, sequence_length, hidden_size)) -> Union[Tuple, BaseModelOutputWithPooling]:# 是否输出所有层的隐藏状态,output_hidden_states = (output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states)# 是否返回字典格式的输出return_dict = return_dict if return_dict is not None else self.config.use_return_dict# 检查输入,要么输入像素值,要么输入嵌入if pixel_values is None and pixel_embeds is None:raise ValueError('You have to specify pixel_values or pixel_embeds')# 优先选择图像嵌入,将其作为隐藏状态if pixel_embeds is not None:hidden_states = pixel_embedselse: # 否则,检查图像像素值的形状,拿他生成嵌入,作为隐藏状态if len(pixel_values.shape) == 4:hidden_states = self.embeddings(pixel_values)else:raise ValueError(f'wrong pixel_values size: {pixel_values.shape}')# 将隐藏状态输入到编码器 self.encoder 中,得到编码器的输出encoder_outputs = self.encoder(inputs_embeds=hidden_states,output_hidden_states=output_hidden_states,return_dict=return_dict,)# 从编码器输出中取出最后的隐藏状态 last_hidden_state,迭代取出第一个位置的输出,是池化的分类嵌入last_hidden_state = encoder_outputs.last_hidden_statepooled_output = last_hidden_state[:, 0, :]# 如果 return_dict 为 False,返回元组格式的结果,包括最后的隐藏状态、池化输出和编码器的其他输出if not return_dict: # + 运算符用于元组时,它的作用是连接两个元组return (last_hidden_state, pooled_output) + encoder_outputs[1:] # (last_hidden_state, pooled_output, hidden_states, attentions)# 如果是字典形式的输出,就返回 BaseModelOutputWithPooling 对象,包含最后的隐藏状态、池化输出、隐藏状态和注意力。return BaseModelOutputWithPooling(last_hidden_state=last_hidden_state,pooler_output=pooled_output,hidden_states=encoder_outputs.hidden_states,attentions=encoder_outputs.attentions,)

chat模型类

初始化了很多参数,主要还是VFM和LLM、MLP,还有是否对这两个模型使用Lora化,以减少训练的参数量。

前向传播

输入图像的像素值、文本的id、图像标志、标签,返回loss、预测的概率等。
重点在于

input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)

将图片和文本嵌入拼接。

像素混洗函数 pixel_shuffle

自己实现的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/35189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Spring Boot框架来生成HTML页面并返回给客户端

文章目录 1. 创建Spring Boot项目1.1 项目结构 2. 配置 pom.xml3. 编写代码3.1 创建主应用程序类3.2 创建数据模型3.3 创建数据仓库3.4 创建控制器3.5 创建HTML模板 4. 运行应用程序总结 下面是一个简单的Java实现,使用Spring Boot框架来生成HTML页面并返回给客户端…

透明屏幕的魅力:为何它如此受欢迎

在科技日新月异的今天,透明屏幕技术以其独特的魅力和广泛的应用前景,逐渐成为了科技领域的一颗璀璨明星。从智能手机、平板电脑到大型显示屏,透明屏幕技术以其前所未有的视觉体验和实用性,赢得了广大消费者的喜爱。 一、透明屏幕的…

docker 镜像突然拉取不了,教你解决

最近我们可以发现,在Linux系统里拉取不了镜像了,翻墙也拉取不了,这时候我们可以有一个新的docker 镜像同步网站来解决这个问题 一、首先打开镜像官网(需要翻墙) https://hub.docker.com/ 然后搜索一个镜像 搜索最新…

Nginx实战:简单登录验证配置(基于openssl)

本文提供的是基于openssl创建的密码文件,对nginx指定的location访问。进行登录验证的配置方式。 1、验证页面配置 我的nginx实验环境是直接yum安装的,如果是自己编译安装的那么对应目录就是自己安装配置的目录。 先在/usr/share/nginx/html下创建一个usertest.html,里面添加…

Spring Cache常见问题解决

目录 一 报错:Null key returned for cache operation 二 报错:类型转换异常 三 取出的数据为null 一 报错:Null key returned for cache operation 这里报错有两种情况: 第一,如果你在新增的方法上使用Cacheable注解,那么肯定是…

绝望中迎来曙光,阿里大模型算法岗 Offer 突然来了!

节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、算法项目落地经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接如…

用定时器T1中断控制两个LED以不同周期闪烁

#include<reg51.h> // 包含51单片机寄存器定义的头文件 sbit D1P2^0; //将D1位定义为P2.0引脚 sbit D2P2^1; //将D2位定义为P2.1引脚 unsigned char Countor1; //设置全局变量&#xff0c;储存定时器T1中断次数 unsigned char Countor2; //设置全局变量&#xff0c;储…

c++之CRTP

CRTP概述 CRTP&#xff0c;即奇异递归模板模式&#xff08;Curiously Recurring Template Pattern&#xff09;&#xff0c;由James O. Coplien在其1995年的论文中首次提出&#xff0c;是C中一个独特而强大的设计模式。它利用模板和继承的特性&#xff0c;允许在编译时进行多态…

virutalBox安装debian并配置docker环境

下载镜像 https://gemmei.ftp.acc.umu.se/debian-cd/current/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso 虚拟机安装 如何在Virtual Box 上安装Debian系统_virtual box debian iso netinst-CSDN博客 启动命令行模式 如何设置Debian图形启动或命令行界面启动&#xff1…

什么是Cookie?有什么用?如何清除浏览器中的Cookie?

互联网上的每一次点击和每一个选择都可能被一种名为Cookie的技术记录下来。但Cookie是什么&#xff1f;我们在网站上登录时&#xff0c;为什么经常会被问及是否接受Cookie&#xff1f;接受Cookie登录会不会影响我们的在线隐私&#xff1f; Cookie是什么&#xff1f; Cookie是一…

设计模式3-分类

设计模式-分类 模式的分类从目的来分创建型模式&#xff08;Creational Patterns&#xff09;结构型模式&#xff08;Structural Patterns&#xff09;行为型模式&#xff08;Behavioral Patterns&#xff09; 从范围来分类模式&#xff08;Class Patterns&#xff09;对象模式…

S-Clustr(影子集群)V3 高并发,去中心化,多节点控制

S-Clustr 项目地址:https://github.com/MartinxMax/S-Clustr/releases/tag/S-Clustr-V3.0 Maptnh Не ограничивайте свои действия виртуальным миром. GitHub: Maptnh Jay Steinberg Man kann die Menschen, die man hasst, in d…

体育赛事翻译欧洲杯足球翻译术语分享

欧洲杯又称欧洲足球锦标赛&#xff0c;是世界上受欢迎和具影响力的国际体育赛事之一&#xff0c;有关足球翻译的术语分享如下&#xff1a; penalty mark (点球)罚球点,midfielder 前卫,center forward 中锋 full back 后卫,bicycle kick / overhead kick 倒钩球,chest-high ba…

如何用Vue3打造一个交互式数据统计仪表盘

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 代码相关技术博客 1. 代码应用场景介绍 本代码示例展示了一个用于展示统计数据的仪表盘界面。它适用于需要可视化跟踪和分析各种指标的应用程序&#xff0c;例如财务管理、健康监测和商业智能。 2. 代码基本…

机器学习-保存模型并根据模型进行预测 python demo

文章目录 前言机器学习-保存模型&#xff0c;根据模型进行预测python demo1. 将我们创建的线性回归模型保存到本地2. 利用我们保存的模型进行房价预测 demo2. 利用我们保存的模型生成对应的预测线性图 demo 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评…

国密SSL证书提升网络安全

随着数字化时代的到来&#xff0c;网络安全已经成为全球关注的焦点。在这种背景下&#xff0c;SSL证书作为保护数据传输安全的重要工具&#xff0c;其重要性日益凸显。 数字证书产品有以下几种类别&#xff1a; 单域名SSL证书&#xff1a;为单一网站提供安全保护。 多域名SS…

恶意软件识别

恶意软件识别是保护计算机系统和用户数据安全的重要步骤。以下是关于恶意软件识别的详细分析&#xff1a; 一、恶意软件的定义 恶意软件&#xff08;Malware&#xff09;是指那些被用来对计算机系统造成破坏或者以掩盖本身恶意活动为目的进行隐藏的软件。这些软件会操控、破坏…

基于HandyControl实现侧边菜单动态加载TabItem的功能

主要功能是点击左侧的 SideMenu 项目&#xff0c;然后在右侧的 TabControl 中创建一个新的 TabItem。这个 TabItem 的内容是一个 TextBlock&#xff0c;显示的是所点击的 SideMenuItem 的 Header 文本。代码还包括了关闭 TabItem 的功能。 以下是具体实现思路&#xff1a; 1.…

代码随想录算法训练营第四十一天|01背包问题 二维 01背包问题 一维 416. 分割等和子集

卡码网 01背包问题 二维 题目链接&#xff1a;01背包问题 二维 踩坑&#xff1a;在考虑当前物品时&#xff0c;应先考虑当前的背包能不能放得下当前物品 思路&#xff1a; 动态数组的含义&#xff1a;dp[i][j]&#xff1a;物品[0, i]在容量为 j 的背包中的最大价值递推公式…

【PyTorch函数解析】einsum的用法示例

一、前言 einsum 是一个非常强大的函数&#xff0c;用于执行张量&#xff08;Tensor&#xff09;运算。它的名称来源于爱因斯坦求和约定&#xff08;Einstein summation convention&#xff09;&#xff0c;在PyTorch中&#xff0c;einsum 可以方便地进行多维数组的操作和计算…