ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python打卡第10天

2026/8/22 10:53:13 拓冰建站 浏览量
Python打卡第10天 浙大疏锦行混淆矩阵对比指标对比特征贡献图001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227importpandas as pdimportmathimportossave_dirrD:\Desktop\Postgraduate\PythonStudy\Python打卡训练营\Python打卡训练营\day10 picfrompathlibimportPathimportmatplotlib.pyplot as pltimportnumpy as npimportseaborn as snsfromsklearn.model_selectionimporttrain_test_split, cross_val_scorefromsklearn.preprocessingimportStandardScalerfromsklearn.metricsimportconfusion_matrix, accuracy_score, precision_score, recall_score, f1_scorefromsklearn.svmimportSVCfromsklearn.neighborsimportKNeighborsClassifierfromsklearn.linear_modelimportLogisticRegressionfromsklearn.naive_bayesimportGaussianNBfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromxgboostimportXGBClassifierfromlightgbmimportLGBMClassifierimportwarningswarnings.filterwarnings(ignore)plt.rcParams[font.sans-serif][SimHei,Microsoft YaHei]# 优先黑体备选微软雅黑plt.rcParams[axes.unicode_minus]False# 解决坐标轴负号显示方框问题datapd.read_csv(rD:\Desktop\Postgraduate\PythonStudy\Python打卡训练营\Python打卡训练营\python60-days-challenge-master\heart.csv)print(data.info())col_map{age:年龄,sex:性别,cp:胸痛类型,trestbps:静息血压,chol:血清胆固醇,fbs:空腹血糖是否120mg/dl,restecg:静息心电图结果,thalach:最大心率,exang:运动是否诱发心绞痛,oldpeak:ST段压低程度,slope:ST段峰值斜率,ca:荧光染色血管数量,thal:地中海贫血,target:是否患心脏病}data.rename(columnscol_map, inplaceTrue)print(data.head())discrete_cols[性别,胸痛类型,空腹血糖是否120mg/dl,静息心电图结果,运动是否诱发心绞痛,ST段峰值斜率,荧光染色血管数量,地中海贫血]target_col[是否患心脏病]continuous_cols[]continuous_cols[colforcolindata.columnsifcolnotindiscrete_colstarget_col]# 1. 划分特征标签 固定种子拆分数据集 # 提取特征与标签标签转为一维数组避免API警告Xdata.drop(columnstarget_col)ydata[target_col].values.ravel()# 固定随机种子42分层抽样保证训练/测试集类别比例一致X_train, X_test, y_train, y_testtrain_test_split(X, y, test_size0.2, random_state42, stratifyy)print(f训练集样本量{len(X_train)}测试集样本量{len(X_test)})# 2. 连续特征IQR异常值处理缩尾法不丢失样本 # 仅用训练集统计分位数再应用到测试集杜绝数据泄露defiqr_winsorize(train_df, test_df, cols_list):train_dftrain_df.copy()test_dftest_df.copy()forcolincols_list:Q1train_df[col].quantile(0.25)Q3train_df[col].quantile(0.75)IQRQ3-Q1upper_boundQ31.5*IQRlower_boundQ1-1.5*IQR# 超出上下限的值截断到边界即箱线图缩尾处理train_df[col]train_df[col].clip(lowerlower_bound, upperupper_bound)test_df[col]test_df[col].clip(lowerlower_bound, upperupper_bound)returntrain_df, test_dfX_train, X_testiqr_winsorize(X_train, X_test, continuous_cols)print(连续特征IQR异常值缩尾处理完成)# 3. 连续特征标准化SVM/KNN/LR对量纲敏感树模型无影响 scalerStandardScaler()# 仅对连续特征标准化离散分类特征保持原值X_train[continuous_cols]scaler.fit_transform(X_train[continuous_cols])X_test[continuous_cols]scaler.transform(X_test[continuous_cols])# 4. 定义8个对比模型 models{SVM: SVC(random_state42),KNN: KNeighborsClassifier(),逻辑回归: LogisticRegression(random_state42, max_iter1000),朴素贝叶斯: GaussianNB(),决策树: DecisionTreeClassifier(random_state42),随机森林: RandomForestClassifier(random_state42),XGBoost: XGBClassifier(random_state42, use_label_encoderFalse, eval_metriclogloss),LightGBM: LGBMClassifier(random_state42, verbose-1)}# 5. 交叉验证 模型训练 指标计算 result_list[]# 存储评估指标cm_dict{}# 存储混淆矩阵label_names[无心脏病,有心脏病]# 0无病1患病print(\n*60)print(各模型5折交叉验证训练集加权F1与测试集结果)print(*60)formodel_name, modelinmodels.items():# 训练集5折交叉验证评估指标为加权F1cv_f1cross_val_score(model, X_train, y_train, cv5, scoringf1_weighted).mean()# 全量训练集拟合模型model.fit(X_train, y_train)y_predmodel.predict(X_test)# 计算测试集四大核心指标accaccuracy_score(y_test, y_pred)precisionprecision_score(y_test, y_pred, averageweighted)recallrecall_score(y_test, y_pred, averageweighted)f1f1_score(y_test, y_pred, averageweighted)# 保存结果result_list.append({模型名称: model_name,交叉验证平均F1:round(cv_f1,4),测试集准确率:round(acc,4),测试集精确率:round(precision,4),测试集召回率:round(recall,4),测试集F1分数:round(f1,4)})cm_dict[model_name]confusion_matrix(y_test, y_pred)print(f{model_name:8s} | 交叉验证F1: {cv_f1:.4f} | 测试集F1: {f1:.4f})# 6. 评估指标对比表格按F1降序 result_dfpd.DataFrame(result_list).sort_values(by测试集F1分数, ascendingFalse).reset_index(dropTrue)print(\n*80)print(所有模型测试集评估指标汇总按F1分数从高到低排序)print(*80)print(result_df.to_string(indexFalse))# 7. 混淆矩阵总图2行4列子图 fig, axesplt.subplots(2,4, figsize(22,10))axesaxes.flatten()# 把二维数组展平方便循环遍历foridx, (name, cm)inenumerate(cm_dict.items()):sns.heatmap(cm, annotTrue, fmtd, cmapBlues, axaxes[idx],xticklabelslabel_names, yticklabelslabel_names,annot_kws{size:14})axes[idx].set_title(f{name} 混淆矩阵, fontsize14, pad10)axes[idx].set_xlabel(预测结果, fontsize12)axes[idx].set_ylabel(真实结果, fontsize12)plt.tight_layout()plt.savefig(os.path.join(save_dir,confusion_matrix_all.png), dpi300, bbox_inchestight)plt.show()# 8. 输出F1分数最高的模型 best_rowresult_df.iloc[0]print(\n*60)print(f✅ 测试集F1分数最高的模型{best_row[模型名称]})print(f 对应F1得分为{best_row[测试集F1分数]})print(f 交叉验证平均F1{best_row[交叉验证平均F1]})print(*60)# 补充各模型特征重要性/系数对比 # 提取特征名称列表feature_namesX_train.columns.tolist()# 1. 可输出特征重要性的模型树模型 逻辑回归importance_models{逻辑回归: models[逻辑回归],决策树: models[决策树],随机森林: models[随机森林],XGBoost: models[XGBoost],LightGBM: models[LightGBM]}# 2. 绘制特征重要性对比图2行3列fig, axesplt.subplots(2,3, figsize(24,14))axesaxes.flatten()foridx, (name, model)inenumerate(importance_models.items()):ifname逻辑回归:# 线性模型取系数绝对值作为重要性importancenp.abs(model.coef_[0])title_suffix系数绝对值else:# 树模型取feature_importances_importancemodel.feature_importances_title_suffix特征重要性# 按重要性降序排序sorted_idxnp.argsort(importance)[::-1]sorted_features[feature_names[i]foriinsorted_idx]sorted_valuesimportance[sorted_idx]# 绘制横向柱状图sns.barplot(xsorted_values, ysorted_features, axaxes[idx], paletteviridis)axes[idx].set_title(f{name} 特征贡献度{title_suffix}, fontsize14, pad10)axes[idx].set_xlabel(重要性数值, fontsize12)axes[idx].set_ylabel(特征名称, fontsize12)# 最后一个子图放SVM和KNN的说明无直接特征重要性axes[-1].axis(off)axes[-1].text(0.5,0.5,SVM / KNN / 朴素贝叶斯\n无原生特征重要性输出\nSVM可通过线性核系数查看\nKNN为距离投票无特征权重,hacenter, vacenter, fontsize14, linespacing2)axes[-1].set_title(无特征重要性的模型, fontsize14, pad10)plt.tight_layout()plt.savefig(os.path.join(save_dir,feature_importance_all.png), dpi300, bbox_inchestight)plt.show()