본문 바로가기
Python/Streamlit

[Streamlit]_잘 만들었으면 자랑해야지! 웹 배포하기

by ssolLEE 2023. 9. 7.
반응형

나의 웹에 대한 고정관념(아무나 못해, 어려워, 난 예쁘게 못만들거야.....뭐든 나에 대해 부정부정한 말들)은 Streamlit을 알게 된 전 후로 나뉠 것 같습니다. 말은 이렇게 해도 Streamlit도 그렇게 쉽진 않아요. 다만 Django보다 편합니다. 

Django도 꾸준히 공부할거에요! 하지만 우선은 Streamlit을 익숙하게 해볼게요. 

 

오늘은 Streamlit에서 만든 앱을 배포하는 것을 실습해보겠습니다. 

잘 만든 건 자랑해야 뿌듯뿌듯하죠! 

오늘 실습은 Streamlit을 가입하고, 깃헙 연동을 한 상태여야 합니다!

이왕이면 깃헙 2차 인증까지 완료해주세요!

 

GitHub repository 생성 

  • 레포지토리를 생성합니다. 배포용이니 public, 사용언어는 python을 선택합니다. 

GitHub 업로드 확인

  • 새 파일은 만들어 requirements.txt라고 명명한 후, 다음과 같이 입력 후 저장합니다. 

  • 새파일을 만들어 app.py라고 명명한 후 테스트 용으로 다음 코드를 입력합니다. 
# -*- coding:utf-8 -*-

import streamlit as st
import numpy as np

def main():

    st.markdown("# Hello Strealit")
    st.write(np.__version__)

if __name__ == "__main__":
    main()
  • git bash에서 다음과 같이 명령어를 차례로 입력하여 GitHub에 업로드 되는지 확인합니다. 
git add .
git commit -m "deploy_test"
git push

Streamlit에서 app 만들기

  • Streamlit 사이트로 이동하여 로그인합니다.

https://streamlit.io/

 

Streamlit • A faster way to build and share data apps

Streamlit is an open-source app framework for Machine Learning and Data Science teams. Create beautiful web apps in minutes.

streamlit.io

  • 다음과 같이 New app이 보이면 클릭합니다.

  • 다음과 같이 내용을 입력(선택)합니다. 

  • Advanced settings에 들어가면 python 버전도 자신의 컴퓨터에 맞게 설정할 수 있습니다. 

  • Advanced settings에 있는 Screts은 DB 연동 공간입니다. 실시간 데이터를 받을 때 인증키를 입력하는 곳이기도 합니다. 이 공간의 활용은 다음에 포스팅 하겠습니다. 
  • 다시 Deploy an app으로 나와 Deploy!를 누르면 배포 완료!
  • 간단하죠?

웹 확인하기

  • Streamlit은 이렇게 빵 굽는 것으로 로딩을 표현합니다. 귀엽습니다. 

  • 아까 우리가 app.py에서 입력한 것이 구현되었습니다.

  • 하단에 Manage app을 클릭해보세요.
  • 로그가 보입니다. 이것도 가상환경을 쓰는 거에요. 아까 우리가 VS code에서 입력했던 numpy와 streamlit이 설치되었습니다. 

  • 상단의 url은 저장해두세요. 나중엔 저 url로 들어가도 여러분이 만든 웹이 보일 것입니다.

 

웹 꾸미기

  • VS code로 돌아옵니다. 이제 웹을 꾸며볼게요.
  • 가상환경 세팅을 합니다. 오랜만이죠?
  • 여기서 팁을 주자면, 바탕화면의 git bash는 깃헙 업로드용으로 두고, VS code 내에서는 터미널을 사용하면 일처리가 쉽습니다. 
  • 다음과 같이 가상환경을 세팅하고 가상환경에 접속합니다. 
virtualenv venv
source venv/Scripts/activate
  • requirements.txt에 필요한 라이브러리를 더 입력하고 저장합니다. 
numpy
streamlit
pandas
matplotlib
seaborn
scikit-learn
plotly
streamlit
  • data 폴더를 만들고 iris.csv를 저장합니다.

iris.csv
0.00MB

  • app.py를 수정하겠습니다. 이 곳은 메인페이지로, 골격을 만드는 곳이라고 생각하시면 됩니다. 여기에 우리는 세부 항목들의 파일을 만들고 이걸 함수처리해서 서로 호출하는 개념으로 구조를 짤 것입니다. 
# -*- coding:utf-8 -*-

import streamlit as st
import numpy as np

def main():

    st.markdown("# Deploy Strealit")
    st.markdown("## using iris data")
    menu = ['Home', 'EDA', 'ML', 'About']
    choice = st.sidebar.selectbox("menu", menu)
    if choice == "Home":
        st.subheader("Home")
    elif choice == "EDA":
        st.subheader("EDA")
    elif choice == "ML":
        st.subheader("ML")
    elif choice == "About":
        st.subheader("About")
    else: 
        pass

if __name__ == "__main__":
    main()
  • 터미널에서 strealit run app.py를 실행합니다.
  • 배포 작업할 때는 이렇게 run으로 웹을 확인한 후, 최종적으로 git bash에서 깃헙에 업로드해주면 됩니다. 
  • 다음과 같이 코드가 구현되었습니다.

 

세부 항목 꾸미기 - EDA

  • EDA를 꾸며볼까요?
  • 새 파일을 만든 후 eda_app.py라고 명명합니다. 그리고 다음과 같이 입력합니다. 
# -*- coding:utf-8 -*-

import streamlit as st
import pandas as pd

import matplotlib.pyplot as plt
import plotly.express as px
import seaborn as sns

def run_eda_app():

    st.subheader("EDA Page")
    st.subheader("EDA-ing")
  • 메인인 app.py로 가서 위 코드를 호출하도록 다음과 같이 수정합니다. 

잘 나온다.

  • 데이터를 불러오겠습니다. 
def run_eda_app():

    st.subheader("EDA Page")
    st.subheader("EDA-ing")

    iris_df = pd.read_csv("data\iris.csv")
    st.dataframe(iris_df)

  • 이렇게 간단하게 데이터를 넣을 수 있습니다.(감격감격)
  • 이런 식으로 웹 규모가 커지면 app.py에 다음 코드와 같이 import 하여 관리하면 됩니다. 
import streamlit as st
import numpy as np
from eda_app import run_eda_app
from 폴더명.파일명 import 함수명
  • 조금 더 꾸며보겠습니다. eda_app.py에 다음과 같이 submenu를 지정합니다.
def run_eda_app():

    st.subheader("EDA Page")
    st.subheader("EDA-ing")

    iris_df = pd.read_csv("data\iris.csv")
    st.dataframe(iris_df)
    
    # 메뉴 지정
    submenu = st.sidebar.selectbox("submenu", ['통계', '시각화', '분석'])
    if submenu == "submenu":
        st.subheader("submenu")
    elif submenu == "통계":
        st.subheader("통계")
    elif submenu == "시각화":
        st.subheader("시각화")
    elif submenu == "분석":
        st.subheader("분석")
    else: 
        pass

  • 그래프를 넣어볼까요?
    elif submenu == "시각화":
        st.subheader("시각화")
        fig1= px.scatter(iris_df,
                         x = 'sepal_width',
                         y = 'sepal_length',
                         color = 'species',
                         size = 'petal_width',
                         hover_data= ['petal_length'],
                         title= "Scatter Plot")
        st.plotly_chart(fig1)

세부 항목 꾸미기 - ML

  • 이제 새 폴더 models를 만들고 새 파일 model.py를 만듭니다.

  • model.py에 다음 코드를 입력합니다. 
# -*- coding:utf-8 -*-
import pandas as pd 

# 라벨 인코딩
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split # 데이터셋 분리
from sklearn.linear_model import LogisticRegression # 알고리즘 선택
import joblib # 모델 저장 시, 사용

# 데이터 불러오기
data = pd.read_csv("data/iris.csv")

# 종속변수에 라벨인코딩 부여
le = LabelBinarizer()
# print(le.fit(data['species']))
data['species'] = le.fit_transform(data['species'])
# print(le.classes_)
# print(data['species'])

# 독립변수, 종속변수로 분리
X = data.drop(columns=['species'])
y = data['species']

# 훈련, 테스트 데이터로 검증
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

model = LogisticRegression()
model.fit(X_train, y_train) # 모델 생성 코드, 모형 학습 코드

model_file = open("models/lgr_model_iris230901.pkl", "wb")
joblib.dump(model, model_file) # Export
model_file.close()
  • terminal에서 python model.py를 실행시키면 models 폴더에 파일이 생성됩니다. 

  • app.py에 다음과 같이 import를 입력하고 스스로 ml 페이지를 만들어봅시다.

  • 제가 만든 ml_app.py 파일입니다. 여러분은 어떻게 만드셨나요?
  • 내용을 다 채우는 것보다는 코드 흐름을 이해하고, 머신러닝 페이지에 자신이 입력한 문구가 출력되었다면, 그걸로 충분합니다.
# -*- coding:utf-8 -*-

import streamlit as st
import joblib
import os
import numpy as np

def run_ml_app():

    st.subheader("ML Page")
    st.subheader("ML-ing")

    # layout
    col1, col2 = st.columns(2)
    with col1:
        st.subheader("수치 입력")
        sepal_length = st.select_slider("Sepal Length", options = np.arange(1, 11))
        sepal_width = st.select_slider("Sepal Width", options = np.arange(1, 11))
        petal_length = st.select_slider("Petal Length", options = np.arange(1, 11))
        petal_width = st.select_slider("Petal Width", options = np.arange(1, 11))

        sample_list = [sepal_length, sepal_width, petal_length, petal_width]
        st.write(sample_list)

    with col2:
        st.subheader("모델 결과 확인")
        
        # 모델 불러오기
        model_file = "models/lgr_model_iris230331.pkl"
        model = joblib.load(open(os.path.join(model_file), 'rb'))
        st.write(model)

    with col2:
        st.subheader("모델 결과 확인")

        # 모델 불러오기
        model_file = "models/lgr_model_iris230331.pkl"
        model = joblib.load(open(os.path.join(model_file), "rb"))
        st.write(model)
        # 배열로 만듦
        one_sample = np.array(sample_list).reshape(1, -1)
        st.write(one_sample)
        st.write(one_sample.shape)
        # 범주 예측
        prediction = model.predict(one_sample)
        st.write(prediction)
        # 확률값 예측
        pred_prob = model.predict_proba(one_sample)
        st.write(pred_prob)

        if prediction == 0:
            st.success("Setosa 종")
            pred_proba_scores = {
                "1일 확률": pred_prob[0][0] * 100, 
                "0일 확률": pred_prob[0][1] * 100, 
            }
            st.write(pred_proba_scores)
            st.image('https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Irissetosa1.jpg/220px-Irissetosa1.jpg')
        elif prediction == 1:
            st.success("00 종")
            pred_proba_scores = {
                "1일 확률": pred_prob[0][0] * 100, 
                "0일 확률": pred_prob[0][1] * 100, 
            }
            st.write(pred_proba_scores)
            st.image('https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Blue_Flag%2C_Ottawa.jpg/220px-Blue_Flag%2C_Ottawa.jpg')
        else:
            st.warning("아이돈노!")
  • 이렇게 머신러닝도 꾸밀 수 있는, streamlit이었습니다.

감사합니다.

** 마지막으로 git add . / git commit -m "커밋 메시지" / git push 로 배포 완료 해주세요!