rknn如何转换模型
对于不同的芯片,需要不同的工具:
RKNN-Toolkit1 v1.7.1 (for RK3399pro/RK1808/RV1126/RV1109)
工具:https://github.com/rockchip-linux/rknn-toolkit
RKNN-Toolkit2 v1.3 (for RK356x/RK3588/RV1106)
工具: https://github.com/rockchip-linux/rknn-toolkit2
在rknn-toolkit/examples/的目录下有各种格式的模型转换为rknn模型的例子,照着例子改就行。
也可以从百度磁盘下载rknn-toolkit的DOCKER,里面包含了所有的github的代码及转换模型的环境https://eyun.baidu.com/s/3bqbs86j
提取码:rknn
rknn不量化的默认格式是什么
是float16的。
对于rknn输出的数据,可以使用如下的代码在float16和float32之间进行转换。
void __f32_to_f16(uint16_t* f16, float* f32, int num)
{
float* src = f32;
uint16_t* dst = f16;
int i = 0;
for (; i < num; i++) {
float in = *src;
uint32_t fp32 = *((uint32_t *) &in);
uint32_t t1 = (fp32 & 0x80000000u) >> 16; /* sign bit. */
uint32_t t2 = (fp32 & 0x7F800000u) >> 13; /* Exponent bits */
uint32_t t3 = (fp32 & 0x007FE000u) >> 13; /* Mantissa bits, no rounding */
uint32_t fp16 = 0u;
if( t2 >= 0x023c00u )
{
fp16 = t1 | 0x7BFF; /* Don't round to infinity. */
}
else if( t2 <= 0x01c000u )
{
fp16 = t1;
}
else
{
t2 -= 0x01c000u;
fp16 = t1 | t2 | t3;
}
*dst = (uint16_t) fp16;
src ++;
dst ++;
}
}
void __f16_to_f32(float* f32, uint16_t* f16, int num)
{
uint16_t* src = f16;
float* dst = f32;
int i = 0;
for (; i < num; i++) {
uint16_t in = *src;
int32_t t1;
int32_t t2;
int32_t t3;
float out;
t1 = in & 0x7fff; // Non-sign bits
t2 = in & 0x8000; // Sign bit
t3 = in & 0x7c00; // Exponent
t1 <<= 13; // Align mantissa on MSB
t2 <<= 16; // Shift sign bit into position
t1 += 0x38000000; // Adjust bias
t1 = (t3 == 0 ? 0 : t1); // Denormals-as-zero
t1 |= t2; // Re-insert sign bit
*((uint32_t*)&out) = t1;
*dst = out;
src ++;
dst ++;
}
}
转换caffe模型遇到问题:Deprecated caffe input usage
转换caffe模型的时候遇到错误:
这个是因为caffe模型的头部格式和rknn的默认格式不兼容。比如我的模型文件头部是:
name: "xxxx"
input: "data"
input_shape: { dim: 1 dim: 3 dim: 640 dim: 640 }
改为下面的格式就好了:
layer {
name: "data"
type: "Input"
top: "data"
input_param {
shape {
dim: 1
dim: 3
dim: 640
dim: 640
}
}
}
运行rknn模型遇到错误:This RKNN model is not a pre-compiled model
在板子上运行rknn模型,遇到错误:
This RKNN model is not a pre-compiled model, but the npu driver is mini driver.
Mini driver only support rknn models with pre-compiled mode.
Create RKNN model fail, error=-14
rknn_init error ret=-14
意思也很直白,我板子上的库是Mini driver, 所以只能加载预编译的模型,在转换模型的时候,打开预编译开关precompile:
rknn.config(mean_values=[[0, 0, 0]], std_values=[[1, 1, 1]], reorder_channel='2 1 0', pre_compile=True)
运行模型超过20秒,dmesg中有GPU[0] hang错误消息
运行时遇到错误:
E [op_optimize:428]CONCAT, uid 181 must have same quantize parameter!
同时,demsg中也有错误信息:
[galcore]: GPU[0] hang, automatic recovery.
这个问题我在rknn的技术群里咨询了, rknn1.7之后的版本对这个问题有较好的解决,只要升级板子上的rknn库和驱动就行了。
rknn的驱动和更新方法:https://github.com/rockchip-linux/rknpu
所谓更新驱动,就是把库拷贝到板子上。
官方文档里提到的驱动仅仅是驱动吗?
接上个问题,官方问题里似乎把rknn的动态库称为用户态驱动,所以在文档里看到更新驱动不能只更新ko文件,so文件也要一起更新。
量化模型的输出一定是uint8吗?
这个不一定,要看看模型加载后读取的tensor属性。以我的一个模型举例,目标检测模型转换后,bbox坐标是uint8的,但是分类置信度是float16的,需要用到本文上面提到的float16转float32的函数提取数据。
rknn的uint8输出如何反量化?
static float deqnt_affine_to_f32(int8_t qnt, int32_t zp, float scale)
{
return ((float)qnt - (float)zp) * scale;
}
如何dump网络的的原始数据
在板子上,在命令行上执行"export NN_LAYER_DUMP=1",然后运行程序执行网络推理,最后一层的数据就会dump到当前目录。
如果是在PC上用python评估rknn模型,在命令行上执行"export NN_LAYER_DUMP=1",之后运行模型,则会在当前目录输出大部分网络层的数据。
dump的数据基本都是float类型的,不用再反量化了。
如果读取的图片是BGR, 网络训练时是RGB, 怎么设置reorder_channel
转换模型时可以将rknn.config的reorder_channel设置为’2 1 0’。
rknn.config(mean_values=[[0, 0, 0]], std_values=[[1, 1, 1]], reorder_channel='2 1 0', precompile=True)
opencv读取到的数据算什么格式?
NHWC
如果网络要求NCHW输入,需要转换图片序列吗
不需要,只要在input的fmt设置为图片真实的格式, rknn的库就会自动处理这种转换
inputs[0].fmt = RKNN_TENSOR_NHWC;
文章出处登录后可见!