Prediction part of python CNN MXNet code?


#1

I’m try to learn MXNet and Python. I follow the example:

and I had already trained model, but I can’t find sample of prediction part of python script for the model.

I can load the model but I have error: “Target shape size is different to source” when I try to load sentence for prediction. Could somebody help, please?

Thank you, Alex


#2

This is an older tutorial using the symbol API that comes with a few limitations. For example the batch_size is fixed.

Here is how you can run inference, you need the latest mxnet (pip install mxnet --pre):

There is a dependency on the clean_str function, and the vocabulary object from the tutorial code.

net = mx.gluon.nn.SymbolBlock.imports('cnn-symbol.json', input_names=['data'])
net.params.load('cnn-0049.params', ignore_extra=True)

def predict(net, test_sentence, padding_word="</s>", batch_size=50, sentence_size=56):
    x_test = clean_str(test_sentence).split(" ")
    x_test = x_test + ([padding_word] * (sentence_size - len(x_test)))
    x, y = build_input_data([x_test], [1], vocabulary)
    return net(mx.nd.array(x).repeat(batch_size, axis=0))[0].asnumpy().argmax()

predict(net, "This is terrible")
0

predict(net, "This is amazing")
1

However, if you want to do CNN text classification using MXNet Gluon at the character level, I would also recommend this tutorial I wrote :smile: :


It comes with an example of how to do inference and is not constrained by the batch size.
You can have a look here at an example of how to deploy it as web app:


#3

Thank you so much!

You point me to the right direction. I found the example: https://github.com/gaussic/text-classification

Is it possible to get prediction score in range -1…1 where:
-1 is for absolutely negative review
1 is for absolutely positive review

and any other score is real number between -1 and 1 ?

For example neutral review prediction result: -0.2 … 0.2, mostly positive 0.7…1, mostly negative -1…-0.7 etc.


#4

@AlexCO99 if you look at the example that you are pointing to, the output is the linear output of a dense layer. Which means it isn’t bound between [0, 1] for example, so you need to do a softmax output for example, and the loss used for training is the SoftmaxCrossEntropy.

What I would suggest is to use something like that:

output = model(text)
score = ((output.softmax()[0]-0.5)*2).asscalar()

Which effectively take the score for the positive label, and scale it between [-1,1].

pos: 0 -> -1, pos 1 -> 1, pos 0.5 -> 0


#5

I changed source code from:
output = model(text)
pred = nd.argmax(output, axis=1).asscalar()

to:
output = model(text)
pred = ((output.softmax()[0]-0.5)*2).asscalar()

Now I get an error:

File “C:/Images/mxnet/text-classification-full2.py”, line 413, in predict
score = ((output.softmax()[0]-0.5)*2).asscalar()
File “C:\ProgramData\Anaconda2\lib\site-packages\mxnet\ndarray\ndarray.py”, line 1893, in asscalar
raise ValueError(“The current array is not a scalar”)
ValueError: The current array is not a scalar


#6

It depends on the shape of your input
You can try:

score = ((output.softmax()-0.5)*2)[:, 0].asnumpy()

Then inspect score and index it so that you get the first element of each row. [:, 0] should work, but try a bit until you get what you want.

edit: I tested and this works, gives you an array of scores for each element in your batch. Typically in the example provided in the script, batch-size is 1 at prediction.


#7

Thank you! It’s working as I want.

Is it possible to add to the model neutral labeled reviews?

I tried to add third file but I got error something like “different matrix dimension” …


#8

You’ll need to modify the mr_loader.py file.
Specifically these lines:

        pos_examples = [clean_str(s.strip()) for s in open_file(pos_file)]
        neg_examples = [clean_str(s.strip()) for s in open_file(neg_file)]
        x_data = pos_examples + neg_examples
        y_data = [0.] * len(pos_examples) + [1.] * len(neg_examples)  # 0 for pos and 1 for neg

To add an extra class value: [2.] for example

Also you need to set:

    num_classes = 2  # number of classes

to 3 to have 3 hidden units in your last layer.