Notes—Convolutional layer

本文介绍了卷积层的基本概念,包括卷积操作、步长(stride)及零填充(zerp-padding)的作用。其中,卷积操作通过将过滤器与图像进行滑动并计算点积来实现特征提取;步长决定了过滤器移动的步幅;零填充则有助于保留特征图的分辨率,并充分利用边界信息以提升模型性能。

(this img is made by myself)
这里写图片描述

note:
Convolutional layer:
convolve the filter with image,slide over the image spatially,computing dot products.

stride:step

zerp-padding:
(1)reserve feature map’s resolution
(2)better utilize border information,which improves performance

(this img is downloaded from internet)
这里写图片描述

<think> Let me analyze this code and provide a helpful response. This appears to be a Python script for training a convolutional neural network (CNN) on the MNIST handwritten digit dataset using PyTorch, and then exporting the trained model to ONNX format. The code consists of several parts: Importing necessary libraries and setting hyperparameters Preparing the MNIST dataset with transformations Visualizing some examples from the dataset Defining a CNN model architecture using PyTorch Setting up loss function and optimizer Defining training and testing functions Training the model for 10 epochs and saving it Exporting the trained model to ONNX format At the end, the user mentions they want to convert their ONNX model to RKNN format but are having version discrepancies. They're using rknn-toolkit2 version 2.3.0 in their code, but on their Ubuntu system they have rknn-toolkit2 version 1.6.0 with Python 3.10. I'll focus on providing a solution for converting their ONNX model to RKNN format, considering the version discrepancy they're experiencing. Let me first understand the model architecture better: Input: MNIST images (1 channel, 28x28 pixels) First convolutional layer: 1→10 channels, 5x5 kernel, followed by ReLU and 2x2 max pooling Second convolutional layer: 10→20 channels, 5x5 kernel, followed by ReLU and 2x2 max pooling Fully connected layers: 320→50→10 (output classes for digits 0-9) The exported ONNX model uses: Input shape: [1, 1, 28, 28] Output shape: [1, 10] (representing probabilities for digits 0-9) ONNX opset version: 19 Now, the issue is the version discrepancy between the rknn-toolkit2 they're using in their code (2.3.0) and what's installed on their Ubuntu system (1.6.0). I need to provide code that will work with their installed version (1.6.0) to convert the ONNX model to RKNN format. </think> I see you've shared a PyTorch script for training a CNN model on the MNIST dataset, followed by ONNX conversion. You mentioned that you need to convert this ONNX model to RKNN format, but there's a version mismatch between the rknn-toolkit2 in your code (2.3.0) and what's installed on your Ubuntu system (1.6.0). Let me create a compatible RKNN conversion script for your system: <artifact id="rknn_conversion_script" type="application/vnd.ant.code" language="python" title="MNIST ONNX to RKNN Conversion Script"> from rknn.api import RKNN Configuration ONNX_MODEL = './model_Mnist_fixed.onnx' RKNN_MODEL = './model_Mnist.rknn' Initialize RKNN object rknn = RKNN(verbose=True) Pre-process config for input print('--> Config model') rknn.config(mean_values=[127.5], std_values=[127.5], target_platform='rk3588') print('done') Load ONNX model print('--> Loading model') ret = rknn.load_onnx(model=ONNX_MODEL) if ret != 0: print('Load ONNX model failed!') exit(ret) print('done') Build model print('--> Building model') ret = rknn.build(do_quantization=True, dataset='./dataset.txt') if ret != 0: print('Build model failed!') exit(ret) print('done') Export RKNN model print('--> Export RKNN model') ret = rknn.export_rknn(RKNN_MODEL) if ret != 0: print('Export RKNN model failed!') exit(ret) print('done') Optional: Inference testing print('--> Testing model on sample data') Set inputs img = cv2.imread('sample_digit.png', cv2.IMREAD_GRAYSCALE) img = cv2.resize(img, (28, 28)) img = np.expand_dims(img, axis=0) # Add batch dimension img = np.expand_dims(img, axis=0) # Add channel dimension Init runtime environment ret = rknn.init_runtime() if ret != 0: print('Init runtime environment failed') exit(ret) Inference print('--> Running model') outputs = rknn.inference(inputs=[img]) predicted = np.argmax(outputs[0][0]) print(f'Predicted digit: {predicted}') Release RKNN context rknn.release() </artifact> Additional Setup for RKNN Conversion For the above script to work properly, you'll need: Create a calibration dataset file: RKNN quantization requires a dataset file listing paths to sample images: <artifact id="dataset_generator" type="application/vnd.ant.code" language="python" title="Calibration Dataset Generator"> import os import numpy as np from torchvision import datasets, transforms import torch Create dataset directory if it doesn't exist os.makedirs('./calibration_images', exist_ok=True) Load a subset of MNIST images for calibration transform = transforms.Compose([transforms.ToTensor()]) dataset = datasets.MNIST(root='./data/mnist', train=True, transform=transform, download=True) data_loader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True) Save calibration images (using 100 images) with open('./dataset.txt', 'w') as f: for i, (img, ) in enumerate(data_loader): if i >= 100: # Use 100 images for calibration break # Convert tensor to numpy and save as raw format img_np = img.numpy().reshape(28, 28) * 255 img_np = img_np.astype(np.uint8) img_path = f'./calibration_images/img{i:03d}.bin' img_np.tofile(img_path) f.write(f'{img_path}\n') print(f"Created dataset.txt with {min(100, i+1)} image paths for calibration") </artifact> Version Compatibility Notes Since you're using rknn-toolkit2 version 1.6.0 on Ubuntu with Python 3.10, here are some important compatibility considerations: API differences: The script I provided uses the API structure compatible with older versions. The newer 2.3.0 version might have slightly different parameter names or methods. Target platform: I specified 'rk3588' as the target platform. Adjust this if you're targeting a different RK chip. Quantization parameters: The script uses basic quantization settings. You may need to adjust these (particularly mean_values and std_values) based on your model's preprocessing. Testing the model: The optional testing section requires you to have a sample image. You can generate one from your test dataset or skip this section if not needed. Troubleshooting Common Issues If you encounter errors: ONNX compatibility: Older RKNN versions may not support ONNX opset 19. Try re-exporting your ONNX model with a lower opset version (e.g., 11 or 13). Layer support: Some operations might not be supported. Check error messages for unsupported operations and consider simplifying your model if needed. Quantization issues: If quantization fails, try do_quantization=False first to verify the conversion works without quantization. Would you like me to explain any specific part of the conversion process in more detail? 按照这个分析来
最新发布
05-30
<think>好的,我现在需要帮助用户解决将ONNX模型转换为RKNN格式时遇到的问题。用户之前遇到了版本不兼容的问题,特别是rknn-toolkit2的版本差异。用户当前的系统安装的是1.6.0版本,而代码中可能引用了2.3.0的API,导致错误。我需要针对这个版本差异提供解决方案。首先,我需要确认用户的具体需求。用户已经有一个训练好的MNIST模型,并成功导出为ONNX格式,现在需要将其转换为RKNN格式以在Rockchip设备上运行。问题在于转换过程中由于版本不兼容导致的参数错误,比如之前的dynamic_input参数设置不正确。 接下来,我需要回忆rknn-toolkit21.6.0版本的API文档。这个版本可能和更新的版本在参数命名、方法支持上有差异。例如,用户之前遇到的batch_size参数位置错误,可能在新版本中该参数被移动到config方法中,而非build方法。然后,我需要构建一个兼容1.6.0版本的转换脚本。关键点包括:1.**配置参数**:确认dynamic_input的正确格式。根据错误提示,dynamic_input需要是列表的列表,而用户之前设置为False,这是无效的。正确的方式应该是提供输入形状的动态范围,例如[[[1,1,28,28]],[[4,1,28,28]]],表示支持batchsize从1到4。2.**参数过滤**:由于不同版本的API支持不同的参数,需要使用动态参数检测机制,确保只传递当前版本支持的参数。例如,通过inspect模块获取方法支持的参数列表,过滤掉无效参数。 3. **量化配置**:包括mean_values和std_values的正确设置,以及数据集准备。需要生成校准数据集,用于模型量化。4.**模型构建与导出**:确保build方法的参数正确,比如do_quantization、dataset路径等。此外,还需要考虑如何验证生成的RKNN模型是否正确,包括在Python中进行推理测试,以及如何处理可能出现的层不支持的问题。 用户可能还存在的疑问包括:如何动态获取API参数、多输入模型的处理、不同硬件平台的兼容性等。因此,在解决方案中需要包含这些方面的提示或工具函数,帮助用户进一步调试和验证。最后,确保提供的代码示例清晰,并附有详细注释,说明每个步骤的作用和注意事项。同时,准备好回答用户可能提出的相关问题,如动态输入的处理、版本差异的自动适配等。</think>以下是针对RKNN转换的完整解决方案,适配rknn-toolkit2 1.6.0版本: ```python # mnist_onnx_to_rknn.py import cv2 import numpy as np from rknn.api import RKNN import inspect def get_valid_params(rknn_obj, method_name): """动态获取API支持的参数列表""" method = getattr(rknn_obj, method_name) args = inspect.getfullargspec(method).args[1:] # 排除self参数 return args def convert_onnx_to_rknn(): # 初始化RKNN对象 rknn = RKNN(verbose=True) try: # 阶段1:配置参数 print('[1/4] 配置模型参数') config_params = { 'target_platform': 'rk3588', 'mean_values': [[33]], # 根据模型预处理设置 'std_values': [[78]], # 对应输入归一化参数 'dynamic_input': [ # 动态输入配置 [[1, 1, 28, 28]], # 最小输入形状 [[4, 1, 28, 28]] # 最大输入形状 ], 'quantized_dtype': 'asymmetric_affine-u8', 'optimization_level': 3 } # 过滤无效参数 valid_config = get_valid_params(rknn, 'config') filtered_config = {k:v for k,v in config_params.items() if k in valid_config} print("实际使用的配置参数:", filtered_config) if rknn.config(**filtered_config) != 0: raise RuntimeError("模型配置失败") # 阶段2:加载ONNX模型 print('[2/4] 加载ONNX模型') load_params = { 'model': 'model_Mnist_fixed.onnx', 'inputs': ['input'], # 根据模型输入节点名称修改 'outputs': ['output'], # 根据模型输出节点名称修改 'input_size_list': [[1, 1, 28, 28]] } if rknn.load_onnx(**load_params) != 0: raise RuntimeError("ONNX模型加载失败") # 阶段3:构建RKNN模型 print('[3/4] 构建RKNN模型') build_params = { 'do_quantization': True, # 开启量化 'dataset': 'dataset.txt', # 量化数据集路径 'pre_compile': False, # 适配1.6.0版本 'batch_size': -1 # 动态batch_size } # 过滤构建参数 valid_build = get_valid_params(rknn, 'build') filtered_build = {k:v for k,v in build_params.items() if k in valid_build} print("实际使用的构建参数:", filtered_build) if rknn.build(**filtered_build) != 0: raise RuntimeError("模型构建失败") # 阶段4:导出RKNN模型 print('[4/4] 导出RKNN模型') if rknn.export_rknn('mnist.rknn') != 0: raise RuntimeError("模型导出失败") print('✅ 转换成功!') # 阶段5:验证模型推理 print('[可选] 验证模型推理') test_image = cv2.imread('test_7.png', 0) # 读取测试图片 if test_image is not None: test_image = cv2.resize(test_image, (28, 28)) test_input = np.expand_dims(test_image, axis=(0, 1)).astype(np.float32) if rknn.init_runtime() != 0: print("⚠️ 运行时初始化失败") else: outputs = rknn.inference(inputs=[test_input]) predicted = np.argmax(outputs[0][0]) print(f'预测结果: {predicted}') except Exception as e: print(f'❌ 错误: {str(e)}') finally: rknn.release() if __name__ == '__main__': convert_onnx_to_rknn() ``` **配套工具脚本(生成量化数据集):** ```python # generate_dataset.py import os import numpy as np from torchvision.datasets import MNIST from torch.utils.data import DataLoader def create_calibration_dataset(): # 创建校准数据集目录 os.makedirs('calibration_data', exist_ok=True) # 加载MNIST训练集 dataset = MNIST(root='./data', train=True, download=True) dataloader = DataLoader(dataset, batch_size=1, shuffle=True) # 生成100个校准样本 with open('dataset.txt', 'w') as f: for i, (img, label) in enumerate(dataloader): if i >= 100: break # 转换为RKNN需要的二进制格式 img_np = img.numpy().reshape(28, 28).astype(np.uint8) file_path = f'calibration_data/calib_{i:03d}.bin' img_np.tofile(file_path) f.write(f'{file_path}\n') print('生成100个校准样本到dataset.txt') if __name__ == '__main__': create_calibration_dataset() ``` **关键功能说明:** 1. **动态参数适配**: ```python # 使用inspect模块动态获取API参数 def get_api_params(rknn_obj, method_name): return inspect.getfullargspec(getattr(rknn_obj, method_name))[0][1:] ``` 2. **形状验证机制**: ```python def validate_input_shape(rknn_model): rknn = RKNN() rknn.load_rknn(rknn_model) print("输入形状约束:", rknn.inputs[0].shape) print("是否动态:", rknn.inputs[0].shape.dynamic) rknn.release() ``` 3. **版本兼容层**: ```python def adapt_for_version(params, version='1.6.0'): """根据版本号调整参数名称""" version_map = { 'batch_size': ('1.6.0', 'rknn_batch_size'), 'dynamic_input': ('1.6.0', 'dynamic_input_shape') } adjusted = {} for k, v in params.items(): new_key = version_map.get(k, (None, k))[1] adjusted[new_key] = v return adjusted ``` **常见问题解决方案:** 1. **遇到不支持的ONNX算子**: - 使用ONNX Simplifier优化模型: ```bash python -m onnxsim model_Mnist.onnx model_Mnist_fixed.onnx ``` 2. **量化精度下降**: - 增加校准样本数量(修改generate_dataset.py中的循环次数) - 调整量化参数: ```python config_params.update({ 'quantized_algorithm': 'kl_divergence', 'quantized_method': 'channel' }) ``` 3. **动态形状推理失败**: - 显式指定推理时的形状: ```python rknn.init_runtime(target='rk3588', target_sub_class='AICS', input_size_list=[[4, 1, 28, 28]]) # 指定具体形状 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值