융무의 기술블로그
article thumbnail

웹에서 대시보드를 개발하려고 합니다. 거창하게 개발이라고 말을 하였지만 엄연히 보면 구현에 가까울 거 같습니다.

Python을 활용하여 대시보드를 만드는데 있어서 다양한 방법이 있겠지만 크게 Dash와 Streamlit에 관해 설명하려고 합니다. Dash의 경우 저번 포스팅에 설명을 하였고 실제로 웹에서 배포도 하여 이번에는 Streamlit를 이용하여 웹에서 배포를 해보았습니다. 대시보드 고도화를 위해서는 공홈에서 공부를 하면 좋을 거 같습니다.

https://docs.streamlit.io/en/stable/getting_started.html

 

Get started — Streamlit 0.84.2 documentation

The easiest way to learn how to use Streamlit is to try things out yourself. As you read through this guide, test each method. As long as your app is running, every time you add a new element to your script and save, Streamlit’s UI will ask if you’d li

docs.streamlit.io

https://dash.plotly.com/

 

Dash Documentation & User Guide | Plotly

 

dash.plotly.com

이번 포스팅에는 streamlit를 활용하여 Palmer penguin 데이터 분석 결과를 대시보드로 개발해보려고 합니다.

대시 보드 로딩하는 데 있어서 시간이 조금 소요됩니다.

https://dashboard-penguin.herokuapp.com/

 

Streamlit

Streamlit를 이용하여 웹 개발을 하려면 다음과 같은 구성이 필요로 합니다. 만든 웹 대시보드를 배포하기 위해서는 전용 웹 서비스가 있어야 하지만 Flask나 AWS의 경우 세팅이 간단하지 않은 것으로 알고 있습니다. 또한 Dash를 이용하여 조금 더 풍부하게 대시보드르 만들 수 있었지만 개발을 위한 모듈 코딩을 짜본적이 없고 분석을 위한 모듈 코딩만 해보아서 Dash에 관해서는 조금더 공부가 필요할 거 같습니다. 이에 비해 Streamlit는 직관적이고 디자인이 다소 아쉽게 보일지는 모르겠지만 직관적으로 전달이 가능합니다. Heroku를 이용해서 배포를 하겠습니다.

Procfile
web: sh setup.sh && streamlit run app.py

sh 명령을 실행하고 streamlit를 실행하는 명령어를 담고 있습니다.

setup.sh

sh 명령을 실행할 명령어를 담고 있습니다.

mkdir -p ~/.streamlit/

echo "\
[general]\n\
email = \"your-email@domain.com\"\n\
" > ~/.streamlit/credentials.toml

echo "\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
" > ~/.streamlit/config.toml
runtime.txt

파이썬 버전이 필요로 하다면 runtime.txt 파일에 파이썬 버전을 담아둡니다.

python-3.9.6

 

 

requirements.txt

해당 dashboard를 실행하는 데 있어서 필요한 라이브러리들입니다. 필요 라이브러리 확인은 터미널에서 pip freeze를 통해서 확인해볼 수 있습니다.

 

streamlit==0.84.1
seaborn==0.11.1
matplotlib==3.4.2
matplotlib-inline==0.1.2
xgboost==1.4.2
lightgbm==3.2.1
scikit-learn==0.24.2
pandas==1.2.5
graphviz==0.16

 

app.py

Palmer penguin data set에 대해서 알아보겠습니다.

Palmer penguin data set

  • Species: penguin species (Chinstrap, Adélie, or Gentoo)
  • Island: island name (Dream, Torgersen, or Biscoe) in the Palmer Archipelago (Antarctica)
  • Bill_length_mm: Bill length (mm)
  • Bill_depth_mm: Bill depth (mm)
  • flipper_length_mm: flipper length (mm)
  • body_mass_g: body mass (g)
  • Sex: penguin sex
EDA

간단한 데이터 EDA를 통해서 streamlit 대시보드를 만들어보겠습니다. eda를 통한 데이터 전처리 및 시각화를 한 뒤에 데이터 모델링 부분을 진행하겠습니다.

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import joypy
import pandas as pd
plt.rcParams['figure.figsize'] = 8, 5
plt.style.use("seaborn-whitegrid")

data = sns.load_dataset("penguins")
data.head()

 

팔머 펭귄의 종에 대해 barh plot을 그려보았습니다. 또한 streamlit에서 그래프를 그릴 때 subplots 형태로 만들어주면 대시보드를 만들 때 직관적으로 만들 수 있는 거 같습니다.

fig, ax = plt.subplots()
ax = data['species'].value_counts().plot(kind='barh')

팔머 펭귄의 scatter plot 그려봅니다.

penguins = data.copy()
X = penguins["flipper_length_mm"]
Y = penguins["body_mass_g"]
title = "Flipper length(mm) vs Body mass(g)"
fig, ax = plt.subplots()
ax.scatter(X,Y)
plt.title(title)
plt.xlim(160,240)
plt.ylim(2500,6500)
plt.show()

종에 따른 부리 길이에 관해 violinplot을 그려봅니다.

data.drop(data[data['body_mass_g'].isnull()].index,axis=0, inplace=True)
data['sex'] = data['sex'].fillna('Male')
data.drop(data[data['sex']=='.'].index, inplace=True)

print('Bill Length Distribution')
sns.violinplot(data=data, x="species", y="bill_length_mm", size=8)
plt.show()

seaborn의 PairGrid를 통해서 원하는 그래프와 데이터로 pairplot을 그려봅니다.

penguins = sns.load_dataset("penguins")
penguins["body_mass_100g"] = penguins["body_mass_g"]/100
df = penguins.drop('body_mass_g',axis=1)

labels=["Bill Length (mm)", "Bill Depth (mm)", "Flipper Length (mm)", "Body Mass (100g)"]
label_fontdict = {"fontsize":14, "fontweight":"bold", "color":"gray"}
labelpad = 12

tick_labelsize = "large"

g = sns.PairGrid(df, hue="species",diag_sharey=False)
g.map_diag(sns.kdeplot,fill=True)
g.map_lower(sns.scatterplot)
g.map_lower(sns.regplot, scatter=False, truncate=False, ci=False)
g.map_upper(sns.kdeplot, alpha=0.3)
g.add_legend()
for i in range(4):
    g.axes[3, i].set_xlabel(labels[i], fontdict=label_fontdict)
    g.axes[i, 0].set_ylabel(labels[i], fontdict=label_fontdict)
g.fig.align_ylabels(g.axes[:,0])

모델링

간단한 모델링을 하기 위해서 데이터 전처리를 해주려고 합니다. 필요한 라이브러리들을 불러옵니다.

from sklearn.metrics import f1_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.model_selection import cross_val_score, StratifiedKFold,train_test_split
from sklearn.metrics import confusion_matrix
import xgboost as xgb
import lightgbm as lgb
from sklearn.tree import export_graphviz
from sklearn.cluster import KMeans

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)

이번 프로젝트의 목적은 데이터 분석에 중점을 둔 것이 아닌 데이터 분석의 EDA와 모델링 결과를 stramlit를 이용하여 Dashboard로 개발하는데 초점을 맞추었습니다.

df = data.copy()
target = 'sex'
encode = ['species','island']

target_mapper = {'Male':0, 'Female':1}
def target_encode(val):
    return target_mapper[val]
df['sex'] = df['sex'].apply(target_encode)

target_mapper = {'Adelie':0, 'Gentoo':1,'Chinstrap':2}
def target_encode(val):
    return target_mapper[val]
df['species'] = df['species'].apply(target_encode)

target_mapper = {'Biscoe':0, 'Dream':1,'Torgersen':2}
def target_encode(val):
    return target_mapper[val]
df['island'] = df['island'].apply(target_encode)

X = df.drop('sex', axis=1)
y = df['sex']

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.3, shuffle=True)

 

KFold 결과를 확인하여 3가지 모델에 대해서 confusion_matrix와 feature_importances를 확인해 보겠습니다.

LightGBM

모델을 학습시켜서 나온 결과를 confusion_matrix를 히트맵으로 시각화한 결과와 LGBMClassifier의 feature_importance를 확인해 보겠습니다.

LightGBM의 tree경우 시각화를 하는 데 있어서 아직은 다채로움이 많이 부족해 보이는 것으로 파악됩니다.

digraph = lgb.create_tree_digraph(model_lgbc, orientation='vertical')
digraph.format = 'png'
digraph.view('./lgb')

 

모델을 학습할 때 joblib 라이브러리를 이용하면 학습된 모델을 저장할 수 있는 유용한 기능을 가지고 있습니다.

import joblib
joblib.dump(model_lgbc,'lgb.pkl')

.pkl형태로 저장하여 학습된 모델을 불러올 때는 다음과 같은 형태로 불러올 수 있습니다.

model_lgbc = joblib.load('lgb.pkl')
RandomForest

모델을 학습시켜서 나온 결과를 confusion_matrix를 히트맵으로 시각화한 결과와 RandomForestClassifier의 feature_importance를 확인해 보겠습니다.

RandomForest의 경우 원하는 형태로 tree 시각화가 가능하였습니다.

from pydotplus import graph_from_dot_data
from sklearn.tree import export_graphviz
import graphviz

export_graphviz(estimator, out_file='tree.dot', 
                feature_names = X_train.columns,
                class_names = ['1','2','3','4'],
                max_depth = 2, # 최대 depth
                precision = 2, # 소수점 자릿수
                filled = True, # class별 색 채우기
                rounded=True,  # 박스의 모양
                )
import graphviz

with open("tree.dot") as f:
    dot_graph = f.read()
display(graphviz.Source(dot_graph))

 

XGBoost

모델을 학습시켜서 나온 결과를 confusion_matrix를 히트맵으로 시각화 한 결과와 XGBClassifier의 feature_importance를 확인해 보겠습니다.

 

node_params = {'shape': 'box',
              'style':'filled, rounded',
              'fillcolor': 'LightBlue'}
leaf_params = {'shape':'box',
              'style':'filled',
              'fillcolor':'GreenYellow'}
diagraph = xgb.to_graphviz(model_xgb, num_trees=0, size='5,10',
               condition_node_params=node_params,
               leaf_node_params=leaf_params)
digraph.format = 'png'
digraph.view('./xgb')

to_graphviz를 통해서 xgboost의 트리 모델을 시각화하였습니다.

Clustering

KMeans 알고리즘을 사용하여 3개의 집단으로 clustering을 하였습니다.

데이터 EDA부터 시작하여 데이터 모델링을 하였습니다. 이렇게 데이터 분석을 한 코드들을 streamlit 양식에 맞춰서 app.py로 저장을 해놓습니다. 이렇게 만들어둔 파일들을 통해서 Heroku에 배포하는 방법은 아래 포스팅을 참고하면 좋을 거 같습니다.

https://mjs1995.tistory.com/184?category=802136 

 

[python][plotly] dash와 heroku를 이용한 Dashboard 제작

지도 시각화와 프로젝트 결과물을 토대로 한국지방소멸위험 대시보드를 제작하려고 합니다. korea-dashboard.herokuapp.com/ (대시 보드 로딩하는데 시간이 조금 소요됩니다.) 대시보드 개발 을 위해 다

mjs1995.tistory.com

 

 

'BI > Snowflake' 카테고리의 다른 글

[Snowflake] Hands-On Essentials - data warehouse  (0) 2023.05.14
[snowflake] snowflake 아키텍처  (1) 2023.05.13
[snowflake] snowflake 개요  (0) 2023.05.13
profile

융무의 기술블로그

@융무

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!