-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Model Optimizer: Caffe Custom Layer Not Recognized? #191
Comments
Dear @jzhan299 So now you must create a CPU (and/or) GPU extension as well for ActivationAbs1. This is your problem. Once you create the CPU (and/or GPU) extension, you will overcome the above error. A CPU extension is C++ code. A GPU extension is a combination of OpenCL code and *.xml file (for GPU take a look at https://github.com/opencv/dldt/tree/2019/inference-engine/src/cldnn_engine/cldnn_global_custom_kernels) Please pay close attention to the name of your layer which shows up in your IR (*.xml file). The name in your CPU/GPU extension must match exactly which includes case sensitivity ! This is a common mistake that all of us make in creating custom layer extensions so please watch out for that. You're almost there ! All you have to do now is create a CPU or GPU extension. Unfortunately though, custom layers for MYRIAD are not yet supported. Please post here if you have further questions. Thanks, Shubha |
Hi Shubha: Thanks for the quick response. I'm a bit confused on how to create a CPU extension; in particular, I'm not sure what add_config and REG_FACTORY_FOR are for. Here's my attempt at creating the AbsVal extension:
But after writing this CPU extension, it still does not recognize the layer. Do I need to rebuild the extensions? If so, how? Otherwise, what other steps do I need to take? Thanks, |
Dear @jzhan299 Your ext_absval.cpp looks OK to me. To be honest, the easiest way to create a CPU extension is to copy an existing one, for example, argmax_cpp then modify the code to suit your needs. The Inference Engine Kernels Extensibility Doc is also helpful. After writing your new cpu extension, the cpu_extension.dll (or *.so) will be newly built, containing your new extension. When you build your Inference Engine and samples, you will also get a new cpu_extension.dll containing your new extension. Please see the classification_sample for how you include the extension library in your code:
You will have to do something similar. Hope it helps, Thanks, Shubha |
Hi Shubha: Thanks for the update; I've added the extension loader to my code. I am currently using the prebuilt Inference Engine that comes with OpenVino. Is the only option to build Inference Engine from this repository, and then load the created cpu_extension library in my code? Or is there a way to build the new cpu_extension.so using OpenVino's Inference Engine? -James |
Dear @jzhan299 when you add your extension code in the same location as the other extensions (like argmax.cpp), and rebuild your Inference Engine, then your extension will get built into the cpu_extension.dll . Please see this readme for how to rebuild Inference Engine. For the non-dldt version you simply just rebuild the samples as normal and your cpu_extension.dll will automatically get built if you put the code in the correct location (put it where argmax.cpp lives) |
Dear Shubha: Update: I have built Inference Engine, made a minor change to my ext_absval.cpp (changed output->size() to output.size(), see edit above), and now the CPU plugin recognizes my custom facemark detection model! However, my program now crashes when calling the InferenceEngine::InferRequest::Infer method. It does not crash for any of the pretrained OpenVINO models. Do you have any guidance on how to debug this? Infer seems to just be a wrapper function, so I can't tell if or how the custom layer is crashing. I can attach the code (the sample interactive_face_demo with modified FacialLandmarksDetection class) and my caffe model + IR representation if that helps. |
Dear @jzhan299 I have given very detailed steps on how to build a Debug IE here: Make sure your PATH variable is set to the directory which contains your debug plugins. I ran into this recently - sometimes the debug plugins are not there. If this is the case you must pull up the solution file (generated when you build Inference Engine) and build the specific plugin which you require. I'm talking about Windows here, for you in Linux it will be cmake. For instance your plugins are located here: And since I was debugging on CPU, I had to manually build MKLDNNPlugind.dll because it was missing from the Debug folder. But long story short, once you build a Debug version of Inference Engine and you get your paths all set up correctly, you should be able to step into your Infer function and understand exactly what is wrong. I have done this several times, trust me, it works ! The only problem for you is now you have to build IE in Debug which takes awhile. Please report back on this forum. I'm very happy you've made it so far with custom layers @jzhan299 ! Congrats ! Thanks, Shubha |
Dear Shubha: I've built debug IE, got the environment working (did have to build tbb_debug,dll and some other dlls manually). When debugging my program, stepping into the infer function brings me from InferenceEngine::InferRequest::Infer() to MKLDNNPlugind.dll!InferenceEngine::InferRequestBaseMKLDNNPlugin::MKLDNNAsyncInferRequest::Infer(InferenceEngine::ResponseDesc * resp):
Stepping in further leads to void MKLDNNPlugin::MKLDNNAsyncInferRequest::Infer():
Exceptions are then thrown in Wait(). But I am unable to tell what layer caused in my network this issue; there seems to be no way to step into the inference? Instead, I can only wait for the network to output and see the (erroring) output? |
Dear @jzhan299
Could you possibly put breakpoints in those files to see if you hit it ? Also you may have to include
in some files and sprinkle some debug statements using std::cout (this sucks because you'll have to recompile Inference Engine) Let me ask an Inference Engine developer how to debug this and I will report back to you. Thanks for your patience ! Shubha |
Dear Shubha: I believe I have access to mkldnn source code; as seen in my previous comment, I was able to step into mkldnn_async_infer_request. The problem is that this code seems to black box the neural network itself. There seems to be no way to step into the forward pass and finding a more specific error than "the network errors out while processing the input." As for my call stack, the call stack on Line 215 in ie_infer_async_request_thread_safe_default.hpp (before taskCopy->checkException in the wait function):
After exiting wait and extracting exception:
Also, thank you for asking an Inference Engine developer! I hope that together we can solve this issue quickly. -James |
Update: I poked around in the mo folder. Looking at the implementation of the Tanh and other activation layers, I think my implementation of the Absolute Value layer is incorrect, and is thus causing the crash. While I was able to modify their ops and _ext implementations for Absolute Value, I could not find their CPU extension files to modify from. Where is the CPU implementation for non-extension layers (in particular, where is the CPU file for dldt\model-optimizer\mo\ops\Activation.py)? Also, could you/the inference engine developer take a look at the revised files? I've zipped and attached them below.
|
Thanks for the update and the *.zip which you attached. I will take a look and will consult IE developers as needed. But http://caffe.berkeleyvision.org/tutorial/layers/absval.html is not an Activation Layer ! Are you using it as an Activation layer in your model ? Usually when we think of Activation Layers we think of Relu, tanh, exp, sigmoid, etc.... But are you actually using absval as an activation layer function in your model ? An activation layer is distinct from an Input or Output Layer, and I suppose you can use any function as an Activation Layer actually. To see where Activation.py is implemented for CPU, take a look at
Hope it helps, Thanks, Shubha |
Dear Shubha: Yes, I believe that I am using it as an activation layer. Caffe notes it as one as well. You can check the facemark detection model attached in the zip to confirm; though feel free to correct me if I am wrong. I will try implementing it in Activation.py and reporting back. Thank you for looking at my zip! Best, |
Dear @jzhan299 I already see this code in C:\Intel\dldt\inference-engine\src\mkldnn_plugin\nodes\mkldnn_activation_node.cpp but it's eltwise, which may be different than what you're trying to do.
|
Dear Shubha: Yes, element-wise is exactly what I am trying to do. As a result, I have added a quick if statement in
In
I have removed Reconverting the model and running the demo still yields: I also noticed that there is also [Update: I have implemented my own [Update 2 (06/28): Implemented ie_absval_layer.cpp and ie_absval_layer.hpp. Did so by taking the corresponding files for Tanh and replacing all tanh references with absval references. Still unsupported activation layer type. Will try rebuilding entire inference engine instead of individual projects.] Thanks, |
Hi James, were you able to make the absval layer work in openvino? We are also trying to add it as a custom layer for our Siamese network model but confused on how to go about doing it |
@jzhan299 were you able to finish this task? As of now OpenVINO support eltwise operation Abs. And all you need is to create an extractor for this op in the Model Optimizer (no need to write any CPU extension). |
It seems that the issues is not actual anymore as no response. Closing it. Feel free to reopen it or create a new one. |
I tried writing a custom layer for the Caffe Absolute Value Layer. As per your IDZ post and the official documentation, I created a absval.py and absval_ext.py:
EDIT: .\deployment_tools\model_optimizer\extensions\ops\absval.py:
EDIT: .\deployment_tools\model_optimizer\extensions\front\caffe\absval_ext.py
After writing this code, I was able to convert my Caffe landmark detection model using the ModelOptimizer into an IR representation:
But when I try to use the converted model in the interactive face demo, it errors out and says the primitive is not recognized.
The error log:
InferenceEngine:
API version ............ 1.6
Build .................. 23780
[ INFO ] Parsing input parameters
[ INFO ] Reading input
[ INFO ] Loading plugin CPU
[ INFO ] Loading network files for Face Detection
[ INFO ] Batch size is set to 1
[ INFO ] Checking Face Detection network inputs
[ INFO ] Checking Face Detection network outputs
[ INFO ] Loading Face Detection model to the CPU plugin
[ INFO ] Age/Gender DISABLED
[ INFO ] Loading network files for Head Pose Estimation network
[ INFO ] Batch size is set to 16 for Head Pose Estimation network
[ INFO ] Checking Head Pose Estimation network inputs
[ INFO ] Checking Head Pose Estimation network outputs
[ INFO ] Loading Head Pose Estimation model to the CPU plugin
[ INFO ] Emotions Recognition DISABLED
[ INFO ] Loading network files for Facial Landmarks Estimation
[ INFO ] Batch size is set to 16 for Facial Landmarks Estimation network
[ INFO ] Checking Facial Landmarks Estimation network inputs
[ INFO ] Checking Facial Landmarks Estimation network outputs
[ INFO ] Loading Facial Landmarks Estimation model to the CPU plugin
[ ERROR ] Unsupported primitive of type: AbsVal name: ActivationAbs1
Is there an error in my implementation, or there another problem that must be solved for Model Optimizer to recognize this primitive?
The text was updated successfully, but these errors were encountered: