| 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 |
|
|
| |
| try: |
| model = xgb.XGBClassifier() |
| model.load_model('xgboost_model.json') |
| feature_names = joblib.load('feature_names.joblib') |
| |
| 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) |
| |
| 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 |
| |
| |
| 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 "НИЗКИЙ (Норма)" |
| |
| |
| 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) |
|
|
| |
| 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")) |