Message Boards Message Boards

[✓] Avoid example of NetChain running in MXNet to cause Error?

GROUPS:

Cross post here

Problem remains in Mathematica 11.2

First defining the net

SeedRandom[1234];
net = NetInitialize@NetChain[{5, 3}, "Input" -> 2];
{net[{1, 2}], net[{0, 0}], net[{0.1, 0.3}]}

{{1.27735, -1.21455, -1.02647}, {0., 0., 0.}, {0.141054, -0.145882, -0.099945}}

Exporting it to net of MXNet.

Export["simple model-symbol.json", net, "MXNet"]

The JSON file(It define the net structure) is

enter image description here

Via the code we can see the name of parameter is the same between params and JSON file.

import mxnet as mx
mx.nd.load('simple model-0000.params')

enter image description here

It has error ValueError: need more than 1 value to unpack when importing the net.

import mxnet as mx
sym, arg_params, aux_params = mx.model.load_checkpoint('simple model', 0)

enter image description here

Complete code to make prediction.(data_names and label_names can be shown in JSON file.)

import mxnet as mx
import numpy as np
sym, arg_params, aux_params = mx.model.load_checkpoint('simple model', 0)
mod = mx.mod.Module(symbol=sym,data_names=['Input'],label_names=['2'])
mod.bind(for_training=False, data_shapes=[('Input', (1,2))])
mod.set_params(arg_params, aux_params)

input_data=np.array([[1,2]])
array = mx.nd.array(input_data)

from collections import namedtuple
Batch = namedtuple('Batch', ['Input'])
mod.forward(Batch([array]))

prob = mod.get_outputs()[0].asnumpy()
prob = np.squeeze(prob)
print prob

Version:

Mathematica "11.2.0 for Microsoft Windows (64-bit) (September 11, 2017)"

MXNet 0.11.1 (the latest version 20170905mxnetx64vc14cpu.7z)

How to fix it?

POSTED BY: zhou xiao
Answer
3 months ago

(Cross-posting answer from my answer in StackExchange) I will make a complete example of making predictions with exported nets in MXNet (Python binding). First,

SeedRandom[1234]; 
net = NetChain[{LinearLayer[5], LinearLayer[3]}, "Input" -> 2]; 
net = NetInitialize[net]; 
net[{1, 2}]

{1.27735, -1.21455, -1.02647}

Exporting:

Export["example.json", net, "MXNet"]

creates two files, "example.json" and "example.params". Now lets run this in MXNet. The first thing to note: this is designed to be used by the lowest-level Symbol and NDArray API, NOT higher-level APIs like Gluon or Model. These higher-level APIs are often Python specific: using the lowest level means that this will work on every language binding MXNet supports.

The first step is to import the symbol (stored as a json file) and NDArray:

import mxnet as mx
import numpy as np
sym = mx.symbol.load('example.json') 
nd = mx.nd.load('example.params')

If you tried to bind now via e = sym.bind(mx.cpu(), nd), it will fail, as you have not specified an input NDArray, which will tell MXNet what shape the executor will be. Rather, see what the different inputs are to the symbol:

sym.list_arguments()

['Input', '1.Weights', '1.Biases', '2.Weights', '2.Biases']

In MXNet, weights and biases are normal input arguments. Looking at the keys in our NDArray list:

list(nd)

['2.Weights', '2.Biases', '1.Biases', '1.Weights']

we see it does not contain an array for "Input". Lets add it:

inputND = mx.nd.array(np.array([[1,2]]));
nd["Input"] = inputND

Why did I use [[1,2]] and not [1, 2]? The answer is that MXNet always expects a batch dimension. So this example is using a batch size of 1. Now bind and do a forward pass:

e = sym.bind(mx.cpu(), nd)
out = e.forward()

This returns a list of NDArrays:

[
[[ 1.27735424 -1.21454573 -1.02646875]]
<NDArray 1x3 @cpu(0)>]

Which can be converted to a numpy array via out[0].asnumpy(). Further predictions can be made by directly setting the "Input" NDArray:

inputND[:] = np.array([[3,4]])
a = e.forward()

returning:

[
 [[ 3.56568646 -3.15509319 -3.13344383]]
 <NDArray 1x3 @cpu(0)>]
Answer
3 months ago

Thank you @Sebastian,but still have problem when using RNN.

SeedRandom[1234];
net = NetInitialize@NetChain[{10, Ramp, ReshapeLayer[{5, 2}], 
                    LongShortTermMemoryLayer[5], 3}, "Input" -> 2]
net[{1, 2}]
Export["example.json", net, "MXNet"];

enter image description here

In MXNet,when exauxe this code e = sym.bind(mx.cpu(), nd).It rasise error.

raise ValueError('key %s is missing in %s' % (name, arg_key))

ValueError: key 4.State is missing in args

POSTED BY: zhou xiao
Answer
2 months ago

I thought it would be helpful to extend Sebastian's great solution just a bit for images.

First, make and export the net (using the example from the docs):

resource = ResourceObject["MNIST"];
trainingData = ResourceData[resource, "TrainingData"];
testData = ResourceData[resource, "TestData"];
lenet = NetChain[{
    ConvolutionLayer[20, 5], Ramp, PoolingLayer[2, 2],
    ConvolutionLayer[50, 5], Ramp, PoolingLayer[2, 2],
    FlattenLayer[], 500, Ramp, 10, SoftmaxLayer[]},
   "Output" -> NetDecoder[{"Class", Range[0, 9]}],
   "Input" -> NetEncoder[{"Image", {28, 28}, "Grayscale"}]
   ];
trained = 
 NetTrain[lenet, trainingData, ValidationSet -> testData, 
  MaxTrainingRounds -> 3]
Export["~/mnist.json", trained, "MXNet"]

Then in Python, import the net, run it over the mnist test set, and measure the results:

import mxnet as mx
import numpy as np
sym = mx.symbol.load("/home/ubuntu/mnist.json") 
nd = mx.nd.load("/home/ubuntu/mnist.params")

def eval(img):
    # manual 'NetEncoder' step
    mxnet_img = 1 - (img / 255.) 
    mxnet_img = mxnet_img.reshape(28,28) 

    img_inputND = mx.nd.array([[mxnet_img]])
    nd["Input"] = img_inputND
    e = sym.bind(mx.cpu(), nd)
    out = e.forward()

    # manual 'NetDecoder' step
    return np.argmax(out[0].asnumpy())

# Now test it
from sklearn.datasets import fetch_mldata
mnist = fetch_mldata('MNIST original')

results = []
for img in mnist.data[60000:]:
    results.append(eval(img))

expected = mnist.target[60000:]

from sklearn import metrics
print(metrics.classification_report(expected, results))
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, results)) 

Which outputs

enter image description here

and compared to the ClassifierMeasurements yields the same results as expected:

enter image description here

NetEncoders and NetDecoders are one of the best abstractions of your Neural framework. But since we don't have them in MXNet land, I wanted to highlight how careful we must be to do that part by hand: accounting for image representation, colorspace, mean, image normalization, etc... I really think additional python usage examples showing how to use MXNet models trained inside Mathematica are needed for more sophisticated layers and NetModels. Especially recurrent models involving GRU, LSTMs, and attentional constructs would be great. Mainly because I've built and trained some really cool things, but haven't figured out how use them in any real way, that is, to run them in python.

POSTED BY: Mike Sollami
Answer
3 months ago

Thanks Mike! I absolutely agree that we need some more Python examples. RNNs are annoying due to unrolling, so that needs some special care. Noted in our to-do list.

Answer
3 months ago

wow,you make a cool example.Thank you!!!

I want to ask a question

mxnet_img = 1 - (img / 255.)

why it should be subtract img / 255. from a minuend?

POSTED BY: zhou xiao
Answer
2 months ago

Because in Mathematica greyscale colors are in [0,1] where white is 1 and black is 0, but in this Python case it's from 0 to 255 and reversed.

POSTED BY: Mike Sollami
Answer
2 months ago

Thank you very much.I think this is an important step using MMA NN model in pratice.

POSTED BY: zhou xiao
Answer
2 months ago

Group Abstract Group Abstract