Toybrick

关于Pytorch中Conv2d转rknn的问题

LudvigCL

新手上路

积分
43
楼主
发表于 2020-4-11 21:51:36    查看: 34743|回复: 16 | [复制链接]    打印 | 只看该作者
本帖最后由 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

版主

积分
13580
沙发
发表于 2020-4-12 10:02:50 | 只看该作者
问题已上报
回复

使用道具 举报

LudvigCL

新手上路

积分
43
板凳
 楼主| 发表于 2020-4-12 10:14:25 | 只看该作者

好的,多谢您
回复

使用道具 举报

jefferyzhang

版主

积分
13580
地板
发表于 2020-4-13 11:23:58 | 只看该作者
回复如下:

ret = rknn.build(do_quantization=True)
这里做量化的时候需要指定一个dataset.txt文件,文件内容是量化文件路径,它可以是一个npy文件,只要跟模型输入的shape一致。
比如
rknn.build(do_quantization=True,dataset ="./dataset.txt")
dataset.txt填写
./input.npy
回复

使用道具 举报

LudvigCL

新手上路

积分
43
5#
 楼主| 发表于 2020-4-13 11:42:37 | 只看该作者
jefferyzhang 发表于 2020-4-13 11:23
回复如下:

ret = rknn.build(do_quantization=True)

好的多谢,我尝试一下
回复

使用道具 举报

LudvigCL

新手上路

积分
43
6#
 楼主| 发表于 2020-4-13 16:29:25 | 只看该作者
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

新手上路

积分
43
7#
 楼主| 发表于 2020-4-13 17:47:46 | 只看该作者
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

版主

积分
13580
8#
发表于 2020-4-13 18:16:29 | 只看该作者
LudvigCL 发表于 2020-4-13 17:47
后续进行模型转换的时候又遇到了permute转换失效和core dumped两个错误。
模型定义:
import torch

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

init runtime要确保板子DRV API和rknn toolkit版本是匹配的。
测试仿真情况和在板子运行情况。
回复

使用道具 举报

LudvigCL

新手上路

积分
43
9#
 楼主| 发表于 2020-4-13 18:25:24 | 只看该作者
jefferyzhang 发表于 2020-4-13 18:16
你这种问题要自己先跟下,找到错误点NPU部门才会介入,他们不会帮你debug的。
首先你要在PC上做转换,不 ...

目前就是在PC上进行转换,而且已经确定了permute函数转换后失效。
回复

使用道具 举报

jefferyzhang

版主

积分
13580
10#
发表于 2020-4-13 22:37:50 | 只看该作者
LudvigCL 发表于 2020-4-13 18:25
目前就是在PC上进行转换,而且已经确定了permute函数转换后失效。

你是在Init runtime environment时候出错,请发下你toolkit、api、drv三者的版本号分别是多少
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

产品中心 购买渠道 开源社区 Wiki教程 资料下载 关于Toybrick


快速回复 返回顶部 返回列表