Toybrick

多输入时,通道顺序为何会乱? Python接口怎么用多输入?

xsky

中级会员

积分
388
楼主
发表于 2020-2-22 21:56:12    查看: 10916|回复: 6 | [复制链接]    打印 | 显示全部楼层
本帖最后由 xsky 于 2020-2-22 22:30 编辑

在多输入时,各个输入shape不一样,为何从onnx转换为rknn后输入的顺序会乱, 输出的顺序是正常的,
另外C API 可以支持多输入, Python接口怎么构选多输入?  user guide 文档并没有叙述.
谢谢!

Pytorch             1.2.0
RKNN                1.3.0tensorflow         1.14.0
onnx                 1.4.1
onnx-tf              1.2.1
RKNN API  1.3.0,  DRIVE: 1.3.0     Debain 10
如下代码:

  1. import platform
  2. import os
  3. import torch
  4. import numpy as np

  5. from rknn.api import RKNN

  6. import onnx
  7. from onnx_tf.backend import prepare

  8. class LSTM(torch.nn.Module):

  9.     def __init__(self, input_size, hidden_size):
  10.         super(LSTM, self).__init__()

  11.         self._input_size = input_size
  12.         self._hidden_size = hidden_size
  13.         self._fc = torch.nn.Linear(input_size, input_size)
  14.         self._tanh = torch.nn.Tanh()
  15.         self._sigmoid = torch.nn.Sigmoid()

  16.     def forward(self, x, h0, c0):

  17.         return self._fc(x), self._sigmoid(h0), self._sigmoid(c0)
  18.         #ox, (h1, c1) = self._lstm(x, (h0, c0))
  19.         return ox, h1, c1

  20. if __name__ == '__main__':

  21.     system = platform.system()

  22.     isize = 128
  23.     hsize = 64
  24.     #m = torch.nn.Linear(isize, hsize)
  25.     m = LSTM(isize, hsize)
  26.     m.eval()
  27.     m.float()

  28.     h0 = torch.full((1, 1, hsize), fill_value=0.15, dtype=torch.float)
  29.     c0 = torch.full((1, 1, hsize//2), fill_value=0.07, dtype=torch.float)
  30.     x = torch.full((1, isize), fill_value=0.1, dtype=torch.float)
  31.     #x1 = torch.full((1, hsize), fill_value=0.2, dtype=torch.float)
  32.     pt_file = "lstm{%dx%d}.pt" % (isize, hsize)

  33.     rknn = RKNN(verbose=True)
  34.     rknn.config(batch_size=1,
  35.                 epochs=1)  # asymmetric_quantized-u8,  quantized_dtype='dynamic_fixed_point-16' , channel_mean_value='0 0 0 1', reorder_channel='0 1 2',

  36.     #pt = torch.jit.trace(m, x, h0, c0)
  37.     #pt.save(pt_file)
  38.     #rknn.load_pytorch(model=pt_file, input_size_list=[[1, isize]])

  39.     onnx_file = pt_file + '.onnx'
  40.     torch.onnx.export(m, (x, h0, c0), onnx_file,
  41.                       export_params=True,  # store the trained parameter weights inside the model file
  42.                       # do_constant_folding=True,  # whether to execute constant folding for optimization
  43.                       opset_version=9,  # the ONNX version to export the model to
  44.                       input_names=['input', 'h0', 'c0'],  # the model's input names
  45.                       output_names=['output', 'h1', 'c1']  # the model's output names
  46.                       # dynamic_axes={'input' : {0 : 'batch_size'},    # variable lenght axes
  47.                       #              'output' : {0 : 'batch_size'}}
  48.                       )
  49.     rknn.load_onnx(model=onnx_file)

  50.     rknn_file = pt_file + '.rknn'
  51.     ret = rknn.build(do_quantization=False, dataset='./dataset.txt')
  52.     rknn.export_rknn(rknn_file)

  53.     print('--> Init runtime environment')

  54.     if system == 'Windows':
  55.         print("rknn run target rk1808")
  56.         ret = rknn.init_runtime(target='rk1808', target_sub_class='AICS')
  57.     else:
  58.         print("rknn run target self")
  59.         ret = rknn.init_runtime()
  60.     if ret != 0:
  61.         print('Init runtime environment failed')
  62.         exit(ret)
  63.     print('done')

  64.     ix = x.numpy()
  65.     tf_model = onnx.load(onnx_file)
  66.     tf_rep = prepare(tf_model)
  67.     tf_out, tf_h1, tf_c1 = tf_rep.run((ix, h0, c0))
  68.     tf_out = np.array(tf_out)
  69.     print("onnx out:", ix.shape, ', ', tf_out.shape)
  70.     print(tf_out)

  71.     torch_out, th_h1, th_c1 = m.forward(x, h0, c0)
  72.     print("torch [out]:", x.shape, ', ', torch_out.shape)
  73.     print(torch_out.detach().unsqueeze(0).numpy())

  74.     ih0 = h0.numpy()
  75.     ic0 = c0.numpy()
  76.     rknn_out = rknn.inference(inputs=[(ix, ih0, ic0)], data_type='float32', data_format='nchw')   # , inputs_pass_through=[1]
  77.     rknn_out = np.array(rknn_out)
  78.     print("rknn out:", ix.shape, ', ', rknn_out.shape)
  79.     print(rknn_out)

  80.     rknn.release()
复制代码


输出的模型形状,输入输出均已命名,且onnx模型可正常运行:



查询RKNN输入相关的代码, 在RK3399Pro上运行:
  1. ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &in_out_num, sizeof(in_out_num));
  2. if (ret < 0) {
  3.     printf(_LINE_MARK_ " rknn_query fail: query in out num, ret=%d\n", ret);
  4.     goto Error;
  5. }
  6. assert(_NInChs == in_out_num.n_input && _NOutChs == in_out_num.n_output);
  7. for (int i = 0; i < _NInChs; i++) {
  8.     inputs_attr[i].index = i;
  9.     ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(inputs_attr[i]), sizeof(inputs_attr[i]));
  10.     if (ret < 0) {
  11.         printf(_LINE_MARK_ " rknn_query fail: query inputs attrs, ret=%d\n", ret);
  12.         goto Error;
  13.     }
  14. }
  15. for (int i = 0; i < _NOutChs; i++) {
  16.     outputs_attr[i].index = i;
  17.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[i]), sizeof(outputs_attr[i]));
  18.     if (ret < 0) {
  19.         printf(_LINE_MARK_ " rknn_query fail: query outputs attrs ret=%d\n", ret);
  20.         goto Error;
  21.     }
  22. }
复制代码



输入为 (x, h0, c0)按顺序对应的shape 分另为:(1, 128), (1, 1, 64), (1, 1, 32),但在RKNN C API中获取到的输入属性为 (1, 1, 32), (1, 128), (1, 1, 64):

输出的顺序确是正确的(1, 128), (1, 1, 64), (1, 1, 32):, scale = 1}}



而且,  不同次导出的onnx,   RKNN编译查询得到的输入属性都会不同

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

xsky

中级会员

积分
388
沙发
 楼主| 发表于 2020-2-24 17:43:28 | 显示全部楼层
本帖最后由 xsky 于 2020-2-24 21:35 编辑
jefferyzhang 发表于 2020-2-23 11:04
为啥不直接用pytorch模型转rknn试试?

之前试了load_pytorch加载 build报错, 应该原因是fc输入要减少一维变成两维的。

不过针对这个多输入的问题还想请教一下:
1. 是啥原因输入的顺序和给的模型不一样?另外C接口查出来的输入属性中.name是空的,如果有这个名字也方便面匹配,onnx是给了名字的。
2. 多输入的Python接口运行是怎么用的?3. 多输入如果形状不一样可以么,比如 [1, 120, 128]  [1, 64] [1, 64]?

再请教一下,目前支持的这些模型格式,是不是都不支持LSTM运算符的?
现在想做个评估看看基本性能,想把TTS部到NPU,或者是测出LSTM的性能,拆出一部分部到上面。

谢谢

回复

使用道具 举报

xsky

中级会员

积分
388
板凳
 楼主| 发表于 2020-2-26 20:49:47 | 显示全部楼层
jefferyzhang 发表于 2020-2-26 09:50
NPU部门回复:
1.支持多输入多输出,多个输入时shape可以不一样,但是输入要按照nchw的格式,具体可以参考m ...

好的,谢谢
回复

使用道具 举报

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

本版积分规则

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


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