지금까지는 남이 만든 모델을 가져온다고 가정했지만, 오늘은 직접 의료 데이터를 생성하고, AI를 학습시켜 파일(.pkl)로 저장한 뒤, 웹 서비스로 띄우는 전체 과정을 실습합니다.
이 과정은 크게 주방(모델 학습)과 홀(웹 서비스)로 나뉩니다.
1부. 주방: 의료 데이터 생성 및 모델 저장 (train_model.py)
먼저 주피터 노트북이나 파이썬 스크립트에서 실행할 코드입니다. 가상의 심장병 데이터를 만들고, RandomForest로 학습시킨 뒤, 그 '뇌'를 heart_model.pkl이라는 파일로 박제(Serialize)합니다.
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib # 모델을 파일로 저장하는 라이브러리
# 1. 가상의 심장병 데이터 생성 (500명)
def generate_data():
np.random.seed(42)
n = 500
df = pd.DataFrame({
'Age': np.random.randint(20, 90, n),
'BMI': np.random.normal(25, 4, n).round(1),
'Blood_Pressure': np.random.randint(90, 180, n), # 혈압
'Cholesterol': np.random.randint(120, 300, n), # 콜레스테롤
'Sex': np.random.choice([0, 1], n), # 0:여성, 1:남성
'Risk': np.random.choice([0, 1], n, p=[0.7, 0.3]) # 0:정상, 1:심장병
})
return df
print("데이터 생성 중...")
df = generate_data()
# 2. 모델 학습
X = df[['Age', 'BMI', 'Blood_Pressure', 'Cholesterol', 'Sex']]
y = df['Risk']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 정확도 확인
score = accuracy_score(y_test, model.predict(X_test))
print(f"모델 학습 완료! 정확도: {score:.2f}")
# 3. 모델을 파일로 저장 (.pkl) -> 이 부분이 핵심!
joblib.dump(model, 'heart_model.pkl')
print("모델이 'heart_model.pkl' 파일로 저장되었습니다.")
실행 결과: 이 코드를 한 번 실행하면, 같은 폴더에 heart_model.pkl이라는 파일이 생깁니다. 이제 AI의 두뇌가 파일로 준비된 것입니다!
2부. 홀: Streamlit으로 AI 웹 서비스 만들기 (app.py)
이제 방금 만든 heart_model.pkl 파일을 불러와서, 의사가 환자 정보를 입력하면 예측 결과를 보여주는 웹 앱을 만듭니다.
핵심 포인트:
- joblib.load()로 모델 불러오기
- @st.cache_resource로 모델 로딩 속도 최적화
- 사용자 입력(위젯)을 모델 학습 때와 똑같은 컬럼 순서로 맞추기
# app.py
import streamlit as st
import pandas as pd
import numpy as np
import joblib
import os
# --- 1. 페이지 설정 ---
st.set_page_config(page_title="심장병 예측 AI")
# --- 2. 모델 로딩 (캐싱 사용) ---
# 모델 파일은 한 번만 불러오면 되므로 cache_resource를 씁니다.
@st.cache_resource
def load_ai_model():
if os.path.exists('heart_model.pkl'):
return joblib.load('heart_model.pkl')
else:
return None
st.title("AI 심장병 위험도 진단 시스템")
st.markdown("---")
# 모델 불러오기
model = load_ai_model()
if model is None:
st.error("모델 파일(heart_model.pkl)을 찾을 수 없습니다. 1부 코드를 먼저 실행해주세요!")
else:
# --- 3. 사이드바: 환자 정보 입력 (위젯) ---
st.sidebar.header("환자 정보 입력")
# 모델 학습 때 사용한 변수: Age, BMI, Blood_Pressure, Cholesterol, Sex
age = st.sidebar.slider("나이 (Age)", 20, 90, 45)
gender = st.sidebar.radio("성별 (Sex)", ["남성", "여성"])
# 학습할 때 남성=1, 여성=0으로 했으므로 변환 필요
sex_value = 1 if gender == "남성" else 0
bmi = st.sidebar.number_input("BMI (체질량지수)", 15.0, 40.0, 24.5)
bp = st.sidebar.number_input("혈압 (Blood Pressure)", 90, 200, 120)
chol = st.sidebar.number_input("콜레스테롤 (Cholesterol)", 100, 400, 190)
# --- 4. 메인 화면: 예측 실행 ---
st.subheader("환자 임상 데이터 확인")
# 입력받은 값을 데이터프레임으로 만듭니다. (컬럼 이름과 순서가 학습 때와 같아야 함!)
input_df = pd.DataFrame({
'Age': [age],
'BMI': [bmi],
'Blood_Pressure': [bp],
'Cholesterol': [chol],
'Sex': [sex_value]
})
# 입력 데이터 보여주기
st.dataframe(input_df)
predict_btn = st.button("진단 결과 예측 (Predict)")
if predict_btn:
# 모델 예측
prediction = model.predict(input_df)[0]
probability = model.predict_proba(input_df)[0][1] # 심장병일 확률 (1일 확률)
st.markdown("---")
st.subheader("AI 분석 결과")
# 결과 시각화 (Progress Bar 활용)
st.write(f"심장질환 발병 확률: {probability*100:.1f}%")
st.progress(float(probability)) # 0.0 ~ 1.0 사이 값 필요
if prediction == 1:
st.error("고위험군 (High Risk) 으로 예측됩니다.")
st.write("권장 사항: 정밀 심혈관 검사 및 전문의 상담이 필요합니다.")
else:
st.success("저위험군 (Low Risk) 으로 예측됩니다.")
st.write("권장 사항: 현재 상태를 유지하며 정기 검진을 받으세요.")

정리
- Training (학습): train_model.py를 실행해서 데이터를 공부시키고 heart_model.pkl이라는 뇌를 만들었습니다.
- Serving (배포): app.py를 실행(streamlit run app.py)해서 그 뇌를 웹사이트에 이식했습니다.
[실행 순서 요약]
- 터미널에서 python train_model.py 실행 $\rightarrow$ heart_model.pkl 생성 확인.
- 터미널에서 streamlit run app.py 실행 $\rightarrow$ 웹 브라우저 열림.
- 웹에서 값을 바꾸고 버튼 클릭 $\rightarrow$ AI가 실시간으로 응답!
'Study Note > Streamlit' 카테고리의 다른 글
| [Django x Streamlit] 의료 데이터 분석 플랫폼 구축하기: ORM부터 웹 대시보드까지 (0) | 2025.12.30 |
|---|---|
| [Streamlit 대시보드] 숫자로 말하는 데이터: st.metric과 멀티페이지 앱(MPA) 설계 (0) | 2025.12.29 |
| "내 앱은 왜 자꾸 까먹을까?" : Session State와 Caching 완벽 해부 (0) | 2025.12.29 |
| 속도는 올리고 코드는 깔끔하게 (0) | 2025.12.29 |
| 의료 데이터 분석, 웹으로 띄우기 (기초편) (0) | 2025.12.29 |