scrapbook
  • "Unorganized" Notes
  • The Best Public Datasets for Machine Learning and Data Science
  • Practice Coding
  • plaid-API project
  • Biotech
    • Machine Learning vs. Deep Learning
  • Machine Learning for Computer Graphics
  • Books (on GitHub)
  • Ideas/Thoughts
  • Ziva for feature animation: Stylized simulation and machine learning-ready workflows
  • Tools
  • đŸȘ¶math
    • Papers
    • Math for ML (coursera)
      • Linear Algebra
        • Wk1
        • Wk2
        • Wk3
        • Wk4
        • Wk5
      • Multivariate Calculus
    • Improving your Algorithms & Data Structure Skills
    • Algorithms
    • Algorithms (MIT)
      • Lecture 1: Algorithmic Thinking, Peak Finding
    • Algorithms (khan academy)
      • Binary Search
      • Asymptotic notation
      • Sorting
      • Insertion sort
      • Recursion
      • Solve Hanoi recursively
      • Merge Sort
      • Representing graphs
      • The breadth-first search algorithm
      • Breadth First Search in JavaScript
      • Breadth-first vs Depth-first Tree Traversal in Javascript
    • Algorithms (udacity)
      • Social Network
    • Udacity
      • Linear Algebra Refresher /w Python
    • math-notes
      • functions
      • differential calculus
      • derivative
      • extras
      • Exponentials & logarithms
      • Trigonometry
    • Probability (MIT)
      • Unit 1
        • Probability Models and Axioms
        • Mathematical background: Sets; sequences, limits, and series; (un)countable sets.
    • Statistics and probability (khan academy)
      • Analyzing categorical data
      • Describing and comparing distributions
      • Outliers Definition
      • Mean Absolute Deviation (MAD)
      • Modeling data distribution
      • Exploring bivariate numerical data
      • Study Design
      • Probability
      • Counting, permutations, and combinations
      • Binomial variables
        • Binomial Distribution
        • Binomial mean and standard deviation formulas
        • Geometric random variable
      • Central Limit Theorem
      • Significance Tests (hypothesis testing)
    • Statistics (hackerrank)
      • Mean, Medium, Mode
      • Weighted Mean
      • Quartiles
      • Standard Deviation
      • Basic Probability
      • Conditional Probability
      • Permutations & Combinations
      • Binomial Distribution
      • Negative Binomial
      • Poisson Distribution
      • Normal Distribution
      • Central Limit Theorem
      • Important Concepts in Bayesian Statistics
  • đŸ“œïžPRODUCT
    • Product Strategy
    • Product Design
    • Product Development
    • Product Launch
  • đŸ‘šâ€đŸ’»coding
    • of any interest
    • Maya API
      • Python API
    • Python
      • Understanding Class Inheritance in Python 3
      • 100+ Python challenging programming exercises
      • coding
      • Iterables vs. Iterators vs. Generators
      • Generator Expression
      • Stacks (LIFO) / Queues (FIFO)
      • What does -1 mean in numpy reshape?
      • Fold Left and Right in Python
      • Flatten a nested list of lists
      • Flatten a nested dictionary
      • Traverse A Tree
      • How to Implement Breadth-First Search
      • Breadth First Search
        • Level Order Tree Traversal
        • Breadth First Search or BFS for a Graph
        • BFS for Disconnected Graph
      • Trees and Tree Algorithms
      • Graph and its representations
      • Graph Data Structure Interview Questions
      • Graphs in Python
      • GitHub Repo's
    • Python in CG Production
    • GLSL/HLSL Shading programming
    • Deep Learning Specialization
      • Neural Networks and Deep Learning
      • Untitled
      • Untitled
      • Untitled
    • TensorFlow for AI, ML, and DL
      • Google ML Crash Course
      • TensorFlow C++ API
      • TensorFlow - coursera
      • Notes
      • An Introduction to different Types of Convolutions in Deep Learning
      • One by One [ 1 x 1 ] Convolution - counter-intuitively useful
      • SqueezeNet
      • Deep Compression
      • An Overview of ResNet and its Variants
      • Introducing capsule networks
      • What is a CapsNet or Capsule Network?
      • Xception
      • TensorFlow Eager
    • GitHub
      • Project README
    • Agile - User Stories
    • The Open-Source Data Science Masters
    • Coding Challenge Websites
    • Coding Interview
      • leetcode python
      • Data Structures
        • Arrays
        • Linked List
        • Hash Tables
        • Trees: Basic
        • Heaps, Stacks, Queues
        • Graphs
          • Shortest Path
      • Sorting & Searching
        • Depth-First Search & Breadth-First Search
        • Backtracking
        • Sorting
      • Dynamic Programming
        • Dynamic Programming: Basic
        • Dynamic Programming: Advanced
    • spaCy
    • Pandas
    • Python Packages
    • Julia
      • jupyter
    • macos
    • CPP
      • Debugging
      • Overview of memory management problems
      • What are lvalues and rvalues?
      • The Rule of Five
      • Concurrency
      • Avoiding Data Races
      • Mutex
      • The Monitor Object Pattern
      • Lambdas
      • Maya C++ API Programming Tips
      • How can I read and parse CSV files in C++?
      • Cpp NumPy
    • Advanced Machine Learning
      • Wk 1
      • Untitled
      • Untitled
      • Untitled
      • Untitled
  • data science
    • Resources
    • Tensorflow C++
    • Computerphile
      • Big Data
    • Google ML Crash Course
    • Kaggle
      • Data Versioning
      • The Basics of Rest APIs
      • How to Make an API
      • How to deploying your API
    • Jupiter Notebook Tips & Tricks
      • Jupyter
    • Image Datasets Notes
    • DS Cheatsheets
      • Websites & Blogs
      • Q&A
      • Strata
      • Data Visualisation
      • Matplotlib etc
      • Keras
      • Spark
      • Probability
      • Machine Learning
        • Fast Computation of AUC-ROC score
    • Data Visualisation
    • fast.ai
      • deep learning
      • How to work with Jupyter Notebook on a remote machine (Linux)
      • Up and Running With Fast.ai and Docker
      • AWS
    • Data Scientist
    • ML for Beginners (Video)
    • ML Mastery
      • Machine Learning Algorithms
      • Deep Learning With Python
    • Linear algebra cheat sheet for deep learning
    • DL_ML_Resources
    • Awesome Machine Learning
    • web scraping
    • SQL Style Guide
    • SQL - Tips & Tricks
  • 💡Ideas & Thoughts
    • Outdoors
    • Blog
      • markdown
      • How to survive your first day as an On-set VFX Supervisor
    • Book Recommendations by Demi Lee
  • career
    • Skills
    • learn.co
      • SQL
      • Distribution
      • Hypothesis Testing Glossary
      • Hypothesis Tests
      • Hypothesis & AB Testing
      • Combinatorics Continued and Maximum Likelihood Estimation
      • Bayesian Classification
      • Resampling and Monte Carlo Simulation
      • Extensions To Linear Models
      • Time Series
      • Distance Metrics
      • Graph Theory
      • Logistic Regression
      • MLE (Maximum Likelihood Estimation)
      • Gradient Descent
      • Decision Trees
      • Ensemble Methods
      • Spark
      • Machine Learning
      • Deep Learning
        • Backpropagation - math notation
        • PRACTICE DATASETS
        • Big Data
      • Deep Learning Resources
      • DL Datasets
      • DL Tutorials
      • Keras
      • Word2Vec
        • Word2Vec Tutorial Part 1 - The Skip-Gram Model
        • Word2Vec Tutorial Part 2 - Negative Sampling
        • An Intuitive Explanation of Convolutional Neural Networks
      • Mod 4 Project
        • Presentation
      • Mod 5 Project
      • Capstone Project Notes
        • Streaming large training and test files into Tensorflow's DNNClassifier
    • Carrier Prep
      • The Job Search
        • Building a Strong Job Search Foundation
        • Key Traits of Successful Job Seekers
        • Your Job Search Mindset
        • Confidence
        • Job Search Action Plan
        • CSC Weekly Activity
        • Managing Your Job Search
      • Your Online Presence
        • GitHub
      • Building Your Resume
        • Writing Your Resume Summary
        • Technical Experience
      • Effective Networking
        • 30 Second Elevator Pitch
        • Leveraging Your Network
        • Building an Online Network
        • Linkedin For Research And Networking
        • Building An In-Person Network
        • Opening The Line Of Communication
      • Applying to Jobs
        • Applying To Jobs Online
        • Cover Letters
      • Interviewing
        • Networking Coffees vs Formal Interviews
        • The Coffee Meeting/ Informational Interview
        • Communicating With Recruiters And HR Professional
        • Research Before an Interview
        • Preparing Questions for Interviews
        • Phone And Video/Virtual Interviews
        • Cultural/HR Interview Questions
        • The Salary Question
        • Talking About Apps/Projects You Built
        • Sending Thank You's After an Interview
      • Technical Interviewing
        • Technical Interviewing Formats
        • Code Challenge Best Practices
        • Technical Interviewing Resources
      • Communication
        • Following Up
        • When You Haven't Heard From an Employer
      • Job Offers
        • Approaching Salary Negotiations
      • Staying Current in the Tech Industry
      • Module 6 Post Work
      • Interview Prep
  • projects
    • Text Classification
    • TERRA-REF
    • saildrone
  • Computer Graphics
  • AI/ML
  • 3deeplearning
    • Fast and Deep Deformation Approximations
    • Compress and Denoise MoCap with Autoencoders
    • ‘Fast and Deep Deformation Approximations’ Implementation
    • Running a NeuralNet live in Maya in a Python DG Node
    • Implement a Substance like Normal Map Generator with a Convolutional Network
    • Deploying Neural Nets to the Maya C++ API
  • Tools/Plugins
  • AR/VR
  • Game Engine
  • Rigging
    • Deformer Ideas
    • Research
    • brave rabbit
    • Useful Rigging Links
  • Maya
    • Optimizing Node Graph for Parallel Evaluation
  • Houdini
    • Stuff
    • Popular Built-in VEX Attributes (Global Variables)
Powered by GitBook
On this page
  • What you’ll learn
  • You will need these resources to follow this tutorial
  • Deploying trained neural nets to C++ and why ONNX
  • Converting a Keras model to ONNX
  • Compiling and loading a C++ DG Node
  • Compiling your node
  • Loading your node
  • Using CNTK and loading an ONNX file
  • Compiling and loading
  1. 3deeplearning

Deploying Neural Nets to the Maya C++ API

PreviousImplement a Substance like Normal Map Generator with a Convolutional NetworkNextTools/Plugins

Last updated 4 years ago

In the past year, I have discussed many neural net types and their applications here in the blog. I have implemented simplified examples of most of them using the Maya Python API. But in the creation of production applications, deploying these solutions to C++ is essential for performance reasons. In this article I discuss a reasonably simple solution for this in a Windows environment, using the ONNX file format as a means of saving and loading our models in a framework agnostic manner. Disclaimer: I’m not super experienced in C++ and the Maya C++ API. If you lack C++ skills don’t feel discouraged, this is a super simple example! You might want to check out . I also assume you are comfortable at least with my . Finally, I assume you are using Visual Studio 2017, and Maya 2018 update 5.

What you’ll learn

You will need these resources to follow this tutorial

Deploying trained neural nets to C++ and why ONNX

I have a long history of writing code for discontinued platforms, including Softimage, Windows Phone, and Fabric Engine. There is one lesson I have learned from these experiences: target the most popular platform in your field, even if some niche platform looks more interesting. So, my instinct for this article was to use Tensorflow. Tensorflow is the most popular ML framework nowadays, and it is actively maintained by Google; moreover, Tensorflow has a built-in Keras interface. Sadly, I found the deployment of trained Tensorflow models to C++ overly complicated, and the Windows support is lacking. The easiest alternative on Windows is CNTK, which is native to the system [Windows 10]. CNTK is actively developed by Microsoft and can be trained using Keras. On the downside, it is not a popular platform, which makes me wary of its future. , is an open-source format developed by Microsoft, Amazon, and Facebook. This format allows one to store a trained model and run it anywhere. Many packages like Caffe2 (Facebook), PyTorch, MXNet (Apache), MATLAB, and CNTK support ONNX; also, tools are available to convert ONNX models to and from Apple ML, Keras, Tensorflow, Scikit-learn, and others. Finally, companies like Nvidia, Qualcomm, and Tencent seem to support the format.

The ONNX logo, source: http://onnx.ai

So, even though I’m a bit skeptical of not using the most popular solution in the field, I feel like ONNX has significant traction and probably should not go away in the short term. In this tutorial we’ll convert a Keras model to ONNX and load the ONNX models using Windows’s CNTK library, then we output results to a C++ Maya DG Node.

Converting a Keras model to ONNX

  • Python 3.6

  • Jupyter Notebook

  • Some Keras backend (CNTK, Tensorflow, or Theano)

  • Keras

  • Scikit-learn

  • and, finally, onnxmltools

After training the model, we export it to ONNX using the following lines of code:

import onnxmltools onnx_model = onnxmltools.convert_keras(model, target_opset=7) onnxmltools.utils.save_model(onnx_model, 'irisModel.onnx')

Now you should have a .onnx file which you can load from your C++ code. Note that target_opset refers to the version of ONNX we are targeting. Opset 7 = version 1.2.

Compiling and loading a C++ DG Node

Compiling your node

#include <maya/MPxNode.h> #include <maya/MFnPlugin.h> #include <maya/MPlug.h> #include <maya/MDataBlock.h> #include <maya/MDataHandle.h> // (1) class emptyNode: public MPxNode { 
 }; // (2) MTypeId emptyNode::id(0x80014);emptyNode::emptyNode() {}emptyNode::~emptyNode() {} // (3) MStatus emptyNode::compute(const MPlug& plug, MDataBlock& data) { 
 } void* emptyNode::creator() { 
 } // (4) MStatus emptyNode::initialize() { 
 } // (5) MStatus initializePlugin(MObject obj) { 
 } MStatus uninitializePlugin(MObject obj { 
 }

We create a new class inheriting from the MPxNode class (1), then we give it a unique ID (2). In the compute function (3) we load the data we need from the data block, perform the computations, store the data back in the data block, and update the node’s dirty status. In the initialize function (4) we create attributes and declare their dependencies. Finally, we provide Maya with the entry points for its plug-in system in the initialize and uninitialized functions (5). To correctly compile your plug-in remember to adjust this settings in your Visual Studio project: (1) Set project type to DLL and output file to .mll (because of Maya); (2) Add C:\Program Files\Autodesk\Maya2018\include\ to the include directories in VC++ Directories; (3) Add C:\Program Files\Autodesk\Maya2018\lib to your additional include directories; (4) In the linker properties add ‘Foundation.lib’ and ‘OpenMaya.lib’ to Additional Dependencies, and the C:\Program Files\Autodesk\Maya2018\lib path to Additional Library Directories. See the following images for reference:

Once this you have done this, you can build your project to generate the .mll file that you can then load inside Maya.

Loading your node

One way to install your compiled node is to use the browse button in the Plug-in Manager.

You can load single filed plug-ins using the browse button. This path is ok if your plugin is one single file [like our emptyNode]. But since our plugin has many files (our .mll plus DLLs from the CNTK library), it is best to load it as a Maya module. So, I suggest you create a directory for all Maya modules you’ll be building if you don’t have one already. In it, you’ll create: (1) a folder for the Iris Model module, (2) a .mod file declaring the content of the Iris Model folder. Here is how your files and folder structure should look like:

And your irisModel.mod file should read like this: + irisModel 1.0 ./irisModel/ MOD_PLUG_IN_PATH+:=plug-ins PATH+:=bin This code tells Maya irisModel v1.0 lives at root/irisModule; Maya plug-in files will are stored in the plug-ins folder, and binary dependencies (in our case the CNTK DLLs) are stored in the bin folder. Finally, we need to make Maya look for our ‘mayamodules’ folder on startup. For that edit your Maya.env file (Users/Documents/Maya/2018/) adding this line to it: MAYA_MODULE_PATH=C:\PathTo\mayamodules Phew. That should do it. Copy the .mll file you have compiled to the ‘plug-ins’ folder you have created. Your empty C++ DG node should work fine when you load it through the Plug-in Manager window.

Using CNTK and loading an ONNX file

Search for CNTK. For simplicity I suggest you install the CPU-only version:

Once you have CNTK installed here is what you’ll need to do to load your model and get predictions from it: #include "CNTKLibrary.h" [
] // (1) const CNTK::DeviceDescriptor device = CNTK::DeviceDescriptor::CPUDevice();modelPtr = CNTK::Function::Load(“c:/filePath/model.onnx”, device, CNTK::ModelFormat::ONNX); // (2) CNTK::Variable inputVar = modelFunc->Arguments()[0];CNTK::Variable outputVar = modelFunc->Output(); // (3) CNTK::ValuePtr inputVal = CNTK::Value::CreateBatch(inputVar.Shape(), inputData, device);std::unordered_map<CNTK::Variable, CNTK::ValuePtr> inputDataMap = { { inputVar, inputVal } }; // (4) std::unordered_map<CNTK::Variable, CNTK::ValuePtr> outputDataMap = { { outputVar, nullptr } }; // (5) modelFunc->Evaluate(inputDataMap, outputDataMap, device); // (6) CNTK::ValuePtr outputVal = outputDataMap[outputVar];std::vector<std::vector<float>> outputData;outputVal->CopyVariableValueTo(outputVar, outputData); Here is what is going on:

  1. We define the hardware and get a pointer to the loaded model.

  2. Then we create variables for the inputs and outputs of the model.

  3. We create a mapping to pass our inputs to the model’s input variable.

  4. Then we create a mapping to the output variable using a null pointer to indicate the use of system allocated memory.

  5. Now we perform the actual prediction [evaluation in CNTK’s terms].

  6. And, finally, we get the output variable and cast its data to a vector of vectors (or matrix, or bi-dimensional array, or list of lists, or however else you want to call it).

std::string win_str_result; std::string prob_str_result; // get position of max element auto result_int = std::distance(outputData[0].begin(), std::max_element(outputData[0].begin(), outputData[0].end())); switch (result_int) { case 0: { win_str_result = "Iris Setosa"; break; } case 1: { win_str_result = "Iris Virginica"; break; } case 2: { win_str_result = "Iris Versicolor"; break; } } auto probabilities = outputData[0]; prob_str_result = "[ " + std::to_string(probabilities[0]) + ", " + std::to_string(probabilities[1]) + ", " + std::to_string(probabilities[2]) + " ]";

Compiling and loading

In Conclusion

In this article, you have learned one path to deploying Neural Networks to Maya using the C++ API. This is an important component in the deployment of more production like solutions. The solution described in this article is relatively easy to implement and is highly compatible with many popular frameworks and platforms. I hope this will enable you in taking your projects to the next level!

To turn your Keras models into ONNX models, you’ll need the package. Sadly ‘onnxmltools’ is only available for Python 3. So, my recommendation is that you install these dependencies:

I do recommend you use (or better yet ), which is a way to have many different Python installations smartly organized in your computer. You install Anaconda using a GUI and operate it through a prompt using no more than a handful of commands. Once you’ve installed all dependencies, you are ready to train the model and save it to ONNX. I’ll be using the model I’ve trained in my first tutorial on . You can download the Jupyter Notebook to train the model in the . The model uses the Iris dataset, to infer one of three types of flowers based on the size of sepals and petals.

Samples of the classes in the Iris dataset

Before loading your ONNX model, you’ll need to create a Maya DG Node you can load it in. Since Maya’s Python API is a wrapping of its C++ API, this is very similar to what we have previously done in the . With the added complexities of compiling a Maya plugin, many of which have been addressed by . Please review these materials if you feel like you are missing something.

I provide you with the code for two different DG nodes in . One is an empty node template, and the other is the final code. You’ll notice from the empty node that a C++ DG Node has the same structure than a Python DG Node:

(1) Changes made to the project’s General properties
(2) Changes made to the project’s VC++ Directories properties
(3) Changes made to the project’s C/C++ properties
(4) Changes made to the project’s Linker properties
Snapshot of a Maya module folder structure

Ok. Now we need to fill our DG node with the important stuff. You’ll have to create the same attributes we have created in the . Since this is very similar, I won’t repeat myself. You can find the final code in the . Then we’ll need to get the values from the data block and feed it to our model. To load the ONNX model, we’ll use the CNTK library. You can install it using the NuGet package manager inside Visual Studio. Rick click the References in your project and start NuGet, like so:

Opening the NuGet package manager.
Installing CNTK from NuGet

In the final code, available in the , you’ll notice we have created a model cache class, so we don’t need to load the model at every new evaluation; we also make the model path variable, using an MPxNode attribute. Finally, we create two strings to properly display the name of the predicted flower and the predicted probabilities.

After compiling your code, you’ll see many files in your Release folder. Copy your irisModel.mll file to the ‘plug-ins’ . Copy all other .dll files to the ‘bin’ . These DLLs are from the CNTK we are using. If everything is set up correctly you can load the Maya sample scene found in the resources; it should look like this:

Our C++ node running predictions live inside Maya.
onnxmltools
Anaconda
miniconda
how to use Neural Nets inside Maya
resources for this article
tutorial on running neural nets from a Python DG node
Raffaele Fragapane’s video series
the resources section
Python DG tutorial
resources
resources
folder we have previously created
folder we have previously created
Raffaele Fragapane’s sensible introduction to compiling Maya C++ Plug-ins
tutorial on running neural nets from a Python DG node
Deploying trained neural nets to C++ and why ONNX
Converting a Keras model to ONNX
Compiling and loading a C++ Maya DG node
Using CNTK and loading an ONNX file
ONNX, or Open Neural Network Exchange