STreamlit 如何实现在每次小部件交互后不会重新运行的有状态 ML 应用程序

Posted

技术标签:

【中文标题】STreamlit 如何实现在每次小部件交互后不会重新运行的有状态 ML 应用程序【英文标题】:STreamlit how to implement a stateful ML app that doesnt rerun after every widget interaction 【发布时间】:2021-12-29 02:46:38 【问题描述】:

我想实现一个有状态的机器学习应用程序,它不会在每次与小部件的交互时重新运行。

应用流程: 第 1 步:输入文件路径并单击按钮将数据上传到数据框。 第 2 步:显示示例数据 第 3 步:显示描述性统计信息 第 4 步:根据选择框的选择动态绘制所选特征的直方图。

当我选择除第 4 步绘图的默认选择之外的新变量时,整个脚本会重新运行。 如何保存状态信息,这样当我在第 4 步时,上面的所有内容都不会重新运行,即不应再次调用第 1、2、3 步。只有我在第 4 步中与之交互的内容。 请帮帮我。

import numpy as np
import pandas as pd
import sklearn as sk
import matplotlib.pyplot as plt
import streamlit as st
import pyspark
from pyspark import *
from PIL import Image
from io import StringIO
import st_state_patch

def load_data(ss,uploaded_file):
    df = ss.read.format('csv').option('header','true').load(uploaded_file)
    return df

def sample_data(df,widget):
    df_sample = pd.DataFrame(df.head(5))
    df_sample.columns = df.columns
    widget.dataframe(df_sample)
    
def descriptive_stats(df,widget):
    df_desc = df.summary().toPandas()
    widget.dataframe(df_desc)
    
def hist_plot(df,col,widget):
    df_plot = df.select(col).toPandas().iloc[:,0]
    fig, ax = plt.subplots()
    ax.hist(df_plot,density = False, bins = 50)
    widget.pyplot(fig)

def main():
    sparkapp = pyspark.sql.SparkSession.builder.master('local[4]').appName('No-code Spark Pipeline').getOrCreate()
    df = pd.DataFrame()
    st.title("No-Code ML Spark Pipeline")
    st.subheader('1. Upload file (csv)')
    uploaded_file = st.text_input("Provide local file path")
    upload_button1 = st.button('Upload')
    st.caption('Sample data')
    upload_cont1 = st.empty()
    white_background = Image.open('C:/Users/hp/Desktop/white_600_240.png')
    upload_cont1.image(white_background)
    # Call load data
    if upload_button1:
        df = load_data(sparkapp,uploaded_file)
        sample_data(df, upload_cont1)
    # Call sample data
    
    st.subheader('2. Exploratory Data Analytics')
    st.caption('Descriptive statistics')
    eda_cont1 = st.empty()
    eda_cont1.image(white_background,use_column_width=True)
    # Call descriptive stats
    if upload_button1:
        descriptive_stats(df, eda_cont1)         
    st.caption('Histogram / Frequency plot')
    eda_sel_feat = st.selectbox('Select feature to be displayed', options = df.columns)
    eda_cont2 = st.empty()
    eda_cont2.image(white_background,use_column_width=True)
    # Call hist plot
    if upload_button1:
        hist_plot(df,eda_sel_feat,eda_cont2)


if __name__ == '__main__':
    main()

【问题讨论】:

【参考方案1】:

Streamlit 有一个称为缓存 (@st.cache) 的功能,它通过对数据进行哈希处理,因此计算不会总是针对类似的函数重复但在这种情况下,我们使用的是 PySpark。

由于 spark 依赖于 Java,Streamlit 无法对 PySpark 函数进行哈希处理。

【讨论】:

以上是关于STreamlit 如何实现在每次小部件交互后不会重新运行的有状态 ML 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 python 的 streamlit 包的多选小部件中添加“全选”选项?

如何在状态更改后强制小部件重新创建自己?

当以html格式下载时,IPython交互式小部件不会以图形方式更新

如何在通知中心频繁更新今日小部件?

在颤振/飞镖中与图像下的小部件交互

Streamlit `altair_chart` 图表不是交互式的