PolySen / app.py
ksmaru's picture
Update app.py
58ef603 verified
Raw
History Blame Contribute Delete
8.33 kB
import gradio as gr
import pandas as pd
import joblib
import numpy as np
import shap
import matplotlib.pyplot as plt
import xgboost as xgb
# 1. ЗАГРУЗКА МОДЕЛИ И КОНФИГУРАЦИЙ
try:
model = xgb.XGBClassifier()
model.load_model('xgboost_model.json')
feature_names = joblib.load('feature_names.joblib')
# Загружаем ожидаемое значение для SHAP
expected_value = joblib.load('shap_expected_value.joblib')
if isinstance(expected_value, (list, np.ndarray)):
expected_value = expected_value[0]
except Exception as e:
print(f"Ошибка загрузки файлов: {e}")
def predict_risk(*args):
# Преобразование входных данных
data_list = list(args)
# Пол: Мужской -> 1, Женский -> 2
data_list[1] = 1 if data_list[1] == "Мужской" else 2
input_df = pd.DataFrame([data_list], columns=feature_names)
# Исходная вероятность от модели
raw_prob = model.predict_proba(input_df)[0][1]
# --- ЛОГИКА РЕКОМЕНДАЦИЙ И ПРОВЕРКА ОТКЛОНЕНИЙ ---
recs = ["## 📋 Персонализированный медицинский отчет:"]
critical_alerts = 0
# Проверка АД
if data_list[6] >= 140 or data_list[7] >= 90:
recs.append(f"🔴 **Артериальная гипертензия ({int(data_list[6])}/{int(data_list[7])}):** Давление выше нормы (120/80). Это главный фактор нагрузки на сосуды и сердце.")
critical_alerts += 1
# Проверка сахара (HbA1c)
if data_list[8] > 5.7:
recs.append(f"🔴 **Гликированный гемоглобин ({data_list[8]}%):** Указывает на риск преддиабета (норма до 5.7%). Рекомендуется диета с низким ГИ.")
critical_alerts += 1
# Проверка воспаления (СРБ)
if data_list[9] > 3.0:
recs.append(f"🔴 **Системное воспаление (СРБ {data_list[9]} мг/л):** Маркер высокого биологического стресса. Ищите скрытые очаги инфекции.")
critical_alerts += 1
# Проверка сна
if data_list[16] < 7:
recs.append(f"😴 **Дефицит сна ({data_list[16]}ч):** Сон менее 7 часов блокирует восстановление нервной системы и повышает аллостатический износ.")
critical_alerts += 1
# Проверка депрессии
if data_list[17] >= 10:
recs.append(f"🧠 **Психоэмоциональный стресс (PHQ-9: {data_list[17]}):** Высокий уровень депрессии истощает ресурсы адаптации.")
critical_alerts += 1
# Проверка экологии (Свинец)
if data_list[13] > 1.5:
recs.append(f"☣️ **Токсическая нагрузка:** Повышен уровень свинеца в крови. Проверьте экологию жилища и качество воды.")
critical_alerts += 1
# --- КАЛИБРОВКА РЕЗУЛЬТАТА ---
# Если критических отклонений мало или нет, мы снижаем вероятность, чтобы избежать ложноположительных результатов
if critical_alerts == 0:
calibrated_prob = raw_prob * 0.15 # Снижаем в несколько раз
recs = ["## ✅ Ваш биологический статус: В норме", "Система не выявила критических отклонений. Ваш организм успешно справляется с текущими нагрузками. Продолжайте соблюдать режим сна и питания."]
elif critical_alerts < 2:
calibrated_prob = raw_prob * 0.6
else:
calibrated_prob = raw_prob
# Ограничиваем вероятность для красоты вывода
display_prob = np.clip(calibrated_prob, 0.01, 0.99)
risk_level = "ВЫСОКИЙ (Требуется коррекция)" if display_prob > 0.5 else "НИЗКИЙ (Норма)"
# --- ГРАФИК SHAP ---
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(input_df)
plt.figure(figsize=(16, 4))
ru_cols = [
"Возраст", "Пол", "Доход", "Образование", "ИМТ", "Талия",
"Систол. АД", "Диастол. АД", "Глик. гемоглобин", "СРБ", "Инсулин",
"Холестерин", "ЛПВП", "Свинец", "Кадмий", "Фталаты", "Сон", "Депрессия"
]
input_df_ru = input_df.copy()
input_df_ru.columns = ru_cols
shap.force_plot(
expected_value,
shap_values[0],
input_df_ru.iloc[0],
matplotlib=True,
show=False,
contribution_threshold=0.03
)
plt.tight_layout()
shap_plot = plt.gcf()
return f"{display_prob:.1%}", risk_level, shap_plot, "\n\n".join(recs)
# 3. ИНТЕРФЕЙС GRADIO
with gr.Blocks(title="ПолиСен 2.5") as demo:
gr.Markdown("# 🏥 Система «ПолиСен» (v2.5)")
gr.Markdown("Оценка биологического износа на основе метаболических и экологических маркеров.")
with gr.Row():
with gr.Column():
gr.Markdown("#### 🧬 Образ жизни и Демография")
age = gr.Slider(18, 85, value=40, step=1, label="Возраст")
gender = gr.Radio(["Мужской", "Женский"], value="Мужской", label="Пол")
income = gr.Slider(0.0, 5.0, value=3.0, step=0.1, label="Индекс дохода")
edu = gr.Slider(1, 5, value=4, step=1, label="Образование (1-5)")
bmi = gr.Slider(15.0, 50.0, value=24.0, step=0.1, label="ИМТ (BMI)")
waist = gr.Slider(60, 150, value=85, step=1, label="Талия (см)")
sleep = gr.Slider(3.0, 12.0, value=8.0, step=0.5, label="Часы сна")
phq9 = gr.Slider(0, 27, value=3, step=1, label="Депрессия (PHQ-9)")
with gr.Column():
gr.Markdown("#### 🩸 Лабораторные маркеры")
sys_bp = gr.Slider(90, 200, value=120, step=1, label="Систолическое АД")
dia_bp = gr.Slider(60, 120, value=80, step=1, label="Диастолическое АД")
hba1c = gr.Slider(4.0, 12.0, value=5.2, step=0.1, label="Глик. гемоглобин (%)")
hscrp = gr.Slider(0.0, 10.0, value=0.7, step=0.1, label="СРБ (мг/л)")
insulin = gr.Slider(2.0, 100.0, value=8.0, step=1, label="Инсулин")
chol = gr.Slider(120, 300, value=185, step=1, label="Холестерин")
hdl = gr.Slider(20, 100, value=60, step=1, label="ЛПВП (HDL)")
lead = gr.Slider(0.0, 5.0, value=0.2, step=0.01, label="Свинец")
cadm = gr.Slider(0.0, 3.0, value=0.1, step=0.01, label="Кадмий")
phth = gr.Slider(0.0, 500.0, value=20.0, step=1, label="Фталаты")
inputs = [age, gender, income, edu, bmi, waist, sys_bp, dia_bp, hba1c, hscrp, insulin, chol, hdl, lead, cadm, phth, sleep, phq9]
btn = gr.Button("🚀 ЗАПУСТИТЬ ПОЛНЫЙ АНАЛИЗ", variant="primary")
with gr.Row():
with gr.Column(scale=1):
out_prob = gr.Label(label="Риск перегрузки")
out_level = gr.Textbox(label="Клинический статус")
with gr.Column(scale=2):
out_plot = gr.Plot(label="Вклад факторов")
out_rec = gr.Markdown()
btn.click(predict_risk, inputs=inputs, outputs=[out_prob, out_level, out_plot, out_rec])
if __name__ == "__main__":
demo.launch(theme=gr.themes.Soft(primary_hue="teal"))