# Using your own models¶

We include three examples for you to try: a model trained on the MNIST dataset for both Keras and Tensorflow, and a Keras VGG16 model. We’ve tried to make it as simple as possible, but we do make a few assumptions:

- Your graph has a definitive entry and exit point. Specifically, a placeholder tensor for some kind of input and output operation (typically image arrays and class probabilities, respectively).
- These placeholders are of unspecified length.
- The portion of the computational graph you’re interested in requires no other inputs.

If you built your model with Keras using a Sequential model, you should be more or less good to go. If you used Tensorflow, you’ll need to manually specify the entry and exit points [1].

## Your model data¶

You can specify the data directory with the `MODEL_LOAD_ARGS.data_dir`

setting (see Settings). This directory should contain the Keras or Tensorflow checkpoint files. If multiple checkpoints are found, the latest one will be used (see example Keras model code).

## Utility functions¶

In addition to the graph and weight information of the model itself, you’ll need to define a few functions to help the visualization interact with user input, and interpret raw output from your computational graph. These are arbitrary python functions, and their locations can be specified in the Settings.

We’ll draw from the Keras MNIST example for this guide. All custom models
from the relevant model: either `KerasModel`

or `TensorflowModel`

.

### Preprocessor¶

The preprocessor takes images uploaded to the webapp and converts them into arrays that can be used as inputs to your model. The Flask app will haved converted them to PIL Image objects.

```
import numpy as np
from PIL import Image
from picasso.models.keras import KerasModel
MNIST_DIM = (28, 28)
class KerasMNISTModel(KerasModel):
def preprocess(self, raw_inputs):
image_arrays = []
for target in targets:
im = target.convert('L')
im = im.resize(MNIST_DIM, Image.ANTIALIAS)
arr = np.array(im)
image_arrays.append(arr)
all_targets = np.array(image_arrays)
return all_targets.reshape(len(all_targets),
MNIST_DIM[0],
MNIST_DIM[1], 1).astype('float32') / 255
```

Specifically, we have to convert an arbitrary input color image to a float array of the input size specified with `MNIST_DIM`

.

### Class Decoder¶

Class probabilities are usually returned in an array. For any visualization where we use classification, it’s much nicer to have the class labels available. This method simply attaches the labels to computed probabilities.

```
class KerasMNISTModel(KerasModel):
...
def decode_prob(self, class_probabilities):
results = []
for row in class_probabilities:
entries = []
for i, prob in enumerate(row):
entries.append({'index': i,
'name': str(i),
'prob': prob})
entries = sorted(entries,
key=itemgetter('prob'),
reverse=True)[:self.top_probs]
for entry in entries:
entry['prob'] = '{:.3f}'.format(entry['prob'])
results.append(entries)
return results
```

`results`

is then a list of dicts in the format `[{'index': class_index, 'name': class_name, 'prob': class_probability}, ...]`

. In the case of the MNIST dataset, the index is the same as the class name (digits 0-9).

[1] | We hope to remove these limitations in the future to accomodate a wider variety of possible graph topologies while still maintaining separation between the visualization and model implementation as much as possible. |