Showing Posts From

Vit

QWen3-VL-4B多模态大模型在RK3588上的适配流程记录

本文详细记录了在瑞芯微RK3588上进行Qwen3-VL-4B-Instruct多模态大模型的完整适配记录,以及在适配过程中容易出现问题的重点事项。 QWen3-VL-4B模型的下载与测试 阿里在 2025 年 9 月推出了Qwen3-VL 系列视觉语言模型。相较于其前代产品(如 Qwen2-VL),Qwen3-VL 的发布标志着多模态大模型从简单的视觉感知正式跨越到了深层的逻辑推理与自主 Agent 交互的新阶段。Qwen3-VL 延续了阿里的开源精神,推出了涵盖从端侧到云端的多种规模模型。 !image.png 要进行Qwen3-VL-4B-Instruct这个模型在瑞芯微平台上的适配,首先需要下载模型文件,并在PC端进行基本的推理测试,验证下载到的模型文件的正确性,这部分工作在详解QWen3-VL模型的测试以及vLLM生产环境部署流程一文中已有详细介绍。 Qwen3-VL-4B-Instruct模型在HuggingFace中的链接路径如下,按照上文使用transformers库从huggingface上下载并执行本地的推理验证: !image.png > 注:下文中我已经下载好的本地模型文件的路径为/mnt/d/HuggingFace/hub/models--Qwen--Qwen3-VL-4B-Instruct/snapshots/ebb281ec70b05090aa6165b016eac8ec08e71b17/ 环境的搭建 多模态大模型在瑞芯微平台NPU上的适配,需要同时用到瑞芯微的rknn-llm和rknn-toolkit2工具包。截至2026年1月份,这两个工具包在github上的最新版本是: - rknn-llm:1.2.3 - rknn-toolkit2:2.3.2 以下工作就基于这两个版本展开。比较奇葩的是,这两个工具包的最新版本,对于python环境的版本要求是相互冲突的。所以最好基于上面的两个工具包分别搭建各自的开发环境rknn和rkllm,在后续的不同步骤切换到不同的环境中执行。 rknn-toolkit2的环境搭建可以参考瑞芯微RK3588 NPU开发环境搭建笔记,rkllm的环境搭建流程可以参考轻量级LLM模型QWen2.5-0.5B在RK3588上的适配流程记录。 _整体来讲,QWen3-VL-4B-Instruct这个模型在RK3588开发板上的适配,主要是基于rknn-llm这个仓库中的__rknn-llm-main/examples/multimodal_model_demo__目录中所包含的文件展开。_ - 该目录下有一个README.md可以作为参考,但是其中缺少一些细节。 模型转换 针对QWen3-VL-4B-Instruct这类多模态模型的转换,实际上分为两个步骤,分别对应rknn模型和rkllm模型的转换。最终上板运行的demo,既需要同时加载独立的rknn模型文件和rkllm模型文件,也需要依赖于各自的运行时库:librkllmrt.so和librknnrt.so。 rknn模型的转换 这部分转换操作在rknn环境(即安装rknn-toolkit2工具包的环境中)执行。 这部分分为两个子步骤:模型的Vision部分转换为onnx文件,在从onnx格式的模型文件转换为上板运行的rknn模型文件。 在rknn-llm-main/examples/multimodal_model_demo目录下的export子目录中执行export_vision.py脚本转换模型的Vision部分到onnx文件中: 以上执行完成后会在当前export目录下生成一个onnx子目录,其中包含有转换好的模型Vision部分的onnx文件: 接下来,继续使用相同目录下的export_vision_rknn.py脚本把这个onnx文件转换为板端可运行的rknn模型文件: 以上执行完成后会在当前export目录下生成一个rknn子目录,其中包含有转换好的模型Vision部分的板端运行的rknn模型文件: 至此模型Vision部分的rknn上板运行的模型文件qwen3-vl_vision_rk3588.rknn就已经准备好了。 rkllm模型的转换 这部分转换操作在rkllm环境(即安装rknn-llm工具包的环境中)执行。 这部分同样可以分为两个子步骤:校准数据的准备,rkllm板端模型的转换。 校准数据准备的这部分工作主要在data子目录中进行,该目录下包含一个make_input_embeds_for_quantize.py脚本用于准备校准数据,但是这个脚本是针对Qwen2-VL的,直接在Qwen3-VL模型上使用会报错,所以我基于上面的脚本文件修改了一个make_input_embeds_for_quantize_qwen3-vl.py专门用于生成Qwen3-VL模型的校准数据,然后在export下执行: 以上执行完成后会在data/inputs.json和data/inputs_embeds/生成校准数据,后续rkllm板端模型的转换过程要用到这个校准数据。 接着就是模型转换的最后一步,也是最耗时的一步(主要原因是我的显卡型号比较新,与rkllm环境中的torch和cuda版本有冲突,所以只能使用CPU来执行模型转换):rkllm板端模型文件的转换。主要用到export下的export_rkllm.py脚本: 注意,以上脚本执行的过程中对内存需求巨大,如果在WSL中执行的话会在运行在出现Killed的问题,原因就是内存OOM了,此时需要修改WSL的内存和虚拟内存的配置:在自己的用户目录C:\Users[用户名]下创建一个.wslconfig文件,写入以下内容然后重启WSL,然后重新执行以上转换命令即可: 以上执行完成后会在当前目录下生成rkllm的板端执行文件_w8a8_rk3588.rkllm: 至此,板端推理demo运行所需要的两个板端模型文件qwen3-vl_vision_rk3588.rknn和_w8a8_rk3588.rkllm就准备好了。 板端推理应用程序编译 板端通用的推理应用程序代码在deploy目录下,需要注意RKLLM v1.2.3版本要求交叉编译的gcc版本在10.2以上,需要先下载工具链gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu: !image.png 在deploy目录下,修改其中的build-linux.sh文件中的交叉编译工具链路径GCC_COMPILER,然后执行build-linux.sh脚本编译板端执行文件即可。这个编译过程完成后会把所有上板运行的文件(除以上两个板端模型文件以外)放入一个install目录下。 上板运行测试 上板运行测试的过程,把以上的install目录、两个板端模型文件qwen3-vl_vision_rk3588.rknn和_w8a8_rk3588.rkllm上传到板子的models目录下上。然后执行: 最终demo在rk3588上运行的效果如下图所示: !image.png 参考资料 - airockchip/rknn-llm - airockchip/rknn-toolkit2 - 【硬核部署】Qwen3-VL 在 RK3588 上的部署-CSDN博客 --- 尝试从底层原理的角度去理解和解释技术问题:音视频/摄像头/智能家居/蓝牙/WiFi/无线通信/AI。 敬请关注微信公众号:Pavel Han。

从头实现一个Vision Transformer(ViT)模型

从头实现一个Vision Transformer(ViT)模型 本文针对简单的MNIST手写数字数据集识别的需求,完成了一个最简单的Vision Transformer模型的实现、训练和验证测试,建立对Vision Transformer模型实现流程的完整理解。 MNIST手写数字数据集是最简单的机器视觉数据集,基于MNIST实现一个Vision Transformer模型来实现手写数字字符的识别,难度不会太大,对于模型训练所需要的数据以及算力资源要求也不高,因此通过训练一个MNIST数据集的ViT识别模型,是一个绝佳的入门Vision Transformer模型的实验。 !image.png 关于Vision Transformer模型的整体架构,可以参加另外一篇笔记[[一文入门Vision in Transformer(ViT)模型的架构]]。 !image.png > _注:参考资料1中提供了一个完整的、对MNIST手写字符集进行识别的Vision Transformer模型,本文实际上是对以上资料的学习记录,并增加自己对于实现过程的理解。_ 如[[一文入门Vision in Transformer(ViT)模型的架构]]这篇笔记所总结的,ViT模型的架构和工作流程大致可以分为以下几个阶段:图像切片、添加Cls Token、位置编码、基于多头自注意力机制的Transformer Encoder、最终的训练头。因此,本文仍然按照以上结构来实现一个完整的Vision Transformer结构,并使用MNIST数据集对其进行训练以及最后的测试验证。 1. 导入必要的包 - 导入torchvision.transforms用于实现对MNIST字符集图像分辨率的resize,确保模型输入分辨率是patch分辨率的整数倍;以及把MNIST字符集的图像数据转换为Tensor格式。 - 训练过程所使用的优化器使用torch.optim中所包含的Adam。 - 利用torchvision.datasets.mnist从Pytorch官网自动下载MNIST数据集。 2. Patch Embeddings 这一步实现把输入图像切片为固定大小的patch,并且序列化。如[[一文入门Vision in Transformer(ViT)模型的架构]]所提到的,对于这部分功能,一般是通过一个步长(Stride)等于卷积核大小(kernel_size)的 2D 卷积(Conv2d)来实现的。 以上的 Conv2d 操作实际上是一个卷积投影操作: - kernel_size=patch_size :是用 patch_size×patch_size 的卷积核提取每个 patch - stride=patch_size :步长等于 patch 尺寸,从而实现非重叠的切分动作 - 输出通道数=d_model :每个 patch 被映射为 d_model 维的向量,实现每个patch的向量化 patch embedding的完整代码如下: 在以上的forward操作中,self.linear_project(x)这一步把一张输入图像的维度从(C,H,W)转换为(d_model,P_col,P_row); !image.png x.flatten(2)这一步把所有的patch展平,得到P个序列化Patch,每个patch的维度长度都是d_model,这实际上就是patch embedding操作的输出结果; !image.png 最后的x = x.transpose操作就只是交换输出数据的维度,以适配 Transformer 架构的标准输入格式。 !image.png 3. Cls Token与位置编码 为Batch中的每张图片的Patch列表的开头,增加一个Cls Token的逻辑相对比较简单,就是新建一个长度与Patch向量相同的cls token,然后把这个token放到patch向量的开头作为其0号token即可。 除了Cls Token以外,还需要为Patch向量中增加其位置编码。每个位置编码对于它所代表的位置来说都是唯一的,这使得模型可以识别每个Patch的位置。为了将位置编码添加到Patch向量中,它们必须具有相同的维度 d_model。位置向量的构建公式如下: !image.png 因此总的来说,这一步包含两个步骤:为Batch中每张图片的Patch向量列表中的初始位置增加一个Cls token;为所有的向量增加其位置编码。完整代码如下: 4. 单头及多头注意力模块的实现 有关多头注意力模块的理论以及计算流程等方面的内容,在[[如何理解Transformer架构中的多头注意力机制?]]一文中已有非常详细的总结和解释,在此不再赘述。 单头注意力机制的计算公式如下: 可结合上面的公式以及代码中的注释来理解单头注意力的计算逻辑和流程,基本上就是以上公式的一步步计算而已: 基于以上的单头注意力模块,实现多头注意力模块就比较简单了,就是对多个注意力模块独立计算,把计算结果合并起来,最后再通过一个线性层把多个单头输出的特征进一步融合并输出: 以上单头和多头注意力模块的流程和结构如下图所示: !image.png 5. Transformer Encoder 接下来是完整的Transformer Encoder的实现。Transformer Encoder的结构如下所示: !image.png 其对应的代码如下: 6.整个Vision Transformer模型 最终实现的整个Vision Transformer的模型架构如下: !image.png - 输入图像首先在PatchEmbedding模块中进行切分和向量化、序列化的操作。 - 序列化的Patch向量再在PositionalEncoding模块中增加额外的Cls Token,以及位置向量。 - 以上数据再经过连续N个TransformerEncoder模块的处理,反复通过多头注意力模块提取和融合图像中的特征。 - 最后在一个分类头处理后通过Softmax输出分类识别的概率。 完整Vision Transformer模型的实现如下: 7. 训练和测试 最后对以上构建出来的模型进行训练,以及对训练出来的模型使用MNIST的测试数据集进行验证。 超参数设置 对模型进行训练的超参数设置如下: 训练以及测试数据集的准备 训练和测试使用从Pytorch官网下载的MNIST数据集,使用以下代码下载数据集并准备dataloader: 模型训练 接下来就是对已经构建出来的模型参数进行训练,整个训练的执行流程实际上与[[基于Pytorch实现手写数字识别的卷积神经网络]]一文所描述的基于卷积神经网络的手写数字识别的训练流程大同小异: 训练了15个epoch,从打印的损失值可以看到其损失在稳定向下收敛过程中: 模型测试 最后就是使用以上训练好的模型,对MNIST的测试数据集进行测试: 经过上面的15轮测试,模型对测试集数据的测试准确度就达到了93%。 参考资料 - Building a Vision Transformer Model From Scratch | by Matt Nguyen | Toward Humanoids | Medium --- 尝试从底层原理的角度去理解和解释技术问题:音视频/摄像头/智能家居/蓝牙/WiFi/无线通信/AI。 敬请关注微信公众号:Pavel Han。