<jupyter_start><jupyter_text>Inference with your modelThis is the third and final tutorial of our [beginner tutorial series](https://github.com/awslabs/djl/tree/master/jupyter/tutorial) that will take you through creating, training, and running inference on a neural network. In this tutorial, you will learn how to execute your image classification model for a production system.In the [previous tutorial](02_train_your_first_model.ipynb), you successfully trained your model. Now, we will learn how to implement a `Translator` to convert between POJO and `NDArray` as well as a `Predictor` to run inference. PreparationThis tutorial requires the installation of the Java Jupyter Kernel. To install the kernel, see the [Jupyter README](https://github.com/awslabs/djl/blob/master/jupyter/README.md).<jupyter_code>// Add the snapshot repository to get the DJL snapshot artifacts
// %mavenRepo snapshots https://oss.sonatype.org/content/repositories/snapshots/

// Add the maven dependencies
%maven ai.djl:api:0.6.0
%maven ai.djl:model-zoo:0.6.0
%maven ai.djl.mxnet:mxnet-engine:0.6.0
%maven ai.djl.mxnet:mxnet-model-zoo:0.6.0
%maven org.slf4j:slf4j-api:1.7.26
%maven org.slf4j:slf4j-simple:1.7.26
%maven net.java.dev.jna:jna:5.3.0
    
// See https://github.com/awslabs/djl/blob/master/mxnet/mxnet-engine/README.md
// for more MXNet library selection options
%maven ai.djl.mxnet:mxnet-native-auto:1.7.0-b
import java.awt.image.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;
import ai.djl.*;
import ai.djl.basicmodelzoo.basic.*;
import ai.djl.ndarray.*;
import ai.djl.modality.*;
import ai.djl.modality.cv.*;
import ai.djl.modality.cv.util.NDImageUtils;
import ai.djl.translate.*;<jupyter_output><empty_output><jupyter_text>Step 1: Load your handwritten digit imageWe will start by loading the image that we want to run our model to classify.<jupyter_code>var img = ImageFactory.getInstance().fromUrl("https://djl-ai.s3.amazonaws.com/resources/images/0.png");
img.getWrappedImage();<jupyter_output><empty_output><jupyter_text>Step 2: Load your modelNext, we need to load the model to run inference with. This model should have been saved to the `build/mlp` directory when running the [previous tutorial](02_train_your_first_model.ipynb).TODO: Mention model zoo? List models in model zoo?TODO: Key Concept ZooModelTODO: Link to Model javadoc<jupyter_code>Path modelDir = Paths.get("build/mlp");
Model model = Model.newInstance("mlp");
model.setBlock(new Mlp(28 * 28, 10, new int[] {128, 64}));
model.load(modelDir);<jupyter_output><empty_output><jupyter_text>Step 3: Create a `Translator`The [`Translator`](https://javadoc.io/static/ai.djl/api/0.6.0/index.html?ai/djl/translate/Translator.html) is used to encapsulate the pre-processing and post-processing functionality of your application. The input to the processInput and processOutput should be single data items, not batches.<jupyter_code>Translator<Image, Classifications> translator = new Translator<Image, Classifications>() {

    @Override
    public NDList processInput(TranslatorContext ctx, Image input) {
        // Convert Image to NDArray
        NDArray array = input.toNDArray(ctx.getNDManager(), Image.Flag.GRAYSCALE);
        return new NDList(NDImageUtils.toTensor(array));
    }

    @Override
    public Classifications processOutput(TranslatorContext ctx, NDList list) {
        NDArray probabilities = list.singletonOrThrow().softmax(0);
        List<String> indices = IntStream.range(0, 10).mapToObj(String::valueOf).collect(Collectors.toList());
        return new Classifications(indices, probabilities);
    }
    
    @Override
    public Batchifier getBatchifier() {
        return Batchifier.STACK;
    }
};<jupyter_output><empty_output><jupyter_text>Step 4: Create PredictorUsing the translator, we will create a new [`Predictor`](https://javadoc.io/static/ai.djl/api/0.6.0/index.html?ai/djl/inference/Predictor.html). The predictor is the main class to orchestrate the inference process. During inference, a trained model is used to predict values, often for production use cases. The predictor is NOT thread-safe, so if you want to do prediction in parallel, you should create a predictor object(with the same model) for each thread.<jupyter_code>var predictor = model.newPredictor(translator);<jupyter_output><empty_output><jupyter_text>Step 5: Run inferenceWith our predictor, we can simply call the predict method to run inference. Afterwards, the same predictor should be used for further inference calls.<jupyter_code>var classifications = predictor.predict(img);

classifications<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10702702702702703, 'fraction_numerical': 0.013405405405405406, 'mean_word_length': 5.151595744680851, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '7447', 'license': 'Apache-2.0', 'n_tokens_mistral': 1535, 'n_tokens_neox': 1434, 'n_words': 413, 'path': 'jupyter/tutorial/03_image_classification_with_your_model.ipynb', 'repo_name': 'michaellavelle/djl', 'size': '4625'}