Toybrick

标题: 关于Pytorch中Conv2d转rknn的问题 [打印本页]

作者: LudvigCL    时间: 2020-4-11 21:51
标题: 关于Pytorch中Conv2d转rknn的问题
本帖最后由 LudvigCL 于 2020-4-11 21:50 编辑

Pytorch的conv2d层,对于个别输入输出通道参数在转换时会报ValueError的错误。

pt模型:
import torch
import torch.nn as nn

class Convolution_1(nn.Module):
    def __init__(self, inchannels=512, outchannels=6):
        super(Convolution_1, self).__init__()
        self.conv1x1 = nn.Conv2d(inchannels, outchannels, kernel_size=(1, 1), stride=1, padding=0)

    def forward(self, x):
        out = self.conv1x1(x)
        return out

model = Convolution_1()
out = model(torch.Tensor(1,512,28,28))
print(out.shape)
trace_model = torch.jit.trace(model, torch.Tensor(1,512,28,28))
trace_model.save('./pt_out/conv1_output.pt')

rknn转换:

import numpy as np
import cv2
from rknn.api import RKNN
import torchvision.models as models
import torch

if __name__ == '__main__':

    model = './pt_out/conv1_output.pt'
    input_size_list = [[512,28,28]]

    # Create RKNN object
    rknn = RKNN(verbose=True)

    # Load pytorch model
    print('--> Loading model')
    ret = rknn.load_pytorch(model=model, input_size_list=input_size_list)
    if ret != 0:
        print('Load pytorch model failed!')
        exit(ret)
    print('done')

    # Build model
    print('--> Building model')
    ret = rknn.build(do_quantization=True)
    if ret != 0:
        print('Build pytorch failed!')
        exit(ret)
    print('done')

    # Export rknn model
    print('--> Export RKNN model')
    ret = rknn.export_rknn('./pt_out/conv_1.rknn')
    if ret != 0:
        print('Export rknn failed!')
        exit(ret)
    print('done')报错信息:ValueError: cannot reshape array of size 2352 into shape (1,28,28,512)
torch版本:1.2.0
rknn-toolkit版本:1.3.1b7
转换代码及pt模型、输出日志:链接:https://pan.baidu.com/s/1sqp7TaBxT7z4ERfPsB_MZw
提取码:u97p



作者: jefferyzhang    时间: 2020-4-12 10:02
问题已上报
作者: LudvigCL    时间: 2020-4-12 10:14
jefferyzhang 发表于 2020-4-12 10:02
问题已上报

好的,多谢您
作者: jefferyzhang    时间: 2020-4-13 11:23
回复如下:

ret = rknn.build(do_quantization=True)
这里做量化的时候需要指定一个dataset.txt文件,文件内容是量化文件路径,它可以是一个npy文件,只要跟模型输入的shape一致。
比如
rknn.build(do_quantization=True,dataset ="./dataset.txt")
dataset.txt填写
./input.npy
作者: LudvigCL    时间: 2020-4-13 11:42
jefferyzhang 发表于 2020-4-13 11:23
回复如下:

ret = rknn.build(do_quantization=True)

好的多谢,我尝试一下
作者: LudvigCL    时间: 2020-4-13 16:29
jefferyzhang 发表于 2020-4-13 11:23
回复如下:

ret = rknn.build(do_quantization=True)

请问量化时如果指定为npy文件,那其中的数组是必须按照NHWC格式进行保存吗?
也即是说如果我在jit.trace时输入为tensor(1,512,28,28),那么保存在npy里数组的格式则必须是(1,28,28,512)的numpy数组而非(1,512,28,28)或是(512,28,28)的吗?
作者: LudvigCL    时间: 2020-4-13 17:47
jefferyzhang 发表于 2020-4-13 11:23
回复如下:

ret = rknn.build(do_quantization=True)

后续进行模型转换的时候又遇到了permute转换失效和core dumped两个错误。
模型定义:
import torch
import torch.nn as nn

class ClassHead(nn.Module):
    def __init__(self, inchannels=512, num_anchors=3):
        super(ClassHead, self).__init__()
        self.num_anchors = num_anchors
        self.conv1x1 = nn.Conv2d(inchannels, self.num_anchors * 2, kernel_size=(1, 1), stride=1, padding=0)
        self.output_act = nn.LogSoftmax(dim=-1)

    def forward(self, x):
        out = self.conv1x1(x)
        out = out.permute(0, 2, 3, 1)
        #b, h, w, c = out.shape
        #out = out.view(b, h, w, self.num_anchors, 2)
        #out = self.output_act(out)

        return out

classhead = ClassHead(512,3)
out = classhead(torch.Tensor(1,512,28,28))
print(out.shape)
trace_model = torch.jit.trace(classhead, torch.Tensor(1,512,28,28))
trace_model.save('./pt_out/classhead_output.pt')

rknn转化和推理:
import numpy as np
import cv2
from rknn.api import RKNN
import torchvision.models as models
import torch

if __name__ == '__main__':

    model = './pt_out/classhead_output.pt'
    input_size_list = [[512,28,28]]

    # Create RKNN object
    rknn = RKNN(verbose=True)

    # Load pytorch model
    print('--> Loading model')
    ret = rknn.load_pytorch(model=model, input_size_list=input_size_list)
    if ret != 0:
        print('Load pytorch 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 pytorch failed!')
        exit(ret)
    print('done')

    # Export rknn model
    print('--> Export RKNN model')
    ret = rknn.export_rknn('./pt_out/classhead_output.rknn')
    if ret != 0:
        print('Export rknn failed!')
        exit(ret)
    print('done')

    ret = rknn.load_rknn('pt_out/classhead_output.rknn')

    # init runtime environment
    print('--> Init runtime environment')
    ret = rknn.init_runtime()
    if ret != 0:
        print('Init runtime environment failed')
        exit(ret)
    print('done')

    # Set inputs
    img = np.load('./input.npy')

    # Inference
    print('--> Running model')
    outputs = rknn.inference(inputs=[img])
    print('output')
    print(outputs[0].shape)

在这里维度转换out = out.permute(0, 2, 3, 1)会失效。torch模型推理输出尺寸为(1, 28, 28, 6),但是rknn模型推理的输出尺寸则为(1, 6, 28, 28),permute函数的维度转换没有生效。
第二个问题是如果如下所示继续加入view和Logsoftmax后:

import torch
import torch.nn as nn

class ClassHead(nn.Module):
    def __init__(self, inchannels=512, num_anchors=3):
        super(ClassHead, self).__init__()
        self.num_anchors = num_anchors
        self.conv1x1 = nn.Conv2d(inchannels, self.num_anchors * 2, kernel_size=(1, 1), stride=1, padding=0)
        self.output_act = nn.LogSoftmax(dim=-1)

    def forward(self, x):
        out = self.conv1x1(x)
        out = out.permute(0, 2, 3, 1)
        b, h, w, c = out.shape
        out = out.view(b, h, w, self.num_anchors, 2)
        out = self.output_act(out)

        return out

classhead = ClassHead(512,3)
out = classhead(torch.Tensor(1,512,28,28))
print(out.shape)
trace_model = torch.jit.trace(classhead, torch.Tensor(1,512,28,28))
trace_model.save('./pt_out/classhead_output_2.pt')

模型转换过程会在build时发出warning: Do not support shape > 4. 虽然能够转换生成rknn模型但是会在Init runtime environment时报错:Segmentation fault (core dumped)
我在dataset中指定的input.npy是一个shape为(1, 28, 28, 512)的一个numpy数组。请问这两个错误是什么原因

代码以及模型、错误记录:
链接:https://pan.baidu.com/s/1FlaC6CSMhRzaewiX2iJnsQ
提取码:ovnh


作者: jefferyzhang    时间: 2020-4-13 18:16
LudvigCL 发表于 2020-4-13 17:47
后续进行模型转换的时候又遇到了permute转换失效和core dumped两个错误。
模型定义:
import torch

你这种问题要自己先跟下,找到错误点NPU部门才会介入,他们不会帮你debug的。
首先你要在PC上做转换,不要在板子上搞。然后把其他问题都自己排除下。

init runtime要确保板子DRV API和rknn toolkit版本是匹配的。
测试仿真情况和在板子运行情况。
作者: LudvigCL    时间: 2020-4-13 18:25
jefferyzhang 发表于 2020-4-13 18:16
你这种问题要自己先跟下,找到错误点NPU部门才会介入,他们不会帮你debug的。
首先你要在PC上做转换,不 ...

目前就是在PC上进行转换,而且已经确定了permute函数转换后失效。
作者: jefferyzhang    时间: 2020-4-13 22:37
LudvigCL 发表于 2020-4-13 18:25
目前就是在PC上进行转换,而且已经确定了permute函数转换后失效。

你是在Init runtime environment时候出错,请发下你toolkit、api、drv三者的版本号分别是多少
作者: jefferyzhang    时间: 2020-4-14 08:16
LudvigCL 发表于 2020-4-13 16:29
请问量化时如果指定为npy文件,那其中的数组是必须按照NHWC格式进行保存吗?
也即是说如果我在jit.trace ...

回复如下:

必须按照NHWC的格式。
ps.如果使用npy文件量化并且初始化设置如下
rknn=RKNN(verbose=True)
就会有一个Warning警告
W xxx.npy need NHWC format!
作者: LudvigCL    时间: 2020-4-14 09:52
jefferyzhang 发表于 2020-4-13 22:37
你是在Init runtime environment时候出错,请发下你toolkit、api、drv三者的版本号分别是多少 ...

Init runtime environment是在pc上进行仿真时候出错的,使用的toolkit是1.3.1b7版本
作者: LudvigCL    时间: 2020-4-14 09:53
jefferyzhang 发表于 2020-4-14 08:16
回复如下:

必须按照NHWC的格式。

好的多谢指点
作者: jefferyzhang    时间: 2020-4-14 09:54
LudvigCL 发表于 2020-4-14 09:52
Init runtime environment是在pc上进行仿真时候出错的,使用的toolkit是1.3.1b7版本

beta7在仿真时候是会出问题的,这个只是beta版本。可以试试用1.3.0版来加载这个模型,
不然你只能等正式版出来看看了。
作者: LudvigCL    时间: 2020-4-14 10:07
jefferyzhang 发表于 2020-4-14 09:54
beta7在仿真时候是会出问题的,这个只是beta版本。可以试试用1.3.0版来加载这个模型,
不然你只能等正式 ...

好的,抱歉劳烦您了
作者: luxiaofei    时间: 2020-4-17 14:50
jefferyzhang 发表于 2020-4-14 09:54
beta7在仿真时候是会出问题的,这个只是beta版本。可以试试用1.3.0版来加载这个模型,
不然你只能等正式 ...

BETA版本在哪里可以找到呢?
作者: jefferyzhang    时间: 2020-4-17 15:03
luxiaofei 发表于 2020-4-17 14:50
BETA版本在哪里可以找到呢?

链接:https://pan.baidu.com/s/1DuLeBawfoBP62mu0ADNGAA 
提取码:qtys




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3