手搓多模态-06 数据预处理

news2025/4/17 16:06:31

前情回顾

我们目前实现视觉模型编码部分然而我们所做一张图片编码嵌入许多上下相关嵌入向量然而我们期望一张图片一个向量表示从而文字向量点积形成相似度参考手搓多模态-01 对比学习的优化)所以我们需要一个Linear Projection多个嵌入向量投影一个嵌入向量这些可以之后数据准备阶段我们还有一些数据预处理工作没有本文着重描述如何进行数据预处理

数据预处理

我们新建一个文件paligemma_processer.py.

首先我们创建一个processerprocesser我们实现数据预处理功能

所做预处理主要包括

  • 图像放缩标准化
  • 输入图像-文本对解析形成token向量
  • 图像token创建占位表示Gemma模型输入有一部分输入向量来自视觉编码这部分向量暂时就用一个临时image_token表示方便后面替换
  • 对于图像输入我们需要输入转换形如[Batch_size,Channels,Height,Width]输入,转换torch.tensor类型方便pytorch处理

这部分代码主要如下

class PaligemmaProcessor:

	IMAGE_TOKEN = "<image>"
	def __init__(
			self,
			tokenizer,
			num_image_tokens,
			image_size  
		):
		super().__init__()
		self.image_seq_lenth = num_image_tokens
		self.image_size = image_size

		token_to_add = {"addtional_special_tokens": [self.IMAGE_TOKEN]} ##标识图像占位符
		tokenizer.add_special_tokens(token_to_add)
		EXTRA_TOKENS = [f"<loc:{i:04d}>" for i in range(1024)] ##用于目标检测
		EXTRA_TOKENS += [f"<seg:<{i:04d}>" for i in range(1024)] ##用于语义分割

		tokenizer.add_tokens(EXTRA_TOKENS)
		self.image_token_id = tokenizer.convert_tokens_to_ids(self.IMAGE_TOKEN) ##图像占位符的id

		tokenizer.add_bos_token = False ##去掉默认的bos和eos
		tokenizer.add_eos_token = False

		self.tokenizer = tokenizer
	
	def __call__(
			self,
			text: List[str],
			images: List[Image.Image],
			padding: str = "longest",
			truncation: bool = True
	):
		assert len(text) == 1 and len(images) == 1, "Only support one text and one image for now."
		
		pixel_values = process_images(
			images,
			size=(self.image_size, self.image_size),
			resample= Image.Resampling.BICUBIC,
			rescale_factor=1.0 / 255.0,
			image_mean = IMAGENET_STANDARD_MEAN,
			image_std = IMAGENET_STANDARD_STD
		)

		pixel_values = np.stack(pixel_values,axis=0)
		pixel_values = torch.tensor(pixel_values) ##转换为torch.tensor


		##通过add_image_token_to_prompt函数,将图像占位符添加到文本中,形成一个输入prompt
		input_string = [
			add_image_token_to_prompt(
				prefix_prompt = prompt,
				bos_token = self.tokenizer.bos_token,
				image_seq_len = self.image_seq_lenth,
				image_token = self.IMAGE_TOKEN
			)
			for prompt in text
		]
		
		## 将string类型的prompt转换为嵌入向量,其实这里是根据string中的词元划分成一个token_id的向量
		## 比如输入的string是"<image><image><bos>hello,world<sep>" 然后tokenizer将其分割成[<image>,<image>,<bos>,hell,oworld,<sep>],这里假设hell和oworld都是token,并查找每个token的id,可能得到[0,0,1,11,15,2]作为嵌入向量
		inputs = self.tokenizer(
			input_string,
			padding=padding,
			truncation=truncation,
			return_tensors="pt"
		)
		## 返回待编码的图像以及嵌入好的文本向量
		return_data = {"pixel_values": pixel_values, **inputs}

		return return_data

首先我们tokenizer 添加一些额外特殊token比如用于目标检测特殊位置token以及语义分割特殊token但是我们暂时不会用到它们

图像处理

数据预处理部分我们首先通过一个预处理函数处理图像这里包括图像缩放归一化标准化

		pixel_values = process_images(
			images,
			size=(self.image_size, self.image_size),
			resample= Image.Resampling.BICUBIC,
			rescale_factor=1.0 / 255.0,
			image_mean = IMAGENET_STANDARD_MEAN,
			image_std = IMAGENET_STANDARD_STD
		)

函数实现如下

def process_images(
		images: List[Image.Image],
		size: Tuple[int, int] = None,
		resample: Image.Resampling = None,
		rescale_factor: float = None,
		image_mean: Optional[Union[float,List[float]]] = None,
		image_std: Optional[Union[float,List[float]]] = None
) -> List[np.ndarray]:
	height, width = size
	images = [
		resize(image =image, size = (height,width), resample=resample) if image.size != size else image for image in images
	]
	images = [np.array(image) for image in images]
	images = [
		rescale(image = image, factor = rescale_factor) for image in images
	] ## 归一化缩放
	images = [
		normalize(image = image, mean = image_mean, std = image_std) for image in images
	] ## 标准化
	## image : [Height,Width,Channel] --> [Channel,Height,Width]
	images = [image.transpose(2,0,1) for image in images]
	return images

首先我们需要图像进行缩放那么这里涉及一个重采样函数表示你用什么方法图像进行缩放采样不同方法采样出来效果不一样这里我们Image.Resampling.BICUBIC方法关于这个方法详细信息参考其他博客

缩放操作在将0-255像素缩放0-1防止之后模型嵌入数值不稳定

随后标准化其实就像Batch NormalizationLayer Normalization一样图像像素分布标准正态分布所以需要大量图像RGB通道各自均值方差使用image_net统计结果

然后图像三个维度顺序改变一下

其中resize,rescale,normalize函数依次如下

IMAGENET_STANDARD_MEAN = [0.485, 0.456, 0.406]
IMAGENET_STANDARD_STD = [0.229, 0.224, 0.225]

def resize(
		image: Image.Image,
		size: Tuple[int, int],
		resample: Image.Resampling = None,
		reducing_gap: Optional[int] = None
):
	height,width = size	
	image.resize(size=(width,height),resample=resample,reducing_gap=reducing_gap)
	return image

def rescale(
		image: np.ndarray,
		factor: float,
		dtype: np.dtype = np.float32
):
	image = image * factor
	image = image.astype(dtype)
	return image

def normalize(
		image: np.ndarray,
		mean: Optional[Union[float,List[float]]] = None,
		std: Optional[Union[float,List[float]]] = None
) -> np.ndarray:
	if mean is None:
		mean = IMAGENET_STANDARD_MEAN
	if std is None:
		std = IMAGENET_STANDARD_STD
	mean = np.array(mean)
	std = np.array(std)
	image = (image - mean) / std
	return image

然后我们还需要输出图像信息转换torch.tensor这里转换代码如下

pixel_values = np.stack(pixel_values,axis=0)
pixel_values = torch.tensor(pixel_values) ##转换为torch.tensor

首先stack方法一个numpy tensor list转换一个tensor,然后再把numpytensor转换torchtensor.

token 处理

token处理主要这一部分

		##通过add_image_token_to_prompt函数,将图像占位符添加到文本中,形成一个输入prompt
		input_string = [
			add_image_token_to_prompt(
				prefix_prompt = prompt,
				bos_token = self.tokenizer.bos_token,
				image_seq_len = self.image_seq_lenth,
				image_token = self.IMAGE_TOKEN
			)
			for prompt in text
		]
		
		## 将string类型的prompt转换为嵌入向量,其实这里是根据string中的词元划分成一个token_id的向量
		## 比如输入的string是"<image><image><bos>hello,world<sep>" 然后tokenizer将其分割成[<image>,<image>,<bos>,hell,oworld,<sep>],这里假设hell和oworld都是token,并查找每个token的id,可能得到[0,0,1,11,15,2]作为嵌入向量
		inputs = self.tokenizer(
			input_string,
			padding=padding,
			truncation=truncation,
			return_tensors="pt"
		)
		## 返回待编码的图像以及嵌入好的文本向量
		return_data = {"pixel_values": pixel_values, **inputs}

首先我们构造输入string文本这个构造主要依照论文内容

论文构造输入首先image token占位然后一个bos表示文本信息的开始然后text input然后[sep]论文'\n'表示[sep]

于是我们add_image_token_to_prompt所示

def add_image_token_to_prompt(
		prefix_prompt: str,
		bos_token: str,
		image_seq_len: int,
		image_token: str
):
	##论文使用换行符当做[sep]token,但是可能会出现\n与前面的token重叠导致语义信息丢失。	
	return f"{image_token * image_seq_len}{bos_token}{prefix_prompt}\n"

这里可能出现一个问题论文使用换行符当做[sep]token,但是可能会出现\n与前面的token重叠导致语义信息丢失这里我们暂时不管这个问题

随后tokenizer调用实际输入string根据词汇拆分一个个token对应id,我们预选添加image_token占位符也就是我们构建string_input可能类似"<image><image><bos>hello,world<sep>",tokenizer根据词汇表划分这些token一个list[<image>,<image>,<bos>,"hell","oworld",<sep>],然后通过查表方式这些token转换数值id比如查到我们加入<image>对应id0,<bos>是1, <sep>是2,"hell,"是11,"oworld"是15,(注意,这里假设词汇表的"hell,"是一个token,"oworld"也是一个token)那么输出可能形如[0,0,1,11,15,2]

## 将string类型的prompt转换为嵌入向量,其实这里是根据string中的词元划分成一个token_id的向量
## 比如输入的string是"<image><image><bos>hello,world<sep>" 然后tokenizer将其分割成[<image>,<image>,<bos>,hell,oworld,<sep>],这里假设hell和oworld都是token,并查找每个token的id,可能得到[0,0,1,11,15,2]作为嵌入向量
inputs = self.tokenizer(
	input_string,
	padding=padding,
	truncation=truncation,
	return_tensors="pt"
)
## 返回待编码的图像以及嵌入好的文本向量
return_data = {"pixel_values": pixel_values, **inputs}
return return_data

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

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

相关文章

HCIP【路由过滤技术(详解)】

目录 1 简介 2 路由过滤方法 3 路由过滤工具 3.1 静默接口 3.2 ACL 3.3 地址前缀列表 3.4 filter-policy 3.4.1 filter-policy过滤接收路由&#xff08;以RIP为例&#xff09; 3.4.2 filter-policy过滤接收路由&#xff08;以OSPF为例&#xff09; 1 简介 路由过滤技术…

【AI插件开发】Notepad++ AI插件开发实践(代码篇):从Dock窗口集成到功能菜单实现

一、引言 上篇文章已经在Notepad的插件开发中集成了选中即问AI的功能&#xff0c;这一篇文章将在此基础上进一步集成&#xff0c;支持AI对话窗口以及常见的代码功能菜单&#xff1a; 显示AI的Dock窗口&#xff0c;可以用自然语言向 AI 提问或要求执行任务选中代码后使用&…

Vue3在ZKmall开源商城前端的应用实践与技术创新

ZKmall开源商城作为一款企业级电商解决方案&#xff0c;其前端架构基于Vue3实现了高效、灵活的开发模式&#xff0c;结合响应式设计、组件化开发与全链路性能优化&#xff0c;为多端协同和复杂业务场景提供了先进的技术支持。以下从技术架构、核心特性、性能优化等维度解析Vue3…

SpringAI+MCP协议 实战

文章目录 前言快速实战Spring AISpring AI 集成 MCP 协议Spring Mcp Client 示例Spring Mcp Server 示例 前言 尽管Python最近成为了编程语言的首选&#xff0c;但是Java在人工智能领域的地位同样不可撼动&#xff0c;得益于强大的Spring框架。随着人工智能技术的快速发展&…

[数据结构]图krusakl算法实现

目录 Kruskal算法 Kruskal算法 我们要在连通图中去找生成树 连通图&#xff1a;在无向图中&#xff0c;若从顶点v1到顶点v2有路径&#xff0c;则称顶点v1与顶点v2是连通的。如果图中任意一对顶点都是连通的&#xff0c;则称此图为连通图。 生成树&#xff1a;一个连通图的最小…

QEMU学习之路(5)— 从0到1构建Linux系统镜像

QEMU学习之路&#xff08;5&#xff09;— 从0到1构建Linux系统镜像 一、前言 参考&#xff1a;从内核到可启动镜像&#xff1a;0到1构建你的极简Linux系统 二、linux源码获取 安装编译依赖 sudo apt install -y build-essential libncurses-dev flex bison libssl-dev li…

node ---- 解决错误【Error: error:0308010C:digital envelope routines::unsupported】

1. 报错 在 Node.js 18.18.0 的版本中&#xff0c;遇到以下错误&#xff1a; this[kHandle] new _Hash(algorithm, xofLen);^ Error: error:0308010C:digital envelope routines::unsupported这个错误通常发生在运行项目或构建时&#xff0c;尤其是在使用 Webpack、Vite 或其他…

蓝桥杯——走迷宫问题(BFS)

这是一个经典的BFS算法 1. BFS算法保证最短路径 核心机制&#xff1a;广度优先搜索按层遍历所有可能的路径&#xff0c;首次到达终点的路径长度即为最短步数。这是BFS的核心优势。队列的作用&#xff1a;通过队列按先进先出的顺序处理节点&#xff0c;确保每一步探索的都是当…

详解 Redis repl_backlog_buffer(如何判断增量同步)

一、repl_backlog_buffer 复制积压缓冲区&#xff08;Replication Backlog Buffer&#xff09; 是一个环形内存区域&#xff08;Ring Buffer&#xff09;&#xff0c;用于临时保存主节点最近写入的写命令&#xff0c;以支持从节点断线重连后的增量同步。 1.1 三个复制偏移量 …

使用PyTorch实现ResNet:从残差块到完整模型训练

ResNet&#xff08;残差网络&#xff09;是深度学习中的经典模型&#xff0c;通过引入残差连接解决了深层网络训练中的梯度消失问题。本文将从残差块的定义开始&#xff0c;逐步实现一个ResNet模型&#xff0c;并在Fashion MNIST数据集上进行训练和测试。 1. 残差块&#xff08…

Scala相关知识学习总结5

1、多维数组 定义&#xff1a; val arr Array.ofDim[Double](3,4) 表示二维数组中有三个一维数组&#xff0c;每个一维数组有四个元素。 2、列表 List 不可变 List&#xff1a;默认不可变&#xff0c;可创建有序且可重复的列表&#xff0c;可使用:从右向左增加数据&#xf…

Day1:前端项目uni-app壁纸实战

uni-app官网下载HBuilder。 uni-app快速上手 | uni-app官网 点击HBuilder 安装 新建项目 工具——插件安装 安装uni-app&#xff08;vue3&#xff09; 我们先来准备一下&#xff1a; 先在wallpaper下新建目录 我已经建过了 同样&#xff0c;再在common下建images和style目录&…

光谱相机的光谱数据采集原理

光谱相机的光谱数据采集原理基于‌分光技术‌和‌光电信号转换‌&#xff0c;通过将入射光按波长分解并记录各波段的强度信息&#xff0c;最终生成包含空间和光谱维度的数据立方体。以下是详细原理分解&#xff1a; ‌1. 分光技术&#xff1a;将复合光分解为单色光‌ 光谱相机…

宏碁笔记本电脑擎7PRO搭载的 NVIDIA RTX 5080 显卡安装pytorch

宏碁笔记本电脑擎7PRO搭载的 NVIDIA RTX 5080 显卡是一款高性能移动 GPU&#xff0c;基于 NVIDIA 最新的 Blackwell 架构设计&#xff0c;通过修正架构&#xff08;Blackwell&#xff09;、显存类型与带宽&#xff08;GDDR7、960GB/s&#xff09;、Tensor Core 与 RT Core 全面…

html+css+js 实现一个贪吃蛇小游戏

目录 游戏简介 游戏功能与特点 如何玩转贪吃蛇 游戏设计与实现 HTML结构 JavaScript核心实现 代码结构&#xff1a; 效果 关于“其他游戏” 游戏简介 贪吃蛇是一款经典的单人小游戏&#xff0c;玩家通过控制蛇的移动&#xff0c;吃掉食物来增加长度&#xff0c;避免撞…

Python爬虫生成CSV文件的完整流程

引言 在当今数据驱动的时代&#xff0c;网络爬虫已成为获取互联网数据的重要工具。Python凭借其丰富的库生态系统和简洁的语法&#xff0c;成为了爬虫开发的首选语言。本文将详细介绍使用Python爬虫从网页抓取数据并生成CSV文件的完整流程&#xff0c;包括环境准备、网页请求、…

21.OpenCV获取图像轮廓信息

OpenCV获取图像轮廓信息 在计算机视觉领域&#xff0c;识别和分析图像中的对象形状是一项基本任务。OpenCV 库提供了一个强大的工具——轮廓检测&#xff08;Contour Detection&#xff09;&#xff0c;它能够帮助我们精确地定位对象的边界。这篇博文将带你入门 OpenCV 的轮廓…

医学图像分割效率大幅提升!U-Net架构升级,助力精度提升5%!

在医学图像分割领域&#xff0c;U-Net模型及其变体的创新应用正在带来显著的性能提升和效率优化。最新研究显示&#xff0c;通过引入结构化状态空间模型&#xff08;SSM&#xff09;和轻量级LSTM&#xff08;xLSTM&#xff09;等技术&#xff0c;VMAXL-UNet模型在多个医学图像数…

智能设备运行监控系统

在工业 4.0 与智能制造浪潮下&#xff0c;设备运行效率与稳定性成为企业竞争力的核心要素。然而&#xff0c;传统设备管理模式面临数据采集分散、状态分析滞后、维护成本高昂等痛点。为破解这些难题&#xff0c;设备运行监控系统应运而生&#xff0c;通过融合智能传感、5G 通信…

服务器报错:xxx/libc.so.6: version `GLIBC_2.32‘ not found

/lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32 not found (required by ./aima-sim-app-main) 解决思路 根据错误信息&#xff0c;您的应用程序 aima-sim-app-main 和 libmujoco.so.3.1.6 库依赖于较新的 GNU C Library (glibc) 版本&#xff08;如 GLIBC_2.32, GLIBC…