I exported a trained LSTM neural network from this example from Matlab to ONNX. Then I try to run this network with ONNX Runtime C#. However, it looks like I am doing something wrong and the network does not remember its state on the previous step.
The network should respond to the input sequences with the following outputs:
Input: [ 0.258881980200294 ]; Output: [ 0.311363101005554 ]
Input: [ 1.354147904050896 ]; Output: [ 1.241550326347351 ]
Input: [ 0.258881980200294, 1.354147904050896 ]; Output: [ 0.311363101005554, 1.391810059547424 ]
The first two examples are the sequences that consist of only one element. The last example is the sequence of two elements. These outputs are calculated in Matlab. I reset the network in Matlab between executing it with each new sequence.
Then I try to run the same network using ONNX Runtime. This is my C# code:
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using System;
using System.Collections;
using System.Collections.Generic;
namespace OnnxTest
{
public sealed class OnnxRuntimeTest
{
public OnnxRuntimeTest(ILogger logger)
{
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
private const string modelPath = @"E:\Documents\MATLAB\NeuralNetworkExport\onnx_lstm_medic.onnx";
private readonly ILogger logger;
public void Run()
{
using (var session = new InferenceSession(modelPath))
{
// Input values from the example above:
var input1 = GenerateInputValue(0.258881980200294f);
var input2 = GenerateInputValue(1.35414790405090f);
// I create a container to push the first value:
var container = new List<NamedOnnxValue>() { input1 };
//Run the inference
using (var results = session.Run(container))
{
// dump the results
foreach (var r in results)
{
logger.Log(string.Format("Output for {0}", r.Name));
logger.Log(r.AsTensor<float>().GetArrayString());
// Outputs 0,3113631 - as expected
}
}
// The same code to push the second value:
var container2 = new List<NamedOnnxValue>() { input2 };
using (var results = session.Run(container2))
{
// dump the results
foreach (var r in results)
{
logger.Log(string.Format("Output for {0}", r.Name));
logger.Log(r.AsTensor<float>().GetArrayString());
// Outputs 1,24155 - as though this is the first input value
}
}
}
}
private NamedOnnxValue GenerateInputValue(float inputValue)
{
float[] inputData = new float[] { inputValue };
int[] dimensions = new int[] { 1, 1, 1 };
var tensor = new DenseTensor<float>(inputData, dimensions);
return NamedOnnxValue.CreateFromTensor("sequenceinput", tensor);
}
As you can see, the second session run results with 1,24155 instead of the expected value (1.391810059547424) as though the network is still in its initial state. It looks like I do not save the state of LSTM-network, but I can't find how to do this in the documentation.
So, does anyone know how to make LSTM keep its state?