在rk3588上部署InternVL系列
在rk3588上部署InternVL2-1B
准备
首先要在hf上下载InternVL2-1B的模型传送门(镜像)
git clone https://hf-mirror.com/OpenGVLab/InternVL2-1B
还要安装rknn转换的必要软件,这里不多赘述
转换
将vision_model和mlp转为onnx的代码如下:
import numpy as np
import os
import torch
import torch.nn as nn
from transformers import AutoTokenizer, AutoModel
import torch.nn.functional as F
from PIL import Image
import torchvision.transforms as T
from torchvision.transforms import InterpolationMode
from transformers.modeling_utils import PreTrainedModel
IMAGENET_MEAN = (0.485, 0.456, 0.406)
IMAGENET_STD = (0.229, 0.224, 0.225)
def build_transform(input_size):
MEAN, STD = IMAGENET_MEAN, IMAGENET_STD
transform = T.Compose([
T.Lambda(lambda img: img.convert('RGB') if img.mode != 'RGB' else img),
T.Resize((input_size, input_size), interpolation=InterpolationMode.BICUBIC),
T.ToTensor(),
T.Normalize(mean=MEAN, std=STD)
])
return transform
def find_closest_aspect_ratio(aspect_ratio, target_ratios, width, height, image_size):
best_ratio_diff = float('inf')
best_ratio = (1, 1)
area = width * height
for ratio in target_ratios:
target_aspect_ratio = ratio[0] / ratio[1]
ratio_diff = abs(aspect_ratio - target_aspect_ratio)
if ratio_diff < best_ratio_diff:
best_ratio_diff = ratio_diff
best_ratio = ratio
elif ratio_diff == best_ratio_diff:
if area > 0.5 * image_size * image_size * ratio[0] * ratio[1]:
best_ratio = ratio
return best_ratio
def dynamic_preprocess(image, min_num=1, max_num=12, image_size=448, use_thumbnail=False):
orig_width, orig_height = image.size
aspect_ratio = orig_width / orig_height
# calculate the existing image aspect ratio
target_ratios = set(
(i, j) for n in range(min_num, max_num + 1) for i in range(1, n + 1) for j in range(1, n + 1) if
i * j <= max_num and i * j >= min_num)
target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])
# find the closest aspect ratio to the target
target_aspect_ratio = find_closest_aspect_ratio(
aspect_ratio, target_ratios, orig_width, orig_height, image_size)
# calculate the target width and height
target_width = image_size * target_aspect_ratio[0]
target_height = image_size * target_aspect_ratio[1]
blocks = target_aspect_ratio[0] * target_aspect_ratio[1]
# resize the image
resized_img = image.resize((target_width, target_height))
processed_images = []
for i in range(blocks):
box = (
(i % (target_width // image_size)) * image_size,
(i // (target_width // image_size)) * image_size,
((i % (target_width // image_size)) + 1) * image_size,
((i // (target_width // image_size)) + 1) * image_size
)
# split the image
split_img = resized_img.crop(box)
processed_images.append(split_img)
assert len(processed_images) == blocks
if use_thumbnail and len(processed_images) != 1:
thumbnail_img = image.resize((image_size, image_size))
processed_images.append(thumbnail_img)
return processed_images
def load_image(image_file, input_size=448, max_num=12):
image = Image.open(image_file).convert('RGB')
transform = build_transform(input_size=input_size)
images = dynamic_preprocess(image, image_size=input_size, use_thumbnail=True, max_num=max_num)
pixel_values = [transform(image) for image in images]
pixel_values = torch.stack(pixel_values)
return pixel_values
# 加载本地模型
path = './InternVL2-1B'
save_path = 'onnx/InternVL2-1B_vision.onnx'
image_file = 'InternVL2-1B/examples/image1.jpg'
def export_vision_InternVL(model_path: str, save_path: str):
"""
Export the vision encoder and projector of Janus-Pro-1B model to ONNX format
"""
# 设置默认数据类型为 float32
torch.set_default_dtype(torch.float32)
vl_gpt = AutoModel.from_pretrained(model_path,torch_dtype = torch.float32,trust_remote_code=True)
# Move model to CPU and convert to float32
vl_gpt = vl_gpt.cpu().eval().float() # 确保模型是 float32
# Create a wrapper class for vision encoder + projector
class VisionWrapper(nn.Sequential):
def __init__(self, model):
super().__init__()
self.vision_town = model.vision_model
self.mlp = model.mlp1
self.vision_mlp = model.extract_feature
def forward(self, pixel_values):
projected_features = self.vision_mlp(pixel_values)
return projected_features
# Create wrapper instance and convert to float32
vision_wrapper = VisionWrapper(vl_gpt)
vision_wrapper.eval().float() # 确保包装器也是 float32
# Create dummy input with float32
batch_size = 1
num_channels = 3
height = 448 # InternVL2 default image size
width = 448
dummy_input = load_image(image_file=image_file, max_num=12).to(torch.float32).cpu()
# dummy_input = torch.randn(batch_size, num_channels, height, width, dtype=torch.float32)
# Export to ONNX with higher opset version
torch.onnx.export(
vision_wrapper,
dummy_input,
save_path,
export_params=True,
opset_version=16, # 使用高版本 opset 以支持 scaled_dot_product_attention
do_constant_folding=True,
input_names=['pixel_values'],
output_names=['projected_features'],
dynamic_axes={
'pixel_values': {0: 'batch_size'},
'projected_features': {0: 'batch_size'}
},
# 添加额外的配置
operator_export_type=torch.onnx.OperatorExportTypes.ONNX,
training=torch.onnx.TrainingMode.EVAL,
verbose=False
)
print(f"Successfully exported vision components to {save_path}")
# Verify the exported model
import onnxruntime
# Create inference session
ort_session = onnxruntime.InferenceSession(save_path)
# Run inference with dummy input
ort_inputs = {
'pixel_values': dummy_input.numpy()
}
ort_outputs = ort_session.run(None, ort_inputs)
# Compare with PyTorch output
torch_output = vision_wrapper(dummy_input)
# Check numerical accuracy with更宽松的容忍度
import numpy as np
np.testing.assert_allclose(
torch_output.detach().numpy(),
ort_outputs[0],
rtol=1e-1, # 放宽相对误差容忍度
atol=1e-2 # 放宽绝对误差容忍度
)
print("ONNX model verification successful!")
# 打印一些统计信息
torch_output_np = torch_output.detach().numpy()
onnx_output_np = ort_outputs[0]
abs_diff = np.abs(torch_output_np - onnx_output_np)
rel_diff = np.abs((torch_output_np - onnx_output_np) / (torch_output_np + 1e-7))
print(f"\nValidation Statistics:")
print(f"Max absolute difference: {np.max(abs_diff):.6f}")
print(f"Mean absolute difference: {np.mean(abs_diff):.6f}")
print(f"Max relative difference: {np.max(rel_diff):.6f}")
print(f"Mean relative difference: {np.mean(rel_diff):.6f}")
if __name__ == "__main__":
os.makedirs('onnx', exist_ok=True)
try:
import onnx
try:
onnx_version = onnx.__version__
except AttributeError:
try:
onnx_version = onnx.version.version
except AttributeError:
onnx_version = "Unknown"
print(f"ONNX version: {onnx_version}")
except ImportError:
print("ONNX not installed")
import onnxruntime
print(f"ONNX Runtime version: {onnxruntime.__version__}")
export_vision_InternVL(path, save_path)
将onnx转为rknn的代码如下:
from rknn.api import RKNN
import numpy as np
import os
model_path = "./onnx/InternVL2-1B_vision.onnx"
target_platform = "rk3588"
rknn = RKNN(verbose=False)
rknn.config(
target_platform=target_platform,
mean_values=[[0.5 * 255, 0.5 * 255, 0.5 * 255]],
std_values=[[0.5 * 255, 0.5 * 255, 0.5 * 255]],
)
rknn.load_onnx(model_path, inputs=['pixel_values'], input_size_list=[[1,3,448,448]])
rknn.build(do_quantization=False, dataset=None)
os.makedirs("rknn", exist_ok=True)
rknn.export_rknn("./rknn/" + model_path.split("/")[-1].split(".")[0] + "_{}.rknn".format(target_platform))
语言模型参考rkllm的Qwen模型转换
如有疑问或需求,请联系QQ:1198807618,欢迎各位批评指正
在rk3588上部署InternVL系列的更多相关文章
- 总想自己动动手系列·2·本地和外网(Liunx服务器上部署的web项目)按照自定义的报文格式进行交互(完结篇)
一.准备工作 (1)创建一个web-project工程,部署本地可正常访问,部署在云服务上可访问. (2)理解如何在web.xml文件中配置过滤器,和创建一个自定义的过滤器. (3)懂得如何打war包 ...
- 总想自己动动手系列·1·本地和外网(Liunx服务器上部署的web项目)按照自定义的报文格式进行交互(准备篇)
一.准备工作 (1)有一台属于自己的云服务器,并成功部署和发布一个web项目(当然,本质上来说Java-Project也没问题),通过外网IP可以正常访问该web项目. 需要说明的是:任何web项目, ...
- 在腾讯云上部署Hexo博客
推荐理由 ----搭建个人的空间博客目前深受个人开发者的追捧,然而博客的种类和平台有很多,Hexo是一个开源的静态博客生成器.相比于其他博客而言它只要是web容器就能用.除了闷头专研技术之外,程序员还 ...
- 在 Ubuntu 14.04 服务器上部署 Hexo 博客
版权声明:本文由宋秉金 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/241080001487926962 来源:腾云阁 ...
- 在Nginx上部署ThinkPHP,解决Pathinfo问题
在Nginx上部署ThinkPHP,解决Pathinfo问题 事实上.要解决nginx不支持pathinfo的问题.有两个解决思路,一是不使用pathinfo模式,二是改动nginx的配置文件,使它支 ...
- .NET开发框架(五)-IIS上部署ASP.NET Core项目教程
系列教程:从初学者到架构师的一步步蜕变 本篇经验将和大家介绍如何在IIS上部署ASP.NET Core项目,希望对初学.NET CORE的童靴入门有所帮助! 1.打开VS,创建项目,选择ASP.NET ...
- 在CentOS上部署kubernetes1.9.0集群
原文链接: https://jimmysong.io/kubernetes-handbook/cloud-native/play-with-kubernetes.html (在CentOS上部署kub ...
- Tensorflow 模型线上部署
获取源码,请移步笔者的github: tensorflow-serving-tutorial 由于python的灵活性和完备的生态库,使得其成为实现.验证ML算法的不二之选.但是工业界要将模型部署到生 ...
- fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
andrew,20130601,guilin 本文记录在树莓派(fedora)上部署ASP.NET MVC2 的过程. 本文共分为六部分,分别是前置条件,Apache的安装,Mysql的安装,安装mo ...
- CentOS 7 上部署Mono 4 和Jexus 5.6
概述 在这篇文章中我们将讨论如何在CentOS 7操作系统,安装 jexus. mono 和 配置 jexus,因此它将能够在这种环境中运行一个asp.net mvc 4 应用.这篇文章是描述如何在 ...
随机推荐
- CF1837E Play Fixing 题解
首先来考虑什么情况方案数为 \(0\): 可以确定,在某一层中,两个原本都能晋级的队伍比赛: 可以确定,在某一层中,两个原本都不能晋级的队伍比赛. 发现假如写出每一场比赛及其胜者,可以形成一棵树形结构 ...
- Arduino 语法--数组
数组是一种可访问的变量的集合.Arduino的数组是基于C语言的,实现起来虽然有些复杂,但使用却很简单. 一.创建或声明一个数组 数组的声明和创建与变量一致,下面是一些创建数组的例子. arrayIn ...
- .NET周刊【2月第3期 2025-02-16】
国内文章 我们是如何解决abp身上的几个痛点 https://www.cnblogs.com/jackyfei/p/18709265 张飞洪分享了abp框架在.net社区的使用经验,认为其在模块化.D ...
- Flink学习(十三) Flink 常见核心概念分析
分布式缓存熟悉 Hadoop 的你应该知道,分布式缓存最初的思想诞生于 Hadoop 框架,Hadoop 会将一些数据或者文件缓存在 HDFS 上,在分布式环境中让所有的计算节点调用同一个配置文件.在 ...
- Scala面向对象之创建对象,重载构造方法,继承抽象类实现接口
package com.wyh.day01 object ScalaClass { def main(args: Array[String]): Unit = { val student = new ...
- 仿京东短信验证码UI效果(鸿蒙)
整体思路: 外层Stack布局,里面TextInput组件用来调起键盘,Row布局中循环出四个Text组件,Row布局覆盖在TextInput组件上,用来展示输入的数字. 定义两个参数,code用来接 ...
- C++ open()和read()函数使用详解
对于Framework工程师来说,必要C或者C++编程能力是必须的,像对设备节点的操作是最基本的操作,那么我们便会用到open和read函数.open()函数用于打开文件,而read()函数用于从打开 ...
- WSL2 - Ubuntu 22.04使用记录
1 安装 搭配Windows Terminal使用为佳,在微软商店可下载: 然后依照官网描述即可. 命令行中运行wsl --install即可.不过由于想自行指定发行版,于是: wsl --list ...
- [源码系列:手写spring] IOC第三节:Bean实例化策略InstantiationStrategy
主要内容 在第二节中AbstractAutowireCapableBeanFactory类中使用class.newInstance()的方式创建实例,仅适用于无参构造器. 大家可以测试一下,将第二节 ...
- MySQL-脏页的刷新机制
MySQL内存结构-缓冲区 MySQL的缓冲区中有数据页,索引页,插入缓冲等等,这个角度是从页的功能来分类的.本小节从另一个视角关注这些页,如果从 是否被修改过(和磁盘不一致) 这个角度来区分这些页, ...