Wednesday, 30 May 2018

Introducing NeuralMET

Updated 28 June 2018: new locations added

An Online Weather Forecaster using Artificial Intelligence Deep Learning Neural Networks built in MATLAB


In this post, I pick up from where I left off in my previous post(s) where I developed some preliminary Machine Learning (ML) models for weather prediction using MATLAB. In this next post, I deploy the weather forecasts into production in order to complete my end-to-end example of using MATLAB for prototyping and deploying Deep Learning neural networks. You will need to read the previous post for context, as I do not repeat any of that here.

Production Deployment via the MATLAB Compiler 


The MATLAB Compiler provides the option to build a self-contained Windows executable which encompasses the entire MATLAB code in a single application. However, for future-proofing / code re-usability, I instead chose to build a library in C# / .NET containing all the neural network prediction code (importing the trained networks via a MATLAB ".mat" data file -- 72 networks in all, covering the 8 variables across the 9 lookahead forecast periods), including the SQL database interaction (for reading the METAR observations and persisting the computed forecasts, every half hour). This was (almost) trivially simple to accomplish using the MATLAB Compiler Graphical-User-Interface. Having built the library (in my case, named NeuralMetLib.dll), I then built a very simple Windows Console application in C# which imported the compiled MATLAB library via the following few lines of code:

using MathWorks.MATLAB.NET.Arrays; 
using NeuralMetLib; 
namespace TestNeuralMetConsole 

class Program 
 { 
  static void Main(string[] args) 
   { 
    NeuralMet nm = new NeuralMet(); 
    MWArray resultMW= nm.testNeuralMET(); 
   } 
  } 


I deployed this Windows Console app on an AWS EC2 t2.small instance type and "wrapped it" behind a Windows Scheduler Task to enable the automatic triggering of forecast updates every half hour -- and that essentially completed the deployment of the production code.

Client Web Application


In order to consume the deployed forecasts and make them available for viewing, I built a simple ASP.NET web app, hosted on Microsoft Azure. You can find it here. This Online Forecaster automatically updates whenever new METAR data is obtained. It also displays the running statistics of the neural network forecasts versus the naïve ("zero-order-hold") forecasts (which can be compared directly with the Revised Error Curves in the previous post).

Conclusions & Next Steps


The MATLAB Compiler proved to be a straightforward and effective means of deploying trained Deep Learning Neural Network into production. Comparing this to my previous experience of deploying neural networks from TensorFlow, I found the MATLAB approach to be considerably easier.

As a next step, I'll use the same approach to deploy the Deep Learning training code (i.e., as well as the prediction code). In that way, the re-training of the neural networks can be fully automated, say, every month or so. I'll also add more locations (i.e., in addition to EGNS) once I capture the necessary METAR data.

I'd also like to try using Containers as opposed to entire Virtual Machine instances, in the interests of optimal use of infrastructure.

GOTCHAS


Dealing with the following "gotchas" was the most time-consuming aspect of the deployment. These aside, the entire process took only a couple of hours to build, test, and deploy. 

GOTCHA: In order for the Compiled MATLAB code to access the (Azure) SQL database, the following steps had to be carried out on the target machine (in my case, a Windows 2016 Server):

Installed JRE 8 from here

Installed Microsoft JDBC Driver 6.4 for SQL Server from here (where I arbitrarily selected 'C:\Program Files\JDBC6' for the installation location) 

Each time I accessed the SQL database from within the MATLAB source-code, I configured the database connection within MATLAB as follows:

javaaddpath('C:\Program Files\JDBC6\sqljdbc_6.4\enu\mssql-jdbc-6.4.0.jre8.jar','-end'); 

conn=database('DATABASE_SERVER_NAME',...
'ACCOUNT_NAME','PASSWORD',...
'com.microsoft.sqlserver.jdbc.SQLServerDriver',...
'jdbc:sqlserver://k00cpfylic.database.windows.net:1433;
                             database=DATABASE_SERVER_NAME'); 

where DATABASE_SERVER_NAME, ACCOUNT_NAME, and PASSWORD are (obviously!) for your own database rather than mine. Also, make sure the SQL Server database firewall is configured to allow connections from the target machine (straightforward in Azure when using a fixed IP address on the target machine). When compiled, the deployed application successfully connects to the SQL database.


DOUBLE GOTCHA: When compiling the MATLAB code via the MATLAB Compiler, there can be situations where multiple functions in MATLAB have the same name but different usage depending on the given Toolbox. In such cases you need to "steer" the Compiler by giving it some direction at compile-time. Specifically, when compiling functions that use the 'predict' function applied to Deep Learning neural nets (of type SeriesNetwork), you need to add the following pragma line to the function which contains the 'predict' function:


 %#function SeriesNetwork %declares which "predict" function to use 

Otherwise, the code will compile without error, but will give the following runtime error: 

Undefined function 'predict' for input arguments of type 'double'

GOTCHA: When building a .NET application which consumes the compiled MATLAB dll, make sure the project settings in Visual Studio are configured to build specifically for the 64bit CPU target (not Any CPU), otherwise an error similar to the following will arise at runtime:

Unhandled Exception: System.TypeInitializationException: The type initializer for 'NeuralMetLib.NeuralMet' threw an exception. ---> System.TypeInitializationExc eption: The type initializer for 'MathWorks.MATLAB.NET.Utility.MWMCR' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Mat hWorks.MATLAB.NET.Arrays.MWArray' threw an exception. ---> System.BadImageFormat Exception: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) at MathWorks.MATLAB.NET.Arrays.MWArray.mclmcrInitialize2(Int32 primaryMode) at MathWorks.MATLAB.NET.Arrays.MWArray..cctor() --- End of inner exception stack trace --- at MathWorks.MATLAB.NET.Utility.MWMCR..cctor() --- End of inner exception stack trace --- at NeuralMetLib.NeuralMet..cctor() --- End of inner exception stack trace --- at NeuralMetLib.NeuralMet..ctor() at TestNeuralMetConsole.Program.Main(String[] args) in E:\FlyLogicalSoftware\ VS2017\WinDotnet\NeuralMet\TestNeuralMetConsole\Program.cs:line