출처 : 변성윤님 블로그.
출처 : 부스트캠프 AI Tech.
1. Streamlit
1.1 웹 서비스를 만드는 과정
- 데이터 분석가(또는 데이터 사이언티스트 등)가 웹 서비스를 작업하는 Flow
- 데이터 Product로 중요하게 된다면 프론트엔드/PM 조직과 협업
- 단, 프론트엔드/PM 조직은 다른 웹도 만들고 있어서 빠르게 이터레이션이 어려움
- 단, 프론트엔드/PM 조직은 다른 웹도 만들고 있어서 빠르게 이터레이션이 어려움
- 다른 조직의 도움 없이 빠르게 웹 서비스를 만드는 방법이 무엇일까? 이런 문제를 해결하기 위해 등장한 것이 Streamlit
- 주의할 점 : 툴이나 라이브러리에 집착하지 말고, 점진적으로 문제를 해결하는 과정에 집중하기!
- 현재 사용하는 도구의 장단점은 어떤 것이고 새로운 대안이 있을지 항상 생각해보기!
- 강의에선 Voila - Streamlit 순서로 했지만, 추후엔 Streamlit부터 시작해도 괜찮음 모든 것은 프로젝트의 요구 조건에 따라 다름!
1.2 Streamlit의 대안
1) R의 Shiny
2) Flask, Fast API : 백엔드를 직접 구성 + 프론트엔드 작업도 진행
3) Dash : 제일 기능이 풍부한 Python 대시보드 라이브러리
4) Voila : Jupyter Notebook을 바로 시각화 가능
1.3 Streamlit Component
1.3.1 Streamlit 소개
- https://streamlit.io/
- https://docs.streamlit.io/
- Streamlit Gallery : https://streamlit.io/gallery
1.3.2 Streamlit 장점
- 파이썬 스크립트 코드를 조금만 수정하면 웹을 띄울 수 있음
- 백엔드 개발이나 HTTP 요청을 구현하지 않아도 됨
- 다양한 Component 제공해 대시보드 UI 구성할 수 있음
- Streamlit Cloud도 존재해서 쉽게 배포할 수 있음(단, Community Plan은 Public Repo만 가능)
- 화면 녹화 기능(Record) 존재
1.3.3 Streamlit 설치 & 실행
$ pip3 install streamlit
$ streamlit run streamlit-basic.py
$ streamlit run streamlit-basic.py --server.port 30003
1.3.4 Streamlit Component basics
# Title, Header, Write
import treamlit as st
import pandas as pd
import numpy as np
import time
st.title("Title")
st.header("Header")
st.subheader("subheader")
st.write("Write Something")
# streamlit button
if st.button("버튼이 클랙되면"):
st.write("클리 후 보이는 메세지!")
if st.button("버튼이 클랙되면2"):
st.write("클리 후 보이는 메세지!2")
# streamlit checkbox
checkbox_btn = st.checkbox("체크박스 버튼")
if checkbox_btn:
st.write("체크박스 버튼 클릭!")
checkbox_btn2 = st.checkbox("체크박스 버튼", value=True)
if checkbox_btn2:
st.write("button2")
# streamlit pandas dataframe, markdown
# st.write : 보여줄 수 있는 것이면 어떤 것이든 보여줌
# st.dataframe : Interactive한 Dataframe, 컬럼 클릭이 가능하고 정렬도 가능
# st.table : Static한 Dataframe
df = pd.DataFrame({'first column' : [1,2,3,4,], 'second column' : [10,20,30,40]})
st.markdown('======')
st.write(df)
st.dataframe(df)
st.table(df)
# Dataframe의 Max 값을 색칠할 수 있음
st.dataframe(df.style.highlight_max(axis=0))
st.table(df.style.highlight_max(axis=0))
# streamlit metric, json
st.metric("My metric", 42,2)
st.json(df.to_json())
# Streamlit Line Chart
chart_data = pd.DataFrame(np.random.randn(20,3), columns = ['a','b','c'])
st.line_chart(chart_data)
# Streamlit map Chart
map_data = pd.DataFrame(np.random.randn(1000,2) / [50,50] , columns = ['lat','lon'])
st.map(map_data)
# Streamlit Chart
# 그 외에도 Plotly Chart 등을 쉽게 사용할 수 있음
# Chart 문서 - https://docs.streamlit.io/library/api-reference/charts
# Streamlit Radio Button, Select Box
selected_item = st.radio("Radio Part", ('a','b','c'))
if selected_item == 'a':
st.write('a')
elif selected_item == 'b':
st.write('b')
elif selected_item == 'c':
st.write('c!')
option = st.selectbox('please select in select box!', ('kyle','seongyun','zzsza'))
st.write('you selected: ', option)
# Streamlit Multi Select Box
multi_select = st.multiselect('select multi!', ['a','b','c','d'])
st.write('you selected: ', multi_select)
# Streamlit Slider
value = st.slider('select a range of values ', min = 0.0, max = 100.0, default = (25.0, 75.0))
st.write('values : ', values)
# Streamlit Input Box, Caption, Code, Latex
text_input = st.text_input('input text')
st.write(text_input)
password_input = st.text_input("암호를 입력해주세요 : ", type = "password")
number_input = st.number_input("숫자를 입력해주세요")
st.write(number_input)
st.date_input("날짜를 입력하세요")
st.time_input("시간을 입력하세요")
st.caption("This is caption")
st.code("a = 123")
st.latex("\int a x^2 \,dx")
# Sidebar에는 파라미터를 지정하거나, 암호를 설정할 수 있음
st.sidebar.button("hi")
# 기존 method 앞에 sidebar를 붙이면 sidebar에 보이게 됨
# Streamlit Layout - Columns
col1, col2, col3, col4 = st.columns(4)
col1.write("this is col1")
col2.write("this is col2")
col3.write("this is col3")
col4.write("this is col4!")
# Streamlit Layout - Expander
with st.expander("클릭하면 열려요!"):
st.write("content!")
# Streamlit Spinner
# 연산이 진행되는 도중 메세지를 보여주고 싶은 경우
with st.spinner("Please wait.."):
time.sleep(5)
# Streamlit Ballons
# 직접 실행
st.ballons()
# Streamlit Status Box
st.success("Success")
st.info("Info")
st.warning("Warning")
st.error("Error message")
# Streamlit Form
with st.form(key = "입력 form"):
username = st.text_input("Username")
password = st.text_input("Password", type="password")
st.form_submit_button("login")
# Streamlit File Uploader
uploaded_file = st.file_uploader("Choose a file", type = ["png","jpg","jpeg"])
# Streamlit API Document
# https://docs.streamlit.io/library/api-reference
1.3.5 Streamlit Cheat Sheet
1.3.6 Streamlit Data Flow
- Streamlit의 화면에서 무언가 업데이트되면 전체 Streamlit 코드가 다시 실행
- 1) Code가 수정되는 경우
- 2) 사용자가 Streamlit의 위젯과 상호작용하는 경우(버튼 클릭, 입력 상자에 텍스트 입력시 등)
1.4 Session State
- Streamlit의 Data Flow로 인해 매번 코드가 재실행되며 중복 이벤트를 할 수 없음
- Global Variable 처럼 서로 공유할 수 있는 변수가 필요
- Streamlit 0.84 버전에 session_state가 개발됨
- st.session_state.{session_state_value}
- session_state_value에 저장해서 활용하는 방식
1.4.1 Session State가 없다면
- Increment 버튼을 누르면 +1, Decrement 버튼을 누르면 -1이 되는 Counter 예제
- 버튼을 누를 때마다 코드가 재실행되어 count_value = 0 으로 되서
- increment button을 몇번 클릭해도 값은 1
- decrement button을 몇번 클릭해도 값은 -1
st.title("Counter Example without session state")
count_value = 0
increment = st.button('Increment')
if increment:
count_value += 1
decrement = st.button('Decrement')
if decrement:
count_value -= 1
st.write('Count = ', count_value)
1.4.2 Session State가 있다면
- 의도된 대로 정상 작동
st.title("Counter Example with session state")
if 'count' not in st.session_state:
st.session_state.count = 0
increment = st.button('Increment')
if increment:
st.session_state.count += 1
decrement = st.button('Decrement')
if decrement:
st.session_state.count -= 1
st.write('Count = ', st.session_state.count)
1.4.3 Session State more info
- https://blog.streamlit.io/session-state-for-streamlit/
- Session State를 사용한 예시 https://share.streamlit.io/streamlit/release-demos/0.84/0.84/streamlit_app.py
1.5 Streamlit Cache - @st.cache
- 매번 다시 실행하는 특성 때문에 데이터도 매번 다시 읽을 수 있음
- 이런 경우 @st.cache 데코레이터를 사용해 캐싱하면 좋음(캐싱 : 성능을 위해 메모리 등에 저장하는 행위)
- 데이터를 읽는 함수를 만들고, 데코레이터를 적용
DATE_COLUMN = 'date/time'
DATA_URL = ("https://s3-us-west-2.amazonaws.com/streamlit-demo-data/uber-raw-data-sep14.csv.gz")
@st.cache
def load_data(nrow):
data = pd.read_csv(DATA_URL, nrows=nrows)
lowercase = lambda x: str(x).lower()
data.remane(lowercase, axis='columns', inplace=True)
data[DATE_COLUMN] = pd.to_datetime(data[DATA_COLUMN])
return data
'MLOps' 카테고리의 다른 글
MLOps - 8. Streamlit 실습 (0) | 2022.05.23 |
---|---|
MLOps - 7. Streamlit (0) | 2022.05.23 |
MLOps - 5. Voila, ipywidget (0) | 2022.05.21 |
MLOps - 4. Voila, ipywidget (0) | 2022.05.20 |
MLOps - 3. 머신러닝 프로젝트 라이프 사이클 (0) | 2022.05.19 |
댓글