news 2026/3/7 9:18:57

Day16 ROC曲线和PR曲线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day16 ROC曲线和PR曲线

@浙大疏锦行

一、前置代码

# 先运行之前预处理好的代码 import pandas as pd import pandas as pd #用于数据处理和分析,可处理表格数据。 import numpy as np #用于数值计算,提供了高效的数组操作。 import matplotlib.pyplot as plt #用于绘制各种类型的图表 import seaborn as sns #基于matplotlib的高级绘图库,能绘制更美观的统计图形。 import warnings warnings.filterwarnings("ignore") # 设置中文字体(解决中文显示问题) plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体 plt.rcParams['axes.unicode_minus'] = False # 正常显示负号 data = pd.read_csv('E:\study\PythonStudy\python60-days-challenge-master\data.csv') #读取数据 # 先筛选字符串变量 discrete_features = data.select_dtypes(include=['object']).columns.tolist() # Home Ownership 标签编码 home_ownership_mapping = { 'Own Home': 1, 'Rent': 2, 'Have Mortgage': 3, 'Home Mortgage': 4 } data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping) # Years in current job 标签编码 years_in_job_mapping = { '< 1 year': 1, '1 year': 2, '2 years': 3, '3 years': 4, '4 years': 5, '5 years': 6, '6 years': 7, '7 years': 8, '8 years': 9, '9 years': 10, '10+ years': 11 } data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping) # Purpose 独热编码,记得需要将bool类型转换为数值 data = pd.get_dummies(data, columns=['Purpose']) data2 = pd.read_csv("E:\study\PythonStudy\python60-days-challenge-master\data.csv") # 重新读取数据,用来做列名对比 list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名 for i in data.columns: if i not in data2.columns: list_final.append(i) # 这里打印出来的就是独热编码后的特征名 for i in list_final: data[i] = data[i].astype(int) # 这里的i就是独热编码后的特征名 # Term 0 - 1 映射 term_mapping = { 'Short Term': 0, 'Long Term': 1 } data['Term'] = data['Term'].map(term_mapping) data.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列 continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist() #把筛选出来的列名转换成列表 # 连续特征用中位数补全 for feature in continuous_features: mode_value = data[feature].mode()[0] #获取该列的众数。 data[feature].fillna(mode_value, inplace=True) #用众数填充该列的缺失值,inplace=True表示直接在原数据上修改。 # 最开始也说了 很多调参函数自带交叉验证,甚至是必选的参数,你如果想要不交叉反而实现起来会麻烦很多 # 所以这里我们还是只划分一次数据集 from sklearn.model_selection import train_test_split X = data.drop(['Credit Default'], axis=1) # 特征,axis=1表示按列删除 y = data['Credit Default'] # 标签 # 按照8:2划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 80%训练集,20%测试集 from sklearn.ensemble import RandomForestClassifier #随机森林分类器 from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标 from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵 import warnings #用于忽略警告信息 warnings.filterwarnings("ignore") # 忽略所有警告信息 # --- 1. 默认参数的随机森林 --- # 评估基准模型,这里确实不需要验证集 print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---") rf_model = RandomForestClassifier(random_state=42) rf_model.fit(X_train, y_train) # 在训练集上训练 rf_pred = rf_model.predict(X_test) # 在测试集上预测 print("\n默认随机森林 在测试集上的分类报告:") print(classification_report(y_test, rf_pred)) print("默认随机森林 在测试集上的混淆矩阵:") print(confusion_matrix(y_test, rf_pred))

二、ROC曲线

from sklearn.metrics import roc_curve, auc import matplotlib.pyplot as plt # 预测测试集上的概率(注意:ROC曲线需要的是预测概率,而不是最终的类别预测) # predict_proba() 返回一个 n_samples x n_classes 的数组,我们需要正类(1)的概率,即第二列 rf_pred_proba = rf_model.predict_proba(X_test)[:, 1] # 1. 计算 ROC 曲线的 FPR 和 TPR # y_test 是真实标签,rf_pred_proba 是正类的预测概率 fpr, tpr, thresholds = roc_curve(y_test, rf_pred_proba) # 2. 计算 AUC (Area Under the Curve) roc_auc = auc(fpr, tpr) # 3. 绘制 ROC 曲线 plt.figure(figsize=(8, 6)) plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.4f)' % roc_auc) plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--', label='Random Guess') # 对角线 plt.xlim([0.0, 1.0]) # 设置 x 轴范围 plt.ylim([0.0, 1.05]) # 设置 y 轴范围,稍微超出 1.0 plt.xlabel('False Positive Rate (FPR)') # x 轴标签 plt.ylabel('True Positive Rate (TPR)') # y 轴标签 plt.title('Receiver Operating Characteristic (ROC) Curve') # 图表标题 plt.legend(loc="lower right") # 图例位置 plt.grid(True) # 显示网格 plt.show() print("\n模型在测试集上的 AUC (Area Under the Curve): %0.4f" % roc_auc) import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import roc_curve, auc # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False def plot_distribution_and_roc(mu_neg, mu_pos, title_prefix): # --- 1. 模拟数据 (完全沿用之前的逻辑) --- # 负样本分布 (好人,分数低) n_neg = 10000 neg_scores = np.random.normal(loc=mu_neg, scale=0.15, size=n_neg) # 正样本分布 (坏人,分数高) n_pos = 1000 pos_scores = np.random.normal(loc=mu_pos, scale=0.15, size=n_pos) # 合并 y_true = np.array([0] * n_neg + [1] * n_pos) y_scores = np.concatenate([neg_scores, pos_scores]) # 归一化 y_scores = (y_scores - y_scores.min()) / (y_scores.max() - y_scores.min()) # --- 2. 计算 ROC 曲线的关键差异点 --- # 这里的输入和 PR 曲线一模一样,但输出变成了 FPR 和 TPR fpr, tpr, thresholds = roc_curve(y_true, y_scores) roc_auc = auc(fpr, tpr) # --- 绘图 --- fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 5)) # === 左图:分布图 (保持不变) === ax1.hist(y_scores[y_true==0], bins=50, alpha=0.5, color='blue', label='负样本 (好人/蓝山)', density=True) ax1.hist(y_scores[y_true==1], bins=50, alpha=0.5, color='red', label='正样本 (坏人/红山)', density=True) ax1.set_title(f'{title_prefix}:预测分数分布 (重叠度)', fontsize=14) ax1.set_xlabel('预测概率 (阈值刀从右往左切)') ax1.set_ylabel('密度') ax1.legend() # === 右图:ROC 曲线 (核心变化) === # 绘制 ROC 曲线 ax2.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (AUC = {roc_auc:.2f})') # 绘制对角线 (随机猜测基准线) ax2.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--', label='随机猜测 (AUC=0.5)') # 填充曲线下面积 ax2.fill_between(fpr, tpr, color='darkorange', alpha=0.2) ax2.set_title(f'{title_prefix}:对应的 ROC 曲线', fontsize=14) ax2.set_xlabel('FPR (假正率 - 误伤的好人比例) -> 代价', fontsize=12) ax2.set_ylabel('TPR (真正率 - 抓到的坏人比例) -> 收益', fontsize=12) ax2.set_xlim([-0.02, 1.0]) ax2.set_ylim([0.0, 1.05]) ax2.legend(loc="lower right") ax2.grid(True) plt.show() # --- 运行对比 --- # 情况一:模型很差 (山峰严重重叠) # 逻辑:你想抓红球,必然会抓到一大把蓝球。 plot_distribution_and_roc(mu_neg=0.4, mu_pos=0.5, title_prefix="情况A:模型较差(山峰重叠)") # 情况二:模型很好 (山峰分得很开) # 逻辑:你可以先把红球抓干净,都还碰不到蓝球。 plot_distribution_and_roc(mu_neg=0.3, mu_pos=0.8, title_prefix="情况B:模型优秀(山峰分离)")

三、PR曲线

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/5 20:32:26

详细分析一下 国富论里里面 十一章 论 地租

《国富论》第十一章《论地租》&#xff08;Of the Rent of Land&#xff09;是亚当斯密对土地收入性质的系统性分析&#xff0c;属于其分配理论的重要组成部分。本章在斯密的理论体系中具有承上启下的作用&#xff0c;既延续了对生产要素报酬&#xff08;工资、利润、地租&…

作者头像 李华
网站建设 2026/3/6 17:46:13

现在 夸脱小麦 多少 盎司白银

根据当前的国际市场价格数据&#xff0c;1夸脱小麦约相当于0.24盎司白银。这个比例与您在《国富论》中读到的历史数据&#xff08;如14世纪约4盎司白银/夸脱&#xff09;相比&#xff0c;已经发生了巨大变化。下面是根据最新市场数据进行的计算和对比分析&#xff1a;&#x1f…

作者头像 李华
网站建设 2026/3/6 20:31:14

Java Web html 图书管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展&#xff0c;图书管理系统在图书馆、学校及企业中的应用日益广泛&#xff0c;传统的手工管理模式已无法满足高效、精准的管理需求。数字化图书管理系统能够实现图书信息的快速检索、借阅记录的自动化管理以及用户权限的精细化控制&#xff0c;极大地…

作者头像 李华
网站建设 2026/3/6 6:42:24

半光滑牛顿法非线性优化带35个测试函数 半光滑牛顿法求解非线性目标函数约束优化问题的MATLA...

半光滑牛顿法非线性优化带35个测试函数 半光滑牛顿法求解非线性目标函数约束优化问题的MATLAB自编源代码&#xff0c;不调用MATLAB优化库函数&#xff0c;每个函数开头有简单英语注释&#xff0c;求解速度比MATLAB自带优化库函数快。 目标函数支持非线性目标函数、二次型函数等…

作者头像 李华
网站建设 2026/3/6 18:19:01

C 标准库 - `<math.h>`

C 标准库 - <math.h> 引言 在 C 语言编程中,数学运算是一项基本且重要的操作。《math.h》头文件提供了丰富的数学函数,用于处理各种数学问题。本文将详细介绍 <math.h> 标准库中的函数、使用方法以及注意事项。 1. <math.h> 函数概述 <math.h> 头…

作者头像 李华
网站建设 2026/3/5 12:52:09

【AUTOSAR AP CorAUTOSAR AP 错误处理与返回值规范:ErrorCode / ErrorDomain / Result / Exception / Violation 的工程化选型

目录标题 AUTOSAR AP 错误处理与返回值规范:ErrorCode / ErrorDomain / Result / Exception / Violation 的工程化选型 1. 错误分类先行:把“失败”拆成 4 种语义 1.1 Error:可恢复、属于 API 的正常输出域 1.2 Violation:断言级失败、不可恢复 1.3 Corruption:系统资源被…

作者头像 李华