Tencent / ncnn

ncnn is a high-performance neural network inference framework optimized for the mobile platform
Other
20.4k stars 4.16k forks source link

请问怎么构建ncnn的3d mat输入? #4241

Open Lin-sudo opened 2 years ago

Lin-sudo commented 2 years ago

detail | 详细描述 | 詳細な説明

如题,我想用ncnn做3dcnn的推理,在issue https://github.com/Tencent/ncnn/issues/637#issuecomment-1118380058 支持3d卷积。

alexnet教程里,2d图片的输入是调用ncnn::Mat::from_pixels方法。如果我的cv::mat是3d的,是否有类似方法,或通过其他方法构建3dmat输入?

#include "mat.h"
unsigned char* rgbdata;// data pointer to RGB image pixels
int w;// image width
int h;// image height
ncnn::Mat in = ncnn::Mat::from_pixels(rgbdata, ncnn::Mat::PIXEL_RGB, w, h);

const float mean_vals[3] = {104.f, 117.f, 123.f};
in.substract_mean_normalize(mean_vals, 0);
LRY89757 commented 2 years ago

插个眼,看源码好像目前确实不太支持?缺少d这个额外维度,不过如果这样的话,ncnn的3D卷积神经网络是如何部署的😢

LRY89757 commented 2 years ago

或许你可以直接用这个mat来进行初始化: NCNN_FORCEINLINE Mat::Mat(int _w, int _h, int _d, int _c, void* _data, size_t _elemsize, Allocator* _allocator)

wzyforgit commented 2 years ago

Mat(int w, int h, int d, int c, size_t elemsize, int elempack, Allocator* allocator = 0);

Lin-sudo commented 2 years ago

@LRY89757 @wzyforgit 感谢大佬的回复。我尝试用对自己的模型进行前向计算

ncnn::Mat in(110, 110, 256, 3);
ncnn::Extractor ex = net->create_extractor();
ex.input("0", in);
ncnn::Mat out;
ex.extract("133", out);  // 出现了错误

出现了异常A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 28925 (ample.modeltest), pid 28883 (ample.modeltest)

net->load_param(paramPath.c_str());net->load_param(paramPath.c_str()); 都返回0,模型加载是成功的。同时,我尝试用ncnn/example里的squeezenetv1.1做测试,构建ncnn::Mat in(224, 224, 3);输入,能正常运行,不会报上面的错误。

接着我对每个blob输出进行测试,发现是在第二层的3d卷积出现了错误

image

我的第一层的3d卷积是

# 在pytorch中
nn.Conv3d(in_channels=3, out_channels=32, kernel_size=(1, 5, 5), stride=1, padding=(0, 2, 2)) 

在pytorch中输入[1,3,256,110,110]经过第一层3d卷积理想的输出是[1,32,256,110,110]。然而在ncnn中构建输入ncnn::Mat in(110, 110, 256, 3);(w=110,h=110,d=256,c=3),用Android Studio debug发现经过第一层3d卷积后的输出是(w=111,h=111,d=1,c=3),因此导致后续计算出现异常。我还尝试了输入ncnn::Mat in(110, 110, 3, 256);,但这样第一层3d卷积就报错了。


我原来的pytorch模型的输入是[batch, depth, channel, width, height] = [1, 256, 3, 110, 110],经过permute转化成[1, 3, 256, 110, 110]再做第一层3d卷积。我按照wiki教程将pytorch模型转化成onnx->ncnn模型。而ncnn/example的squeezenetv1.1的输入是[227, 227, 3]。所以我想问这个异常是不是因为通道组织不一样而导致的,麻烦大佬看一下🙏

image
deepage commented 2 years ago

1.首先使用pnnx去转pytorch模型; 2.根据你图里面输入是1x256x3x110x110时,可以使用 ncnn::Mat in(110, 100, 256, 3); in.fill(1.f); 这样构造出来的mat就是你需要的维度

Lin-sudo commented 2 years ago

1.首先使用pnnx去转pytorch模型; 2.根据你图里面输入是1x256x3x110x110时,可以使用 ncnn::Mat in(110, 100, 256, 3); in.fill(1.f); 这样构造出来的mat就是你需要的维度

大佬好,我按照教程用pnnx转pytorch模型时出现了以下错误,我的pytorch、libtorch都是1.10.0+cpu,看报错好像是没有找到模型参数,这是为什么?😭

$ ./pnnx physnet.pt inputshape=[1,256,3,110,110]
pnnxparam = physnet.pnnx.param
pnnxbin = physnet.pnnx.bin
pnnxpy = physnet_pnnx.py
ncnnparam = physnet.ncnn.param
ncnnbin = physnet.ncnn.bin
ncnnpy = physnet_ncnn.py
optlevel = 2
device = cpu
inputshape = [1,256,3,110,110]
inputshape2 =
customop =
moduleop =
############# pass_level0
############# pass_level1
no attribute value
no attribute value
no attribute value
no attribute value
terminate called after throwing an instance of 'torch::jit::IRAttributeError'
  what():  required keyword attribute 'value' is undefined
Aborted

这是我转.pt的代码

device = torch.device('cpu')
physnet = PhysNetED()
physnet.to(device)
physnet.load_state_dict(torch.load('model/physnet_epoch10.pkl', map_location=device))
physnet.eval()

inputTensor = torch.randn(1, 256, 3, 110, 110)
traced_script_module = torch.jit.trace(physnet, inputTensor)
output1 = traced_script_module(torch.ones(1, 256, 3, 110, 110))
output2 = physnet(torch.ones(1, 256, 3, 110, 110))
print(output1)
print(output2)
traced_script_module.save("physnet.pt")  #没有发生异常
LRY89757 commented 2 years ago

请问你的torch版本?pnnx目前支持的torch版本为1.8+ @Lin-sudo

nihui commented 2 years ago

onnx2ncnn 实际上不支持 3d conv pnnx 可以支持转换

Lin-sudo commented 2 years ago

我之前的pytorch、libtorch的版本都是1.10.0+cpu,我试了1.8.2的版本也是这个错误🥺

Z-Xiong commented 1 year ago

1.首先使用pnnx去转pytorch模型; 2.根据你图里面输入是1x256x3x110x110时,可以使用 ncnn::Mat in(110, 100, 256, 3); in.fill(1.f); 这样构造出来的mat就是你需要的维度

大佬好,我按照教程用pnnx转pytorch模型时出现了以下错误,我的pytorch、libtorch都是1.10.0+cpu,看报错好像是没有找到模型参数,这是为什么?sob

$ ./pnnx physnet.pt inputshape=[1,256,3,110,110]
pnnxparam = physnet.pnnx.param
pnnxbin = physnet.pnnx.bin
pnnxpy = physnet_pnnx.py
ncnnparam = physnet.ncnn.param
ncnnbin = physnet.ncnn.bin
ncnnpy = physnet_ncnn.py
optlevel = 2
device = cpu
inputshape = [1,256,3,110,110]
inputshape2 =
customop =
moduleop =
############# pass_level0
############# pass_level1
no attribute value
no attribute value
no attribute value
no attribute value
terminate called after throwing an instance of 'torch::jit::IRAttributeError'
  what():  required keyword attribute 'value' is undefined
Aborted

这是我转.pt的代码

device = torch.device('cpu')
physnet = PhysNetED()
physnet.to(device)
physnet.load_state_dict(torch.load('model/physnet_epoch10.pkl', map_location=device))
physnet.eval()

inputTensor = torch.randn(1, 256, 3, 110, 110)
traced_script_module = torch.jit.trace(physnet, inputTensor)
output1 = traced_script_module(torch.ones(1, 256, 3, 110, 110))
output2 = physnet(torch.ones(1, 256, 3, 110, 110))
print(output1)
print(output2)
traced_script_module.save("physnet.pt")  #没有发生异常

同问,请问解决了吗?我也是转PhysNet

nihui commented 2 months ago

针对onnx模型转换的各种问题,推荐使用最新的pnnx工具转换到ncnn In view of various problems in onnx model conversion, it is recommended to use the latest pnnx tool to convert your model to ncnn

pip install pnnx
pnnx model.onnx inputshape=[1,3,224,224]

详细参考文档 Detailed reference documentation https://github.com/pnnx/pnnx https://github.com/Tencent/ncnn/wiki/use-ncnn-with-pytorch-or-onnx#how-to-use-pnnx

angelOnly commented 1 month ago

1.首先使用pnnx去转pytorch模型; 2.根据你图里面输入是1x256x3x110x110时,可以使用 ncnn::Mat in(110, 100, 256, 3); in.fill(1.f); 这样构造出来的mat就是你需要的维度

我是这样构建的输入,但是代码报红,没法运行

image