Let’s say you’re a data scientist, and you’ve been asked to solve a problem. Of course, what you really want is to build an interactive tool, so your colleagues can solve the problem themselves!
In this tutorial, I'll show you how to take a machine-learning model in a Jupyter notebook, and turn it into a web application using the Anvil Uplink.
Here's what we'll do:
- Set up a Jupyter notebook
- Connect it to an Anvil app
- Make a user interface
We'll start with a pre-existing Jupyter Notebook containing a classification model that distinguishes between cats and dogs. You give it an image and it scores it as ‘cat’ or ‘dog’.
(Thanks to Uysim Ty for sharing it on Kaggle.)
We'll use the Anvil Uplink to connect a Jupyter Notebook to Anvil. It’s a library you can
pip install on your computer or wherever your Notebook is running.
It allows you to:
- call functions in your Jupyter Notebook from your Anvil app
- call functions in your Anvil app from your Juypter Notebook - store data in your Anvil app from your Jupyter Notebook
- use the Anvil server library inside your Jupyter Notebook
It works for any Python process - this happens to be a Jupyter Notebook, but it could be an ordinary Python script, a Flask app, even the Python REPL!
To connect our notebook, we'll first need to enable the Uplink in the Anvil IDE.
This gives us a key that we can then use in our code.
We then need to
pip install the Uplink library on the machine the Jupyter Notebook is running on:
pip install anvil-uplink
By adding the following lines to our Jupyter notebook, we can connect it to our Anvil app:
Now we can do anything in our Jupyter Notebook that we can do in an Anvil Server Module - call Anvil server functions, store data in Data Tables, and define server functions to be called from other parts of the app.
We'll load an image into the Jupyter Notebook by making an
anvil.server.callable function in the Jupyter Notebook. It will classify the input image as either a cat or a dog.
with anvil.media.TempFile(file) as filename:
img = load_img(filename)
We’re passing the image in as an Anvil Media object, which we then write to a temporary file.
The load_img function loads the file into Pillow, a Python imaging library.
Then we can do a bit of post-processing of the image to get it into a format that the model likes:
# Inside the classify_image function
img = img.resize((128, 128), resample=PIL.Image.BICUBIC)
arr = img_to_array(img)
arr = np.expand_dims(arr, axis=0)
arr /= 255
Then we can just pass it into our model and return the result:
# Inside the classify_image function
score = model.predict(arr)
return ('dog' if score < 0.5 else 'cat', float(score))
Now we need to write some Python code that runs in the browser so the app responds when an image is loaded in.
We can define an event handler that triggers when the FileLoader gets a new file:
def file_loader_1_change(self, file, **event_args):
"""This method is called when a new file is loaded into this FileLoader."""
result, score = anvil.server.call('classify_image', file)
self.result_lbl.text = "%s (%0.2f)" % (result, score)
self.image_1.source = file
The first line calls the
classify_image function in the Jupyter Notebook, passing in the image file.
Then we display the result (cat or dog) and the score (0 to 1; completely dog or completely cat).
We also put the image file into the Image component so that the user can see their cat or dog (or other cat-or-dog-like image) and decide if they agree with the result.
Your app is already published at a private URL, but we can give it a public URL. You can check out this finished app at https://cat-or-dog.anvil.app.
Check out the whole tutorial: