Streamlit Guide: How to build & serve machine learning applications

Ultimately, the output of machine learning work is geared towards end-users who may not know the intricacies involved in its generation. Towards that end, an interface is needed to help users interact with the ML product in a way that helps solve their problems. Traditionally, this would require experience in web development to come up […]
Oct 13th 2021
read

Share this post

Oct 13th 2021
read

Share this post

Streamlit Guide: How to build & serve machine learning applications

Eric Gitonga

| Data | Watercolour | Photography |

Ultimately, the output of machine learning work is geared towards end-users who may not know the intricacies involved in its generation. Towards that end, an interface is needed to help users interact with the ML product in a way that helps solve their problems. Traditionally, this would require experience in web development to come up with a site that users can interact with.

In this article, we’ll explore the use of Streamlit in building and serving ML applications.

We’ll also look at Layer and how it operates in generating entities declaratively from Datasources, Featuresets, and Model ML descriptors.

Finally, we shall deploy the Layer generated model via a Streamlit application that will provide end-users an interface through which they can interact with the model.

What is Streamlit?

Streamlit is an open-source Python library that enables data scientists to create web apps quickly. Users can interact with these apps, seeking information that leads to insight. Moreover, you can make these apps in just a few lines of code.

How to install Streamlit

Streamlit requires Python 3.6 or newer to work. Installation is done by running:

$ pip install streamlit

How to run Streamlit applications

For the first run of Streamlit, run the hello world example:

$ streamlit hello

This launches a Streamlit app with many demos you can interact with to see some of what it has to offer.

word image 8

Running apps you develop is done by:

$ streamlit run app.py

This will have the app.py executed on your local machine, launching the app in your browser from the local network.

To use Streamlit in your application, import it as st.

import streamlit as st

Streamlit widgets

Streamlit has widgets that make it easy to build up the app. So next, let’s explore the widgets available.

Displaying text in Streamlit

We shall now explore the text methods in Streamlit.

The first to be called is usually `st.title`, which defines the title of the app:

st.title("Main Title of App")

For headings and sub-headings, use these two:

st.header("Section Heading")

st.subheader("Section Sub-Heading")

For general text, use:

st.text("Regular text in body")

If you need to write something in markdown, use the following:

st.markdown("`A code block on Markdown`")

To display a block of code, use:

st.code("print("Hello World!"), language="python")

To display mathematical formulas, use:

st.latex(r'''e = \mathop {\lim }\limits_{n \to \infty } \left( {1 + \frac{1}{n}} \right)^n e^{iπ} + 1 = 0''')

The method `st.write` is versatile and is used to display various kinds of elements. The output it gives is determined by the element it is used to display.

st.write("Displays various elements depending on type")

These are displayed in the following image.

word image 145

Displaying data in Streamlit

The methods used to display raw data are illustrated in the following code block.

import pandas as pd

import numpy as np
import streamlit as st
df = pd.DataFrame({
"Item" : ["Bag", "Book", "Pencil", "Pen"],
"Quantity" : [1, 4, 3, 2]
})

st.dataframe(df)
st.table(df)
result = df.to_json(orient="columns")
st.json(result)

word image 146

Displaying charts in Streamlit

Streamlit has built-in charts, as shown below.

arr_a, arr_b = np.random.randn(25), np.random.rand(25)

df = pd.DataFrame({

"A" : arr_a,

"B" : arr_b})

st.line_chart(df)

word image 147

st.area_chart(df)

word image 148

st.bar_chart(df)

word image 149

Streamlit also has integration to the following visualization libraries.

Matplotlib

Define a figure, then pass it to `st.pyplot`.

arr_hist = np.random.randn(1000)

fig, ax = plt.subplots()

ax.hist(arr_hist, edgecolor="k")st.pyplot(fig)

word image 150

Seaborn

Define a figure, then pass it to `st.pyplot()`.

import seaborn as sns fig, ax = plt.subplots()

ax = sns.scatterplot(x="A", y="B", data=df, hue="A", size="B")

st.pyplot(fig)

word image 151

Altair

Define a chart, then pass it to `st.altair_chart`.

import altair as alt

alt_chart = alt.Chart(df).mark_circle().encode(x="A", y="B", size = "B")
st.altair_chart(alt_chart, use_container_width=True)

word image 152

Vega-Lite

Pass the chart parameters to `st.vega_lite_chart`.

st.vega_lite_chart(df, {
"mark": {"type": "circle"},
"encoding": {
"x": {"field": "A", "type": "quantitative"},
"y": {"field": "B", "type": "quantitative"},
"size": {"field": "B", "type": "quantitative"}
},
}, use_container_width = True)

word image 153

Plotly

Define a figure, then pass it to `st.plotly_chart`.

import plotly.express as px
fig = px.bar(x = ["A","B","C"], y = [21,32,13])
st.plotly_chart(fig, use_container_width=True)

word image 154

Bokeh

Define a chart, then pass it to `st.bokeh_chart`.

from bokeh.plotting import figure
x = [0,1,2,3,4,5,6,7,8,9]
y = [-0.6,0.2,-0.3,-0.5,0.8,0.2,-0.9,-0.7,0.4,-0.4]
p = figure(x_axis_label="x", y_axis_label="y")
p.line(x,y)
st.bokeh_chart(p, use_container_width=True)

word image 155

Pydeck

Define the map, then pass it to `st.pydeck_chart`.

import pydeck as pdk
p_map = pdk.Deck(
...
)
st.pydeck_chart(p_map)

word image 156

Graphviz

Define the graph, then pass it to `st.graphviz_chart`.

from graphviz import Digraph
graph = Digraph("G")
graph.edge("A", "D")
graph.edge("B", "C")
graph.edge("B", "D")
graph.edge("D", "C")
graph.edge("C", "A")
st.graphviz_chart(graph)

word image 157

Maps

You can visualize maps using `st.map`. It is a wrapper around `st.pydeck_chart` that creates charts on a map. Pass in the data as a DataFrame of latitudes and longitudes.

map_data = df[["lat", "lon"]]

st.map(map_data)

A Mapbox access token is required and is free to obtain. Set the token variable in the ` ~/.streamlit/config.toml` file as:

[mapbox]

token = "YOUR_MAPBOX_TOKEN"

Displaying media in Streamlit

You can use the image, audio, and video widgets to add media to your Streamlit app.

from PIL import Image

icon = Image.open("icon.png")

image = Image.open("logo.png")

st.image(image)

word image 158

video_file = open("video.mp4", "rb")
video_bytes = video_file.read()
st.video(video_bytes)
word image 159
audio_file = open("video.wav", "rb")
audio_bytes = audio_file.read()
st.audio(audio_bytes)
word image 160

Displaying code in Streamlit

Should you need to display code and its output in your app, you can use the `st.echo` method.

with st.echo():

df = pd.DataFrame({

"Item" : ["Bag", "Book", "Pencil", "Pen"],

"Quantity" : [1, 4, 3, 2]

})

result = df.to_json(orient="columns")

st.json(result)
word image 161

Displaying progress and status in Streamlit

Feedback is good to have in any application. For example, when a process is running, users appreciate it when some form of notification is availed to them. Streamlit has several widgets that help with providing feedback.

Use `st.progress` to display a bar getting filled. You can also use:

  • `st.spinner` to display a message of ongoing execution and
  • `st.success` to display a message of completion of execution.

Another widget that could be used to indicate completion of execution is `st.balloons`.

import time
bar = st.progress(0)
with st.spinner('Execution in process...'):
for status in range(100):
time.sleep(0.05)
bar.progress(status + 1)
st.success('Execution done!')
st.balloons()

word image 9

To give more information to users of your app, you can include the following widgets.

st.info("Purely informational")
st.warning("Potential issues users need to be made aware of")
st.error("Errors resulting from use of app")
e = NameError("Display an exception of type NameError")
st.exception(e)

word image 164

Helper widgets in Streamlit

The next widgets assist in various ways. The first, `st.empty` that allows you to have placeholders in your app. This enables you to overwrite certain widget outputs or have multiple widget outputs governed by one placeholder.

with st.empty():
for seconds in range(5):
st.write(f"⏳ {seconds} seconds have passed")
time.sleep(1)
st.write("✔️ 5 seconds over!")placeholder = st.empty()
# Replace the placeholder with some text:
placeholder.text("Hello")
time.sleep(2)
# Replace the text with a chart:
placeholder.line_chart({"data": [1, 5, 2, 6]})
time.sleep(2)
# Replace the chart with several elements:
with placeholder.beta_container():
st.write("This is one element")
time.sleep(2)
st.write("This is another")
time.sleep(2)
# Clear all those elements:
placeholder.empty()

word image 10

Use `st.help` to find out the details of a function. It could be a built-in function or one you define with the docstring properly in place.

st.help(list)
def upper(x):
"""
Turns the input text to UPPER CASE.
"""
return str.upper(x)
upper("sam")
st.help(upper)

word image 165

Interactive widgets in Streamlit

Interactive widgets enable users of your app to engage with it. This includes making selections, uploading files, or activating processes. The following shows these widgets in action.

st.button activates processes.

if st.button("Click to release balloons"):

st.balloons()
word image 11

`st.checkbox` enables you to toggle things on and off.

df = pd.DataFrame({"Column" : [1,2,3]})
if st.checkbox("Show table"):
st.table(df)

word image 12

`st.radio` or `st.selectbox` is needed when you want the user to select only one item out of several provided.

st.radio("Select your favourite visualization library",
["Matplotlib", "Plotly", "Altair", "PyDeck", "GraphViz"])
st.selectbox("Select your favourite visualization library",
["Matplotlib", "Plotly", "Altair", "PyDeck", "GraphViz"])

word image 13

If the user selects one or more options out of several provided, `st.multiselect` is the widget to use.

st.multiselect("Select one or more visualization libraries you work with",
["Matplotlib", "Plotly", "Altair", "PyDeck", "GraphViz"])

word image 14

`st.slider` lets a user make a numerical/time/date selection of values in a specified range.

st.slider("What is the temperature of the water?",

min_value=0.0, max_value=100.0, value=25.0)

word image 15

If instead of continuous values you need to select from discrete values, `st.select_slider` is the widget to use.

st.select_slider("Select your favourite visualization library",
options = ["Matplotlib", "Plotly", "Altair", "PyDeck", "GraphViz"])

word image 16

`st.text_input` allows free form text input. This is limited to just one line of text. You can specify the maximum number of characters allowed. Pressing Enter applies the entry.

st.write(st.text_input("What is your name?", max_char=50))

word image 17

`st.text_area` allows the entry of multiple lines of free-form text. You can specify the maximum number of characters allowed. Pressing Ctrl+Enter applies the entry.

st.write(st.text_area("Please provide feedback on the usefulness of this tutorial", max_chars=1000))

word image 18

`st.number_input` lets you input free-form numerical values.

st.write(st.number_input("What is your age?", value=0, min_value=0, max_value=100))

word image 19

To select a date, `st.date_input` provides a date picker.

st.date_input("When were you born?")

word image 20

A similar function for time is available with `st.time_input`.

st.time_input("What is the time now?")

word image 21

`st.color_picker` lets you select a color from a picker.

st.color_picker("Pick your favourite colour")

word image 22

`st.file_uploader` enables users to upload files to your app. You can specify the types of files they can upload using the type option.

st.file_uploader("Please upload an image", type=["jpg", "png", "svg"])

word image 166

Mutate data in Streamlit

There are times you have data already collected and ready to process. But after deploying your app, you come across more data pertinent to your app, and you realize this needs to be included as well. Streamlit provides a way of adding new data to existing data, both for DataFrames and charts. This is possible by concatenating the old and new datasets.

df1 = pd.DataFrame(np.random.randn(3, 2),

columns=('col %d' % i for i in range(2)))
my_table = st.table(df1)

my_table
df2 = pd.DataFrame(np.random.randn(2, 2),

columns=('col %d' % i for i in range(2)))
st.table(df2)

my_table.add_rows(df2)

word image 167

You can also add more data to a plot from a second source.

my_chart = st.line_chart(df1)

my_chart.add_rows(df2)
word image 168

Caching in Streamlit

To help improve application performance, Streamlit can cache the data fetched or the results from executing a function. So long as the function name, function code, and input parameters do not change, Streamlit will fetch the results from the cache. If either of those three changes, or when running a function for the first time, then the full duration needed will be used up, and the result stored in the cache.

The code snippet below demonstrates the time difference between when the code is run for the first and second times.

from time import time

url = "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv"

@st.cache
def fetch_data():
df = pd.read_csv(url)
df['lng-r'] = round(df['lng'],2)
df['lat-r'] = round(df['lat'],2)
return df

st.write("This is the first time the code is run")
start = time()
df = fetch_data()
duration = round((time()-start),2)
st.write(df.head())
st.write(duration,"seconds")

st.write("This is the second time the code is run")
start = time()
df = fetch_data()
duration = round((time()-start),2)
st.write(df.head())
st.write(duration,"seconds")

word image 23

Personalizing Streamlit apps

There are several options you can use in Streamlit to personalize your app.

These include:

  • what title your page will have,
  • what icon your page will show (good for those that may want to have their logo as part of the app),
  • how the app is laid out on the page and
  • providing an option to load the sidebar when the page is accessed.

Since these options determine the page’s look, they must be set right at the beginning of your app.

icon = Image.open("images/titanic.png")
st.set_page_config(
page_title="Titanic Prediction",
page_icon=icon,
layout="centered",
initial_sidebar_state="auto",
)

word image 169

Streamlit configurations

There are various settings that Streamlit uses for the proper functioning of your app. Examples of some of these settings are

  • Look and feel of your app (themes)
  • Operation of your app (enabling or disabling cache)
  • How to access your app (port definitions)
  • Integration with external services (access tokens)

To see a full list of all configuration options being used, type:

streamlit config show

There are four options to change from the default configuration to one of your choosing, depending on your needs. These options are:

Global file

Situated in your home directory in the `config.toml` file

~/.streamlit/config.toml for macOS/Linux

%userprofile%/.streamlit/config.toml for Windows

[server]

port = 80

In a per-project config file

Situated in the project’s working directory, where you run Streamlit from.

$CWD/.streamlit/config.toml
[server]

port = 80

Through environment variables

You can use Streamlit environment variables such as:

export STREAMLIT_SERVER_PORT=80

As flags on the command line

This allows you to change various configuration settings on the fly as you run your app.

streamlit run your_script.py --server.port 80

Theming in Streamlit

You can customize the theme of your app. For example, this would enable you to have the application comply with your brand look. You might also need to make your app more accessible to people with color blindness or other visual impairment, making it difficult for them to view an app with the default theme settings.

The following settings are what come in Streamlit by default:

[theme]

primaryColor="#F63366"

backgroundColor="#FFFFFF"

secondaryBackgroundColor="#F0F2F6"

textColor="#262730"

font="sans serif"

Each of these can be changed to suit your requirements. You make these changes by editing the `~/.streamlit/config.toml` file.

[theme]

primaryColor="#0000FF"

backgroundColor="#DDFF00"

secondaryBackgroundColor="#11BB11"

textColor="#331122"

font="monospace"

word image 7

Laying out your Streamlit application

There are several ways you can set up the layout of your application. One way is moving widgets to the sidebar.

st.sidebar.write("These widgets are in the sidebar")
viz_selection = st.sidebar.selectbox("Select your favourite visualization library",
["Matplotlib", "Plotly", "Altair", "PyDeck", "GraphViz"])
temp_selection = st.sidebar.slider('What is the temperature of the water?', 0.0, 100.0, 25.0)
birthdate = st.sidebar.date_input("When were you born?")df = pd.DataFrame({"Column" : [1,2,3]})
st.write("These widgets are in the main window")
if st.checkbox("Show table"):
st.table(df)if st.button("Click to display the output of your selections"):
st.write(viz_selection)
st.write(temp_selection)
st.write(birthdate)

word image 24

The use of `st.form` enables you to bunch various elements together in one container. Each form has a “Submit” set up by `st.form_submit_button` button that a user clicks to activate submission.

with st.form("my_form"):
st.write("Inside the form")
slider_val = st.slider("Form slider selector", 0.0,100.0)
radio_val = st.radio("Form radio selector", [1,2,3])
# Every form must have a submit button.
submitted = st.form_submit_button("Submit")
if submitted:
st.write("slider choice", slider_val, "radio choice", radio_val)
st.write("Outside the form")

word image 170

Streamlit components

Streamlit provides an API that you can use to develop components. These components provide functionality that might not be there in the core Streamlit. For example, the community has developed several components that do various things.

An example is Streamlit Analytics which can track usage of your app once deployed.

import streamlit_analytics

st.title("Looking at Data")

df = pd.DataFrame({

"Item" : ["Bag", "Book", "Pencil", "Pen"],

"Quantity" : [1, 4, 3, 2]

})

with streamlit_analytics.track():

result = df.to_json(orient="columns")

if st.button("Click to show the JSON output"):

st.json(result)

# to view the app with analytics activated, add this to the end of the url: /?analytics=on

word image 171

Authenticating Streamlit apps

Streamlit does not have official support for authentication in the regular version. However, they have a version for teams in beta that will enable controlled access to private repositories and secure connections to private data sources.

For the regular version, several methods to enable authentication are discussed in this Streamlit forum.

Uploading and processing files in Streamlit

Let’s look at a couple of examples of file processing in Streamlit.

Processing an image file

The code below does the following:

  • Upload an image file
  • Convert to NumPy array
  • Make a copy of the array for each of the three color channels Red, Green, and Blue.
  • Extract the information for each of those channels.
  • Combine all arrays (including the original array)
  • Display the resulting image composed of 4 images (one for each of the three channels and the fourth of the original image)
import streamlit as st

import numpy as np

import matplotlib.pyplot as plt

from PIL import Image#Upload the image file to process

image = st.file_uploader("Upload the image file to process", type=["jpg", "png", "svg"])#Wait for file to finish uploading

if image is not None:

img = Image.open(image)#Convert image to array

img = np.array(img)#Make copies of image for each RGB channel

img_R, img_G, img_B = img.copy(), img.copy(), img.copy()#Reduce each channel to the specific colour

img_R[:, :, (1, 2)] = 0

img_G[:, :, (0, 2)] = 0

img_B[:, :, (0, 1)] = 0#Combine all images (including original)

img_rgb = np.concatenate((img_R,img_G,img_B,img), axis=1)#Display all images

fig, ax = plt.subplots()ax.set_axis_off()ax = plt.imshow(img_rgb)st.pyplot(fig)

word image 172

Processing a tabular data file

The code below does the following:

  • Upload a data file
  • Display the first few lines of the DataFrame
  • Generate new columns from existing columns
  • Display the first few lines of the modified DataFrame
  • Generate two plots based on the two new columns
import pandas as pd

import streamlit as st

from datetime import date

import matplotlib.pyplot as plt

import seaborn as sns

#Upload the data file to process

data_file = st.file_uploader("Select the data file to upload", type="csv")

#Wait for file to finish uploading

if data_file is not None:

df = pd.read_csv(data_file)st.markdown("### Dataframe as read in")

st.dataframe(df.head())#Create new columns from existing columns

for i in df.index:

if df.loc[i,"Died"] == "\\N":

df.loc[i,'Age'] = date.today().year - df.loc[i,'Born']

df.loc[i,"Alive"] = "No"

else:

df.loc[i,'Age'] = int(df.loc[i,'Died']) - df.loc[i,'Born']

df.loc[i,"Alive"] = "Yes"

df["Age"] = df["Age"].astype(int)st.markdown("### Dataframe with new columns generated from existing columns")

st.dataframe(df.head())#Set up and display a count plot

plt.figure(figsize=(10,5))

st.markdown("### Counts of Living and Dead Entertainers")

fig, ax = plt.subplots()

ax = sns.countplot(df["Alive"])

st.pyplot(fig)#Set up and display a histogram

plt.figure(figsize=(10,5))

st.markdown("### Distribution of Age of Entertainers")

fig, ax = plt.subplots()

ax = sns.histplot(df["Age"])

st.pyplot(fig)

word image 173word image 174word image 175

Connecting Streamlit to Databases

Streamlit now provides the functionality to connect to a database. This comes in handy when you have an app that needs fresh data every so often. An excellent example of an app with this requirement is one that tracks the stock market. Access to a database of trades made in the stock market will allow users to see the latest information and interact with it knowing they are dealing with up-to-date data.

Streamlit can be connected to the following databases:

These use Streamlit’s secrets management and caching to provide access to data fast and securely.

In a future article, we shall explore in depth Streamlit’s connection to all the databases mentioned in the list above, giving examples of how we can deploy an app to take advantage of these connections.

Layer Applications with Streamlit

Layer is a Declarative MLOps (DM) platform that helps teams develop code-based ML applications. Declarative means you define what you want to accomplish rather than describe how you want to achieve it.

With Layer, you pass in the Dataset, Features, and ML model definitions; then, the platform builds the required entities. This frees up time for designing, developing, and deploying models.

Connecting your data

This definition is done through YAML configuration files. To illustrate the concepts, we’ll walk through the Titanic data set.

Create your first Layer project

To start, set up the environment from which the operations will take place and activate it.

python -m venv env

source env/bin/activate

Let’s start by cloning the Layer examples project.

layer clone https://github.com/layerml/examples

cd titanic

Here is how the project looks like.

.

├── .layer

├── data

│ ├── passenger_features

│ │ ├── dataset.yaml # Definition of `passenger_features`, with each SQL feature definition below.

│ │ ├── ageband.sql

│ │ ├── embarked.sql

│ │ ├── fareband.sql

│ │ ├── is_alone.sql

│ │ ├── sex.sql

│ │ ├── survived.sql

│ │ └── title.sql

│ └── titanic_data

│ └── dataset.yaml # Declares where our source data is

├── models

│ └── survival_model

│ ├── model.yml # Training directives of our model

│ ├── model.py # Definition of our model

│ └── requirements.txt # Environment config file

└── README.md

Defining your datasets

The .layer directory has the project.yml main configuration file. This file contains the metadata of the project.

# Project configuration file

apiVersion: 1

# Name of your project

name: "Titanic Survival Project"

Data definition is done in the dataset.yaml file found in the data/titanic_data directory. That describes what the data source for this project is. In this instance, the Titanic Dataset is uploaded into the demo database which is listed as the Datasource for this project.

# Titanic Survival Project Example

# In this file, we will integrate a source table from the Layer Demo

# Snowflake database. This source table is the Titanic dataset from

# Kaggle (https://www.kaggle.com/c/titanic/data)

apiVersion: 1

# Unique name of this dataset which will be used in this project to

# refer to this dataset

name: "titanic"

type: source

aterialization:target: layer-public-datasetstable_name: "titanic"

Layer needs the “PassengerID” primary key in all feature definitions. This ensures that Layer can join all the features correctly.

Develop features and model train code

Next up is the data/passenger_features directory with SQL files for each feature used to create the training data. The dataset.yml file in this directory is the descriptor for the `Featureset`.

#In this `yaml` file, we will define the attributes of our

# featureset.

apiVersion: 1

type: featureset

name: "passenger_features"

description: "Passenger features from Titanic Dataset"

features:

- name: ageband

description: "5 different age buckets (0, 16,32,48,64+). Filled missing age rows with avg(age)"

source: ageband.sql

....

- name: survived

description: "Whether the passenger survived or not."

source: survived.sql

materialization:target: layer-public-datasetstable_name: "titanic"

A sample SQL file looks like this:

/* Titanic Survival Project Example `Sex` Feature */

SELECT PassengerId,

CASE

WHEN sex = "female" THEN 1

WHEN sex = "male" THEN 0

END

as Sex

FROM titanic

Finally, there is the models/survival_model directory which has the model.py file that implements the model. The model.yml file in this directory is the descriptor for this ML Model.

A snippet of model.py is shown below:.

from typing import Any

from sklearn.ensemble import RandomForestClassifier

...

from layer import Featureset, Train

def train_model(train: Train, pf: Featureset("passenger_features")) -> Any:

df = pf.to_pandas()

X = df.drop(["PassengerId", "Survived"], axis=1)

y = df["Survived"]

...

acc = accuracy_score(y_test, y_pred)

train.log_metric("accuracy", acc)

return random_forest

# In this `yaml` file, we will define the attributes of our model.

apiVersion: 1

# Name and description of our model

name: "survival_model"

description: "Titanic survival predictor"

training:

name: survival_model_training

description: "Titanic Survival Model Training"

# The source model definition file with a `train_model` method

entrypoint: model.py

# File includes the required python libraries with their correct versions

environment: requirements.txt

Pass your source code for features and models

Now run the following commands to log into the platform and initiate the building of the entities.

layer login

layer start

This will generate the model and data catalogs.

word image 176

Go ahead and deploy the model from the Layer Model Catalog.

word image 177

Click on the clip icon to copy the model URL and use it to make real-time predictions.

curl --header "Content-Type: application/json; format=pandas-records" \

--request POST \

--data '[{"Sex":0, "EmbarkStatus":0, "Title":0, "IsAlone":0, "AgeBand":1, "FareBand":2}]' \

$MODEL_DEPLOYMENT_URL

Run this with various values of the data components. A [0] means the passenger did not survive, and vice versa.

Deploying Streamlit applications

This model requires one to work from the command line and edit the code manually for each prediction. That it returns, a number adds an extra level of user-unfriendliness.

This is where Streamlit comes to the rescue, enabling a user-friendly app to get generated. The application makes it easier to change various feature values for model prediction. It also displays the output in a more meaningful manner.

The app has four functions defined to perform the needed work. The first function has the code to parse the API into a format suitable for the Python script.

from requests.structures import CaseInsensitiveDict

def survival_prediction():

url = "$MODEL_DEPLOYMENT_URL"

headers = CaseInsensitiveDict()

headers["Content-Type"] = "application/json; format=pandas-records"

data = dict_to_string()

resp = requests.post(url, headers=headers, data=data)

return int(list(resp.text)[1])

This function returns the predicted value (0 or 1).

The data is in a string format, so we need to format the values obtained from users into this format. The `dict_to_string()` function performs this task.

Next, the `get_passenger_details()` function takes in the values input by the user through the interactive Streamlit widgets.

Here is sample code for one of the features:

p_sex = st.sidebar.radio('What was the gender of the passenger?', ['Male', 'Female'])

if p_sex == 'Male':

sex = 0

else:

sex = 1

Finally, the `make_prediction()` function initiates the prediction and displays a message of whether a passenger survived or not.

The complete code is available on Github.

The app can now be deployed. There are two options to do this, Heroku and Streamlit Sharing.

Heroku

Three files are needed to deploy an app on Heroku. These are:

  • A `procfile` that Heroku uses to determine what type of application your app is.
  • A `requirements.txt` file that lists the packages and their versions required by your app to function properly.
  • A `setup.sh` file which lists the Streamlit configurations set in place for your app

This site goes into detail on how to accomplish a Heroku deployment.

Streamlit Sharing

Streamlit provides a service where you can deploy your app for free. This is through Streamlit Sharing.

For this, set up a repo of your app on Github. The repo has to be public for this to work. It should contain the code, as well as a requirements.txt file.

word image 178

Next, go to Streamlit Sharing and request an invite to the service, which is free. It takes about 24 hours for the request to be approved. Once the invite has been obtained, navigate to your dashboard and deploy the app.

Click on the New app button to start the process.

word image 179

On the window that comes up, put in the path to your repo and the name of the main Streamlit Python script.

word image 180

If you have certain values you need to pass to your app that should not be publicly viewable, you should use the Secrets window in the Advanced settings to fill these in. These shall be encrypted and passed to your app.

word image 181

Click on Save, then on Deploy in the previous window for Streamlit to start processing the request. Once done, it will display your app, which is now ready for public view.

word image 182

It is now publicly available for use.

You can view the app from this walk-through here.

word image 25

Conclusion

This article explored Streamlit and its use in generating apps that end users can interact with to consume ML models. We explored the basics of Streamlit (installation, widgets, and personalization). We also explored a couple of use cases (uploading and processing image and data files).

Layer was also briefly introduced. We looked at what it is and how it operates in generating entities declaratively from Data

sources, Featuresets, and Model ML descriptors.

Finally, we deployed the Layer generated model via a Streamlit app, providing an interface for end-users to interact.

Oct 13th 2021
read

Share this post

Try Layer for free

Get started with Layers Beta

Start Free