서울시 월별 기상정보로 서울시 식중독 발생 환자 수를 예측하는 프로그램 Seoul FP-Weather 개발 프로젝트 진행과정 정리 및 회고. (3) 대시보드 및 웹페이지 구현, 배포 과정
(2023 수정사항)
서울시 월간 기상정보를 기반으로 서울시 월간 식중독 발생 환자 수를 예측하는 AI 머신 러닝 프로그램
Tech Stack
자유주제
로 데이터 파이프라인 구축
및 API 서비스 개발
Pull
& Store
)Machine Learning
& Frond-end
)대시보드
개발 및 배포서론
식중독
프로그램소개
데이터베이스
파이프라인
DB구축
모델링
데이터 불러오기
회귀 모델
객체 부호화
배포
평년값 예측
대시보드
웹 배포
결론
활용방안
한계점
핵심, 느낀점
머신러닝에도 이용했던 서울 월별 기상요인 및 식중독 환자 수 데이터는 식중독 환자 발생 트렌드를 확인하기위한 대시보드를 제작하는데 이용하였음.
서울 월별,계절별 기후평년값 데이터는 pickle 라이브러리를 통해 불러온 모델을 통해 예측을 실시한 후에 예측에 대한 대시보드를 제작하는데 이용하였음.
Bootstrap template을 기반으로 HTML5, CSS3를 통해 웹페이지를 구현하였고, 모바일 버젼에서도 편하게 볼 수 있게끔 웹페이지를 최적화하는 작업도 수행하였음.
import numpy as np
import pandas as pd
import pickle
import os
import sys
import psycopg2
from dotenv import load_dotenv
#dotenv 로딩
load_dotenv(verbose=True)
'''
True
'''
#env 파일로부터 변수 추출
HOST = os.getenv('postgre_host')
PASSWORD = os.getenv('postgre_password')
DATABASE = 'postgredb'
USERNAME = 'kjcheong'
PORT = 5432
#연결
try:
conn = psycopg2.connect(
host=HOST,
port=PORT,
database=DATABASE,
user=USERNAME,
password = PASSWORD)
cur = conn.cursor()
print('connection success to DB')
except:
print('connection failure to DB')
sys.exit()
'''
connection success to DB
'''
#DB를 dataframe으로 저장
import pandas.io.sql as psql
month_avg = psql.read_sql("SELECT * FROM w_avg_month", conn)
month_avg
season_avg = psql.read_sql("SELECT * FROM w_avg_season", conn)
season_avg
#연결 종료
conn.close()
#예측에 쓰일 변수만 남기기
month_var = month_avg.iloc[:,2:]
display(month_var)
season_var = season_avg.iloc[:,1:]
display(season_var)
#모델 복호화
model = pickle.load(open("model.pkl", "rb"))
#예측
predict_month = model.predict(month_var).round(0)
predict_season = model.predict(season_var).round(0)
print(predict_month)
print(predict_season)
'''
[ 94. 34. 16. 14. 142. 222. 162. 171. 124. 80. 68. 149.]
[ 72. 188. 54. 52.]
'''
#기존 dataframe에 column 추가
month_pred = month_avg.copy()
season_pred = season_avg.copy()
month_pred['predict_patient'] = predict_month.astype(int)
season_pred['predict_patient'] = predict_season.astype(int)
display(month_pred)
display(season_pred)
#csv file로 저장
month_pred.to_csv('csv/pred-month.csv', index=False)
season_pred.to_csv('csv/pred-season.csv', index=False)
Seoul-FP-Weather
├── app.py
├── data
│ └── model.pkl
├── templates
│ ├── index.html
│ ├── 404.html
│ ├── 404-1.html
│ └── 404-2.html
├── static
│ ├── css
│ ├── img
│ ├── js
│ └── favicon.ico
├── Procfile
└── requirements.txt
#라이브러리 import
from flask import Flask, render_template, request
import numpy as np
import pickle
#플라스크 클래스명 지정 및 모델 불러오기
app = Flask(__name__)
model = pickle.load(open("./data/model.pkl", "rb"))
#에러 페이지 데코레이터
@app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404
#웹 페이지 rendering
@app.route('/', methods=['GET', 'POST'])
def index():
#웹페이지 (GET)
if request.method == 'GET':
return render_template('index.html'), 200
#입력 변수를 서버에 보내 예측 실행 (POST)
if request.method == 'POST':
try:
var1 = float(request.form['avgTa'])
var2 = float(request.form['maxTa'])
var3 = float(request.form['minTa'])
var4 = float(request.form['sumRn'])
var5 = float(request.form['avgWs'])
var6 = float(request.form['avgRhm'])
var7 = float(request.form['sumSsHr'])
var8 = float(request.form['avgPs'])
array = np.array([[var1, var2, var3, var4, var5, var6, var7, var8]])
pred = int(model.predict(array).round(0))
if pred < 0 :
return render_template('404-1.html') #에러페이지(예상범위를 벗어남)
else :
return render_template('index.html',pred=pred)
except:
return render_template('404-2.html') #에러페이지(숫자만 입력하시오)
#앱 실행코드 (디버깅 모드)
if __name__ == "__main__":
app.run(debug=True)
...
<div class="cover-req" style="background-color: #444;">
<br>
<h1 class="cover-heading">
<p>기상 정보를 입력해주세요<br>(숫자만 입력해주세요)</p>
</h1>
<div class="content-grid">
<div class="heading-grid">
<div class="grid-contents">
<div class="work-request--info">
<form action="/#predict-req" method="post">
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 평균 기온 (℃)</label>
<input type="text" name="avgTa" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 최고 기온 (℃)</label>
<input type="text" name="maxTa" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 최저 기온 (℃)</label>
<input type="text" name="minTa" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 합 강수량 (mm)</label>
<input type="text" name="sumRn" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 평균 풍속 (m/s)</label>
<input type="text" name="avgWs" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 평균 상대습도 (%)</label>
<input type="text" name="avgRhm" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 합 일조시간 (hr)</label>
<input type="text" name="sumSsHr" required>
</div>
<div class="info-name" style="width: 150px; margin-bottom: 20px;">
<label for="formGroupExampleInput">월 평균 해면기압 (hpa)</label>
<input type="text" name="avgPs" required>
</div>
<button type="submit" class="btn btn-lg btn-default">
<img src="../static/img/icon.png" alt="FP-Weather"> Predict !
</button>
</form>
</div>
</div>
<div class="grid-contents">
<div class="predict-result">
{% if pred %}
<br><br>
<img src="../static/img/icon-96.png">
<h2>서울시<br></h2>
<h3>월별 식중독<br><br>환자 수<br><br>예측 결과<br></h3>
<h2>{{ pred }} 명</h2>
<br>
<img src="../static/img/icon-96.png">
<br>
{% endif %}
</div>
</div>
</div>
</div>
</div>
...
입력
출력
성공적으로 작동!
Github Repository 생성
Heroku 회원가입 후 로그인 (Authenticator라는 휴대폰 어플을 통해 인증 후 로그인하였음)
앱 생성
깃허브 연결
web: gunicorn app:app
#python=3.8
#pip freeze > requirements.txt
certifi==2022.9.24
charset-normalizer==2.1.1
click==8.1.3
colorama==0.4.6
contourpy==1.0.6
cycler==0.11.0
Flask==2.2.2
fonttools==4.38.0
gunicorn==20.1.0
idna==3.4
importlib-metadata==5.0.0
itsdangerous==2.1.2
Jinja2==3.1.2
joblib==1.2.0
kiwisolver==1.4.4
lightgbm==3.3.3
MarkupSafe==2.1.1
matplotlib==3.6.0
numpy==1.23.4
packaging==21.3
pandas==1.5.1
Pillow==9.3.0
psycopg2-binary==2.9.5
pyparsing==3.0.9
python-dateutil==2.8.2
python-dotenv==0.21.0
pytz==2022.5
requests==2.28.1
scikit-learn==1.1.3
scipy==1.9.3
seaborn==0.12.1
six==1.16.0
threadpoolctl==3.1.0
urllib3==1.26.12
Werkzeug==2.2.2
wincertstore==0.2
zipp==3.10.0
기상요인을 통해 식중독 발생 환자 수를 예측하는 프로그램
을 구현
하고 배포
하는 것이 프로젝트의 핵심. -> 성공적인 구현 및 배포 완료.Data 수집
, Cloud DB 구축
, 머신러닝 API 서비스 개발
, 대시보드 제작
, 웹페이지 구현
, 모바일 최적화 작업
등...!