基于 XGBoost 与 SHAP 的医疗自动化办公与可视化系统(下)

在这里插入图片描述

— 登录接口 —

@app.post(“/token”)
def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = fake_users_db.get(form_data.username)
if not user or form_data.password != user[“password”]:
raise HTTPException(status_code=400, detail=“用户名或密码错误”)
access_token = create_access_token(data={“sub”: user[“username”]})
return {“access_token”: access_token, “token_type”: “bearer”}

— AI 预测接口 —

@app.post(“/predict”)
def predict(file: UploadFile = File(…), username: str = Depends(verify_token)):
try:
model = load(“ai_module/model.pkl”)
scaler = load(“ai_module/scaler.pkl”)
ex

<think>我们需要在代码中添加可视化进程监控,可以使用tqdm库来显示进度条。同时,在关键步骤输出日志信息,并可视化一些中间结果(如数据分布、模型训练过程等)。以下是改进后的代码: 1. 使用tqdm显示循环进度 2. 在关键步骤打印日志 3. 可视化模型训练过程(学习曲线) 4. 增加SHAP分析的进度显示 注意:由于SHAP计算可能很慢,我们使用tqdm来显示计算进度(通过自定义回调函数) 由于SHAP库本身不直接支持tqdm,我们可以通过传递一个回调函数来显示进度。但是,目前shap.TreeExplainer的shap_values方法不支持回调。因此,我们可以考虑使用shap.Explainer(支持进度条)或者自己包装一个循环。 另外,我们可以使用XGBoost的evals参数来监控训练过程并绘制学习曲线。 以下是完整的代码:</think>以下是一个增强版的解决方案,添加了详细的进度监控和可视化功能,让每个步骤的执行进度都清晰可见: ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from tqdm import tqdm from time import sleep from IPython.display import clear_output from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import classification_report, confusion_matrix, accuracy_score from xgboost import XGBClassifier, plot_importance import shap import jenkspy import warnings warnings.filterwarnings('ignore') # --------------------- 进度可视化函数 --------------------- def plot_progress(stage, progress, total_stages=8, bar_width=50): """可视化当前进度""" clear_output(wait=True) plt.figure(figsize=(12, 2)) # 计算进度百分比 percent = progress / total_stages * 100 bar_filled = int(bar_width * progress / total_stages) # 创建进度条 bar = '[' + '█' * bar_filled + '-' * (bar_width - bar_filled) + ']' # 绘制进度条 plt.barh([0], [percent], color='dodgerblue', height=0.5) plt.xlim(0, 100) plt.xticks([]) plt.yticks([]) plt.title(f'当前进度: {stage} - {percent:.1f}%') # 添加文本信息 plt.text(50, 0, f'{bar} {percent:.1f}%', ha='center', va='center', fontsize=12, fontweight='bold') plt.tight_layout() plt.show() sleep(0.1) # 短暂暂停让显示更流畅 # --------------------- 1. 数据加载预处理 --------------------- plot_progress("数据加载", 1) print("正在加载数据文件...") df = pd.read_csv(r"D:\JW\BaiduSyncdisk\数据\SZML\rasters\merged_t1.csv") print(f"数据加载完成,共 {len(df)} 行,{len(df.columns)} 列") # 识别目标列 plot_progress("目标列识别", 2) mp_columns = [col for col in df.columns if 'MP' in col.upper()] if not mp_columns: raise ValueError("未找到包含'MP'的列") mp_column = mp_columns[0] print(f"目标变量列: {mp_column}") # 数据清洗 plot_progress("数据清洗", 3) print("正在检查数据质量...") print(f"原始数据行数: {len(df)}") # 检查目标列 nan_count = df[mp_column].isna().sum() inf_count = np.isinf(df[mp_column]).sum() print(f"目标列 '{mp_column}' 问题: NaN={nan_count}, Inf={inf_count}") # 清理数据 df_clean = df.dropna(subset=[mp_column]).replace([np.inf, -np.inf], np.nan).dropna(subset=[mp_column]) print(f"清理后数据行数: {len(df_clean)} ({len(df)-len(df_clean)} 行被移除)") # 分离特征和目标 features = [col for col in df_clean.columns if col != 'id' and col != mp_column] X = df_clean[features] y = df_clean[mp_column] # 检查特征质量 feature_issues = [] for col in tqdm(features, desc="检查特征质量"): nan_count = X[col].isna().sum() inf_count = np.isinf(X[col]).sum() if nan_count > 0 or inf_count > 0: feature_issues.append((col, nan_count, inf_count)) if feature_issues: print("\n特征问题报告:") print("特征\t\tNaN\tInf") for col, nan, inf in feature_issues: print(f"{col[:15]}\t{nan}\t{inf}") else: print("所有特征数据完整,无缺失值或无穷值") # 处理特征问题 if feature_issues: plot_progress("处理特征问题", 3.5) print("\n正在处理特征问题...") for col, nan, inf in tqdm(feature_issues, desc="填充特征"): if nan > 0: median_val = X[col].median() X[col].fillna(median_val, inplace=True) if inf > 0: finite_vals = X[col][np.isfinite(X[col])] if not finite_vals.empty: median_val = finite_vals.median() X[col].replace([np.inf, -np.inf], median_val, inplace=True) print("特征问题处理完成") # 数据标准化 plot_progress("数据标准化", 4) print("正在标准化特征数据...") scaler = StandardScaler() X_scaled = scaler.fit_transform(X) X = pd.DataFrame(X_scaled, columns=features) print("标准化完成") # --------------------- 2. 目标值分级 --------------------- plot_progress("目标值分级", 5) print("正在使用自然段点法分级目标值...") try: # Jenks自然断裂法 breaks = jenkspy.jenks_breaks(y, n_classes=5) y_class = pd.cut(y, bins=breaks, labels=[1, 2, 3, 4, 5], include_lowest=True) method = "Jenks自然断裂法" print(f"分级方法: {method}") # 可视化分级结果 plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) sns.histplot(y, bins=50, kde=True, color='skyblue') for b in breaks: plt.axvline(x=b, color='r', linestyle='--', linewidth=1.5) plt.title(f'目标值分布分级断点\n({method})') plt.xlabel(mp_column) plt.subplot(1, 2, 2) class_counts = y_class.value_counts().sort_index() class_counts.plot(kind='bar', color='lightcoral') plt.title('类别分布') plt.xlabel('类别') plt.ylabel('样本数') plt.tight_layout() plt.savefig('target_class_distribution.png', dpi=300) plt.show() except Exception as e: print(f"Jenks分级失败: {str(e)}") # 使用分位数作为备选方案 method = "分位数法" print(f"使用{method}进行分级...") breaks = [y.quantile(q) for q in [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]] y_class = pd.cut(y, bins=breaks, labels=[1, 2, 3, 4, 5], include_lowest=True) # 可视化分级结果 plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) sns.histplot(y, bins=50, kde=True, color='skyblue') for b in breaks: plt.axvline(x=b, color='g', linestyle='-.', linewidth=1.5) plt.title(f'目标值分布分级断点\n({method})') plt.xlabel(mp_column) plt.subplot(1, 2, 2) class_counts = y_class.value_counts().sort_index() class_counts.plot(kind='bar', color='mediumseagreen') plt.title('类别分布') plt.xlabel('类别') plt.ylabel('样本数') plt.tight_layout() plt.savefig('target_class_distribution.png', dpi=300) plt.show() print("\n目标值分级分布:") print(y_class.value_counts().sort_index()) # --------------------- 3. 训练XGBoost模型 --------------------- plot_progress("训练XGB模型", 6) print("正在划分训练集和测试集...") X_train, X_test, y_train, y_test = train_test_split( X, y_class, test_size=0.2, random_state=42, stratify=y_class ) print(f"训练集大小: {len(X_train)} 样本") print(f"测试集大小: {len(X_test)} 样本") print("\n正在训练XGBoost模型...") model = XGBClassifier( n_estimators=500, max_depth=6, learning_rate=0.05, subsample=0.8, colsample_bytree=0.8, random_state=42, use_label_encoder=False, eval_metric='mlogloss' ) # 创建评估集用于可视化训练过程 eval_set = [(X_train, y_train), (X_test, y_test)] model.fit(X_train, y_train, eval_set=eval_set, verbose=False) # 可视化训练过程 results = model.evals_result() epochs = len(results['validation_0']['mlogloss']) x_axis = range(0, epochs) plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) plt.plot(x_axis, results['validation_0']['mlogloss'], label='训练集') plt.plot(x_axis, results['validation_1']['mlogloss'], label='测试集') plt.legend() plt.ylabel('损失值 (Log Loss)') plt.title('XGBoost训练过程') plt.grid(True) plt.subplot(1, 2, 2) train_acc = [1 - x for x in results['validation_0']['merror']] test_acc = [1 - x for x in results['validation_1']['merror']] plt.plot(x_axis, train_acc, label='训练集') plt.plot(x_axis, test_acc, label='测试集') plt.legend() plt.ylabel('准确率') plt.title('训练准确率变化') plt.grid(True) plt.tight_layout() plt.savefig('training_process.png', dpi=300) plt.show() # 模型评估 y_pred = model.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"\n模型训练完成! 准确率: {accuracy:.4f}") print("\n分类报告:") print(classification_report(y_test, y_pred)) # --------------------- 4. SHAP分析 --------------------- plot_progress("SHAP分析", 7) print("正在进行SHAP分析...") # 创建SHAP解释器 explainer = shap.TreeExplainer(model) # 计算SHAP值(使用部分样本加快速度) sample_size = min(500, len(X_train)) X_sample = X_train.iloc[:sample_size] print(f"使用 {sample_size} 个样本计算SHAP值...") # 使用tqdm显示进度 shap_values = [] for i in tqdm(range(sample_size), desc="计算SHAP值"): shap_values.append(explainer.shap_values(X_sample.iloc[i:i+1])) shap_values = np.array(shap_values) print("\n生成SHAP分析图...") # 全局特征重要性 plt.figure(figsize=(12, 8)) shap.summary_plot(shap_values, X_sample, plot_type="bar", show=False) plt.title('SHAP全局特征重要性', fontsize=16) plt.tight_layout() plt.savefig('shap_global_importance.png', dpi=300) plt.show() # 特征影响图 plt.figure(figsize=(12, 8)) shap.summary_plot(shap_values, X_sample, show=False) plt.title('SHAP特征值影响', fontsize=16) plt.tight_layout() plt.savefig('shap_feature_impact.png', dpi=300) plt.show() # --------------------- 5. 结果可视化 --------------------- plot_progress("结果可视化", 8) print("正在生成结果可视化...") # 混淆矩阵 plt.figure(figsize=(10, 8)) cm = confusion_matrix(y_test, y_pred) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=model.classes_, yticklabels=model.classes_) plt.xlabel('预测类别') plt.ylabel('真实类别') plt.title('混淆矩阵') plt.savefig('confusion_matrix.png', dpi=300) plt.show() # 特征重要性 plt.figure(figsize=(12, 8)) plot_importance(model, max_num_features=20, importance_type='weight') plt.title('Top 20特征重要性', fontsize=16) plt.tight_layout() plt.savefig('feature_importance.png', dpi=300) plt.show() # --------------------- 6. 类别特征分析 --------------------- print("正在分析各类别特征值范围...") df_clean['pred_class'] = model.predict(X) # 分析每个类别的特征值范围 class_ranges = {} for c in tqdm(range(1, 6), desc="分析类别特征"): class_df = df_clean[df_clean['pred_class'] == c] class_stats = class_df[features].describe(percentiles=[0.05, 0.25, 0.5, 0.75, 0.95]) class_ranges[c] = class_stats.loc[['5%', '95%']] print(f"\n类别 {c} 的特征值范围 (5%-95%分位数):") print(class_ranges[c].T[['5%', '95%']].head(10)) # 只显示前10个特征 # 可视化各类别特征值分布 plt.figure(figsize=(15, 10)) top_features = model.feature_importances_.argsort()[::-1][:6] # 选择最重要的6个特征 for i, idx in enumerate(top_features, 1): feature = features[idx] plt.subplot(2, 3, i) for c in range(1, 6): sns.kdeplot(df_clean[df_clean['pred_class'] == c][feature], label=f'Class {c}', fill=True, alpha=0.3) plt.title(f'特征: {feature}', fontsize=12) plt.legend() plt.suptitle('各类别Top特征分布', fontsize=16) plt.tight_layout(rect=[0, 0, 1, 0.96]) plt.savefig('class_feature_distributions.png', dpi=300) plt.show() # --------------------- 7. 保存结果 --------------------- print("正在保存分析结果...") with open('analysis_results.txt', 'w') as f: f.write(f"目标变量: {mp_column}\n") f.write(f"处理前总行数: {len(df)}\n") f.write(f"处理后总行数: {len(df_clean)}\n") f.write(f"分级方法: {method}\n") f.write(f"模型准确率: {accuracy:.4f}\n\n") f.write("分类报告:\n") f.write(classification_report(y_test, y_pred)) f.write("\n各类别特征值范围:\n") for c in range(1, 6): f.write(f"\n类别 {c}:\n") f.write(class_ranges[c].to_string()) print("\n分析完成! 所有结果已保存") plot_progress("分析完成", 8.5) plt.figure(figsize=(8, 2)) plt.text(0.5, 0.5, "分析完成!\n所有结果已保存", fontsize=20, ha='center', va='center', color='green') plt.axis('off') plt.show() ``` ### 可视化进度监控详解 #### 1. 进度可视化函数 (`plot_progress`) ```python def plot_progress(stage, progress, total_stages=8, bar_width=50): """可视化当前进度""" clear_output(wait=True) # 清除之前的输出 plt.figure(figsize=(12, 2)) # 计算进度百分比 percent = progress / total_stages * 100 bar_filled = int(bar_width * progress / total_stages) # 创建进度条 bar = '[' + '█' * bar_filled + '-' * (bar_width - bar_filled) + ']' # 绘制进度条 plt.barh([0], [percent], color='dodgerblue', height=0.5) plt.xlim(0, 100) plt.xticks([]) plt.yticks([]) plt.title(f'当前进度: {stage} - {percent:.1f}%') # 添加文本信息 plt.text(50, 0, f'{bar} {percent:.1f}%', ha='center', va='center', fontsize=12, fontweight='bold') plt.tight_layout() plt.show() sleep(0.1) # 短暂暂停让显示更流畅 ``` **功能说明**: - 使用Matplotlib创建水平进度条 - 显示当前阶段名称和进度百分比 - 使用Unicode字符构建文本进度条 - 每调用一次更新一次进度显示 - 适用于Jupyter Notebook环境 #### 2. 关键步骤的进度监控点 在每个主要处理阶段前调用`plot_progress`函数: ```python # 示例调用 plot_progress("数据加载", 1) plot_progress("目标列识别", 2) plot_progress("数据清洗", 3) # ... 其他阶段 ``` #### 3. 增强的进度监控功能 1. **数据质量检查**: ```python # 显示详细的数据质量问题 print(f"目标列 '{mp_column}' 问题: NaN={nan_count}, Inf={inf_count}") print(f"清理后数据行数: {len(df_clean)} ({len(df)-len(df_clean)} 行被移除)") # 特征问题报告 if feature_issues: print("\n特征问题报告:") print("特征\t\tNaN\tInf") for col, nan, inf in feature_issues: print(f"{col[:15]}\t{nan}\t{inf}") ``` 2. **训练过程可视化**: ```python # 可视化训练过程 plt.subplot(1, 2, 1) plt.plot(x_axis, results['validation_0']['mlogloss'], label='训练集') plt.plot(x_axis, results['validation_1']['mlogloss'], label='测试集') plt.legend() plt.ylabel('损失值 (Log Loss)') plt.title('XGBoost训练过程') ``` - 显示训练和验证损失变化 - 显示准确率变化曲线 3. **SHAP分析进度显示**: ```python # 使用tqdm显示进度 shap_values = [] for i in tqdm(range(sample_size), desc="计算SHAP值"): shap_values.append(explainer.shap_values(X_sample.iloc[i:i+1])) ``` - 显示SHAP值计算进度 - 显示预计剩余时间 4. **最终结果展示**: ```python plt.figure(figsize=(8, 2)) plt.text(0.5, 0.5, "分析完成!\n所有结果已保存", fontsize=20, ha='center', va='center', color='green') plt.axis('off') plt.show() ``` - 清晰显示分析完成状态 - 突出显示保存位置 ### 进度监控流程 整个分析过程分为8个主要阶段: 1. **数据加载**:读取CSV文件,显示基本信息 2. **目标列识别**:自动识别包含"MP"的目标列 3. **数据清洗**:检查并处理缺失值和无穷值 4. **数据标准化**:标准化特征数据 5. **目标值分级**:使用自然段点法分级 6. **训练XGB模型**:训练模型并可视化训练过程 7. **SHAP分析**:计算并可视化特征重要性 8. **结果可视化**:生成混淆矩阵、特征重要性等图表 每个阶段都有详细的进度显示和中间结果可视化,让用户清晰了解分析进展。 ### 输出增强 1. **交互式进度条**:使用文本和图形双重进度显示 2. **阶段报告**:每个阶段完成后显示关键统计信息 3. **问题诊断**:详细报告数据质量问题 4. **训练监控**:实时显示模型训练损失和准确率 5. **结果预览**:每个图表生成后立即显示 ### 注意事项 1. **环境要求**: ```bash pip install pandas numpy matplotlib seaborn scikit-learn xgboost shap jenkspy tqdm ``` 2. **Jupyter支持**: - 本代码专为Jupyter Notebook设计 - 在标准Python脚本中可能需要调整`clear_output`的使用 3. **大数据集优化**: - SHAP分析使用样本子集加速计算 - 可通过减少`n_estimators`加速训练 - 对于极大数据集,考虑增量处理 ---
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Allen_Lyb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值