A Guide to Streamlit — Frontend for Data Science Made Simpler | by Yash Prakash | Towards Data Science

Multiple times in our data science job or even in a cool side project that we dedicate our time and energy to, we face the dilemma of how to showcase our work properly. Should we build a new webpage ourselves, make sure our model works as an API and finally, put it all together as a package and expect someone else to run and interact with it the same way we did?
It’s hard to do the frontend work.
Thus, for those of us backend people who never bothered to toil and learn the nuances of HTML, CSS and Javascript, Streamlit is here to save us.
In brief, this is the library that allows us to build frontend for our machine learning and data science apps by writing all the code in Python. Beautiful UIs can easily be designed through numerous components from the library. This is the full documentation from their website.
This means you can have — buttons, pretty text displays, scrollable boxes, drop-down lists, file upload functionalities — all inside of your python project with minimal effort.
Let’s get started with the Rock Paper Scissors project that we’ve been working on from this article:
towardsdatascience.com
If you haven’t read that article yet, this is the work we did there in brief — The Rock Paper scissors dataset is the collection of images from three classes of images, you guessed it — Rock, Paper and Scissor hand gestures. We perform image classification on the dataset using some quick transfer learning with the help of the Fastai deep learning library.
We imported the dataset, trained the model and saved it in this article.
Now comes the part where we design an interactive interface around it.
Just in case you were wondering about the whole codebase: it is all here. Feel free to follow along as you read this tutorial. :)
github.com
We will be adding the following two methods of predicting an image to our app. Either we can:
choose from a list of test images to predict, or
upload a new test image to predict
This sounds pretty simple right? Yes, that it is! But with this, you will gain the knowledge of using a lot of different streamlit components in your further projects as well.
We should now go ahead and make sure we install the library.
Do this from the terminal while inside your virtual environment:
pipenv shell #activate your virtual envpipenv install streamlit #install streamlit
Now go ahead and open up your project directory in your favourite code editor.
For this app, we will be building a full containerised (dockerized) shareable application in the future, so make sure you build this project structure first:
The entirety of the app will be living inside the app directory.
Our project needs to sit in the module directory.
Our trained model (pickled) will be housed in models directory.
And finally, we will have our start.py, the main file to run the app outside the module but inside the app directory.
The other two files are just pipenv files made when using the virtual environment.
Now that we have gotten that out of the way, let’s write some code!
The whole app consists of just some helper functions and one main function to run them all.
Let’s see what’s inside load_model.py
Define the trained model path and import fastai:
from fastai.vision.all import *SAVED_MODEL_PATH = './models/trained_model.pkl'
Finally, define the classifier function:
def _get_model():    model = load_learner(SAVED_MODEL_PATH)    return modeldef perform_prediction(image_path):    model = _get_model()    pred = model.predict(PILImage.create(image_path))    return pred[0]
We also define another function to open and display an image via the PIL libary:
def get_opened_image(image):    return Image.open(image)
Now, we can move on to the start.py.
Let’s connect our helper function in the load_model.py module with a function in this file:
def classify(image_file):    pred = perform_prediction(image_file)    return pred
Let’s now get on with the streamlit app.
Import the libary:
import streamlit as st
First, we define the title of the app like so:
st.sidebar.title("RPS Image Classifier")
Next, we make sure we have a main function. Let’s create a sidebar — to house all the interactive components in the app.
Now, we define the functionality to upload an image.
image_file = st.sidebar.file_uploader('Upload an image', type = 'png')
Finally, we make a button that helps us load our image into the app and display it:
if image_file and st.sidebar.button('Load'):        image = get_opened_image(image_file)        with st.beta_expander('Selected Image', expanded = True):            st.image(image, use_column_width = True)
Now, we include the option of selecting an existing image file as well:
image_file_chosen = st.sidebar.selectbox('Select an existing image:', get_list_of_images())
Here, get_list_of_images is a new function we define in the load_model.py:
def get_list_of_images():file_list = os.listdir(PATH_TO_TEST_IMAGES)return [str(filename) for filename in file_list if str(filename).endswith('.png')]
Pheww! This should now be enough for our UI.
This is how your app should look right now:
These are the components we’ve built:
st.title — the component to write the title. Other text components for various use cases are: st.text, st.write, st.markdown. We’ll be using all of that further in here too.
st.sidebar — to build the sidebar you see in the above image.
st.sidebar.file_uploader — to make a widget of file uploader available in the sidebar. You can also use it simply without the sidebar, like this: st.file_uploader. Then, it will appear in the main area which looks blank in the above image.
st.image — The widget to simply show the image loaded into the app.
st.selectbox — to make a drop-down list of items (images here) to select instead of uploading a file yourself.
This is the part we’ve been waiting for, isn’t it? Well, thanks to fastai, this step is very simple too.
def perform_prediction(image_path):    model = _get_model()    pred = model.predict(PILImage.create(image_path))    return pred[0]def _get_model():    model = load_learner(SAVED_MODEL_PATH)    return model
These two functions help us predict on any given image. We load the learner module from fastai, and then we return back the result. In this case, it is the first item in the pred variable. Hence, pred[0].
The only thing we need to do now is to link this function inside our start.py.
prediction = classify(os.path.join(PATH_TO_TEST_IMAGES, image_file))
And that’s it!
Let’s display the results as well!
st.subheader('Prediction')st.markdown(f'The predicted label is: **{prediction}**')
The app is action now looks like so:
If you’ve followed along with me thus far, take a moment to congratulate yourself on learning the fundamentals of a cool, useful library! The ease of building a frontend for a data science project had never been so great and you should definitely try to apply more of this in your future projects. I surely will!
In the next article, I will be containerising this app with the help of Docker. So do stay tuned for that!
Thank you for reading!
Here is the master codebase of all my Data Science articles:
github.com
I also write about Data Science and Software Engineering on Twitter.