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"))