第100+31步 ChatGPT学习:概率校准 Quantile Calibration

news2024/11/28 4:47:01

基于Python 3.9版本演示

一、写在前面

最近看了一篇在Lancet子刊《eClinicalMedicine》上发表的机器学习分类的文章:《Development of a novel dementia risk prediction model in the general population: A large, longitudinal, population-based machine-learning study》。

学到一种叫做“概率校准”的骚操作,顺手利用GPT系统学习学习。

文章中用的技术是:保序回归(Isotonic regression)。

为了体现举一反三,顺便问了GPT还有哪些方法也可以实现概率校准。它给我列举了很多,那么就一个一个学习吧。

这一期,介绍一个叫做 Quantile Calibration 的方法。

二、Quantile Calibration

Quantile Calibration基于分位数回归的思想,其核心是调整模型的预测分布,使得不同分位数上的预测值与真实值的匹配更加准确。具体来说,Quantile Calibration会根据训练数据集上不同分位数的预测误差来调整模型的输出,使得校准后的预测能够在给定的置信水平下更准确地覆盖真实值。

(1)主要步骤

1)训练模型: 首先,使用训练数据集训练一个机器学习模型,得到预测值和相应的置信区间。

2)计算分位数误差: 在验证集上计算模型的预测误差,特别是关注在不同分位数上的误差。例如,计算第10百分位数、第50百分位数(中位数)、第90百分位数的预测误差。

3)调整预测分布: 根据不同分位数上的误差,调整模型的预测分布。这可以通过调整预测的分位数值,使其与真实值的分布更加匹配。例如,如果第90百分位数的预测值系统性地低于真实值,那么可以将第90百分位数的预测值向上调整。

4)验证校准效果: 在独立的验证集或测试集上验证校准效果,确保校准后的模型能够在不同分位数上更准确地反映真实值的分布。

三、Quantile Calibration代码实现

下面,我编一个1比3的不太平衡的数据进行测试,对照组使用不进行校准的SVM模型,实验组就是加入校准的SVM模型,看看性能能够提高多少?

(1)不进行校准的SVM模型(默认参数)

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import confusion_matrix, roc_auc_score, roc_curve

# 加载数据
dataset = pd.read_csv('8PSMjianmo.csv')
X = dataset.iloc[:, 1:20].values
Y = dataset.iloc[:, 0].values

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.30, random_state=666)

# 标准化数据
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# 使用SVM分类器
classifier = SVC(kernel='linear', probability=True)
classifier.fit(X_train, y_train)

# 预测结果
y_pred = classifier.predict(X_test)
y_testprba = classifier.decision_function(X_test)

y_trainpred = classifier.predict(X_train)
y_trainprba = classifier.decision_function(X_train)

# 混淆矩阵
cm_test = confusion_matrix(y_test, y_pred)
cm_train = confusion_matrix(y_train, y_trainpred)
print(cm_train)
print(cm_test)

# 绘制测试集混淆矩阵
classes = list(set(y_test))
classes.sort()
plt.imshow(cm_test, cmap=plt.cm.Blues)
indices = range(len(cm_test))
plt.xticks(indices, classes)
plt.yticks(indices, classes)
plt.colorbar()
plt.xlabel('Predicted')
plt.ylabel('Actual')
for first_index in range(len(cm_test)):
    for second_index in range(len(cm_test[first_index])):
        plt.text(first_index, second_index, cm_test[first_index][second_index])

plt.show()

# 绘制训练集混淆矩阵
classes = list(set(y_train))
classes.sort()
plt.imshow(cm_train, cmap=plt.cm.Blues)
indices = range(len(cm_train))
plt.xticks(indices, classes)
plt.yticks(indices, classes)
plt.colorbar()
plt.xlabel('Predicted')
plt.ylabel('Actual')
for first_index in range(len(cm_train)):
    for second_index in range(len(cm_train[first_index])):
        plt.text(first_index, second_index, cm_train[first_index][second_index])

plt.show()

# 计算并打印性能参数
def calculate_metrics(cm, y_true, y_pred_prob):
    a = cm[0, 0]
    b = cm[0, 1]
    c = cm[1, 0]
    d = cm[1, 1]
    acc = (a + d) / (a + b + c + d)
    error_rate = 1 - acc
    sen = d / (d + c)
    sep = a / (a + b)
    precision = d / (b + d)
    F1 = (2 * precision * sen) / (precision + sen)
    MCC = (d * a - b * c) / (np.sqrt((d + b) * (d + c) * (a + b) * (a + c)))
    auc_score = roc_auc_score(y_true, y_pred_prob)
    
    metrics = {
        "Accuracy": acc,
        "Error Rate": error_rate,
        "Sensitivity": sen,
        "Specificity": sep,
        "Precision": precision,
        "F1 Score": F1,
        "MCC": MCC,
        "AUC": auc_score
    }
    return metrics

metrics_test = calculate_metrics(cm_test, y_test, y_testprba)
metrics_train = calculate_metrics(cm_train, y_train, y_trainprba)

print("Performance Metrics (Test):")
for key, value in metrics_test.items():
    print(f"{key}: {value:.4f}")

print("\nPerformance Metrics (Train):")
for key, value in metrics_train.items():
print(f"{key}: {value:.4f}")

结果输出:

记住这些个数字。

这个参数的SVM还没有LR好。

(2)进行校准的SVM模型(默认参数)

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import confusion_matrix, roc_auc_score, brier_score_loss, precision_score, f1_score, matthews_corrcoef
from sklearn.isotonic import IsotonicRegression

# 加载数据
dataset = pd.read_csv('8PSMjianmo.csv')
X = dataset.iloc[:, 1:20].values
Y = dataset.iloc[:, 0].values

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.30, random_state=666)

# 标准化数据
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# 使用SVM分类器
classifier = SVC(kernel='rbf', C=0.1, probability=True)
classifier.fit(X_train, y_train)

# 获取未校准的概率预测
y_train_probs = classifier.predict_proba(X_train)[:, 1]
y_test_probs = classifier.predict_proba(X_test)[:, 1]

# 使用Quantile Calibration
class QuantileCalibrator:
    def __init__(self):
        self.isotonic_regressor = IsotonicRegression(out_of_bounds='clip')

    def fit(self, probs, true_labels):
        self.isotonic_regressor.fit(probs, true_labels)

    def transform(self, probs):
        return self.isotonic_regressor.transform(probs)

# 训练Quantile Calibrator
quantile_cal = QuantileCalibrator()
quantile_cal.fit(y_train_probs, y_train)

# 进行校准
calibrated_train_probs = quantile_cal.transform(y_train_probs)
calibrated_test_probs = quantile_cal.transform(y_test_probs)

# 预测结果
y_train_pred = (calibrated_train_probs >= 0.5).astype(int)
y_test_pred = (calibrated_test_probs >= 0.5).astype(int)

# 混淆矩阵
cm_test = confusion_matrix(y_test, y_test_pred)
cm_train = confusion_matrix(y_train, y_train_pred)
print(cm_train)
print(cm_test)

# 绘制混淆矩阵函数
def plot_confusion_matrix(cm, classes, title='Confusion Matrix'):
    plt.imshow(cm, cmap=plt.cm.Blues)
    indices = range(len(cm))
    plt.xticks(indices, classes)
    plt.yticks(indices, classes)
    plt.colorbar()
    plt.xlabel('Predicted')
    plt.ylabel('Actual')
    for first_index in range(len(cm)):
        for second_index in range(len(cm[first_index])):
            plt.text(second_index, first_index, cm[first_index][second_index])
    plt.title(title)
    plt.show()

# 绘制测试集混淆矩阵
plot_confusion_matrix(cm_test, list(set(y_test)), 'Confusion Matrix (Test)')

# 绘制训练集混淆矩阵
plot_confusion_matrix(cm_train, list(set(y_train)), 'Confusion Matrix (Train)')

# 计算并打印性能参数
def calculate_metrics(cm, y_true, y_pred, y_pred_prob):
    a = cm[0, 0]
    b = cm[0, 1]
    c = cm[1, 0]
    d = cm[1, 1]
    acc = (a + d) / (a + b + c + d)
    error_rate = 1 - acc
    sen = d / (d + c) if (d + c) > 0 else 0
    sep = a / (a + b) if (a + b) > 0 else 0
    precision = precision_score(y_true, y_pred, zero_division=0)
    F1 = f1_score(y_true, y_pred, zero_division=0)
    MCC = matthews_corrcoef(y_true, y_pred)
    auc_score = roc_auc_score(y_true, y_pred_prob)
    brier_score = brier_score_loss(y_true, y_pred_prob)
    
    metrics = {
        "Accuracy": acc,
        "Error Rate": error_rate,
        "Sensitivity": sen,
        "Specificity": sep,
        "Precision": precision,
        "F1 Score": F1,
        "MCC": MCC,
        "AUC": auc_score,
        "Brier Score": brier_score
    }
    return metrics

metrics_test = calculate_metrics(cm_test, y_test, y_test_pred, calibrated_test_probs)
metrics_train = calculate_metrics(cm_train, y_train, y_train_pred, calibrated_train_probs)

print("Performance Metrics (Test):")
for key, value in metrics_test.items():
    print(f"{key}: {value:.4f}")

print("\nPerformance Metrics (Train):")
for key, value in metrics_train.items():
    print(f"{key}: {value:.4f}")

看看结果:

验证集大同小异,训练集到时提升了不少,过拟合了呗。

四、换个策略

参考那篇文章的策略:采用五折交叉验证来建立和评估模型,其中四折用于训练,一折用于评估,在训练集中,其中三折用于建立SVM模型,另一折采用Quantile Calibration概率校正,在训练集内部采用交叉验证对超参数进行调参。

代码:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV, KFold
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import confusion_matrix, roc_auc_score, brier_score_loss, precision_score, f1_score, matthews_corrcoef
from sklearn.calibration import calibration_curve, IsotonicRegression

# 加载数据
dataset = pd.read_csv('8PSMjianmo.csv')
X = dataset.iloc[:, 1:20].values
Y = dataset.iloc[:, 0].values

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.30, random_state=666)

# 标准化数据
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# 定义五折交叉验证
kf = KFold(n_splits=5, shuffle=True, random_state=666)
calibrated_probs = []
true_labels = []

class QuantileCalibrator:
    def __init__(self):
        self.isotonic_regressor = IsotonicRegression(out_of_bounds='clip')

    def fit(self, probs, true_labels):
        self.isotonic_regressor.fit(probs, true_labels)

    def transform(self, probs):
        return self.isotonic_regressor.transform(probs)

best_params = None  # 用于存储最优参数

for train_index, val_index in kf.split(X_train):
    X_train_fold, X_val_fold = X_train[train_index], X_train[val_index]
    y_train_fold, y_val_fold = y_train[train_index], y_train[val_index]
    
    # 内部三折交叉验证用于超参数调优
    inner_kf = KFold(n_splits=3, shuffle=True, random_state=666)
    param_grid = {'C': [0.01, 0.1, 1, 10, 100], 'kernel': ['rbf']}
    svm = SVC(probability=True)
    clf = GridSearchCV(svm, param_grid, cv=inner_kf, scoring='roc_auc')
    clf.fit(X_train_fold, y_train_fold)
    best_params = clf.best_params_
    
    # 使用最佳参数训练SVM
    classifier = SVC(kernel=best_params['kernel'], C=best_params['C'], probability=True)
    classifier.fit(X_train_fold, y_train_fold)
    
    # 获取未校准的概率预测
    y_val_fold_probs = classifier.predict_proba(X_val_fold)[:, 1]
    
    # Quantile校准
    quantile_cal = QuantileCalibrator()
    quantile_cal.fit(y_val_fold_probs, y_val_fold)
    calibrated_val_fold_probs = quantile_cal.transform(y_val_fold_probs)
    
    calibrated_probs.extend(calibrated_val_fold_probs)
    true_labels.extend(y_val_fold)

# 用于测试集的SVM模型训练和校准
classifier_final = SVC(kernel=best_params['kernel'], C=best_params['C'], probability=True)
classifier_final.fit(X_train, y_train)
y_test_probs = classifier_final.predict_proba(X_test)[:, 1]

# Quantile校准
quantile_cal_final = QuantileCalibrator()
quantile_cal_final.fit(y_test_probs, y_test)
calibrated_test_probs = quantile_cal_final.transform(y_test_probs)

# 预测结果
y_train_pred = (np.array(calibrated_probs) >= 0.5).astype(int)
y_test_pred = (calibrated_test_probs >= 0.5).astype(int)

# 混淆矩阵
cm_test = confusion_matrix(y_test, y_test_pred)
cm_train = confusion_matrix(true_labels, y_train_pred)
print("Training Confusion Matrix:\n", cm_train)
print("Testing Confusion Matrix:\n", cm_test)

# 绘制混淆矩阵函数
def plot_confusion_matrix(cm, classes, title='Confusion Matrix'):
    plt.imshow(cm, cmap=plt.cm.Blues)
    indices = range(len(cm))
    plt.xticks(indices, classes)
    plt.yticks(indices, classes)
    plt.colorbar()
    plt.xlabel('Predicted')
    plt.ylabel('Actual')
    for first_index in range(len(cm)):
        for second_index in range(len(cm[first_index])):
            plt.text(second_index, first_index, cm[first_index][second_index])
    plt.title(title)
    plt.show()

# 绘制测试集混淆矩阵
plot_confusion_matrix(cm_test, list(set(y_test)), 'Confusion Matrix (Test)')

# 绘制训练集混淆矩阵
plot_confusion_matrix(cm_train, list(set(true_labels)), 'Confusion Matrix (Train)')

# 计算并打印性能参数
def calculate_metrics(cm, y_true, y_pred, y_pred_prob):
    a = cm[0, 0]
    b = cm[0, 1]
    c = cm[1, 0]
    d = cm[1, 1]
    acc = (a + d) / (a + b + c + d)
    error_rate = 1 - acc
    sen = d / (d + c) if (d + c) > 0 else 0
    sep = a / (a + b) if (a + b) > 0 else 0
    precision = precision_score(y_true, y_pred, zero_division=0)
    F1 = f1_score(y_true, y_pred, zero_division=0)
    MCC = matthews_corrcoef(y_true, y_pred)
    auc_score = roc_auc_score(y_true, y_pred_prob)
    brier_score = brier_score_loss(y_true, y_pred_prob)
    
    metrics = {
        "Accuracy": acc,
        "Error Rate": error_rate,
        "Sensitivity": sen,
        "Specificity": sep,
        "Precision": precision,
        "F1 Score": F1,
        "MCC": MCC,
        "AUC": auc_score,
        "Brier Score": brier_score
    }
    return metrics

metrics_test = calculate_metrics(cm_test, y_test, y_test_pred, calibrated_test_probs)
metrics_train = calculate_metrics(cm_train, true_labels, y_train_pred, np.array(calibrated_probs))

print("Performance Metrics (Test):")
for key, value in metrics_test.items():
    print(f"{key}: {value:.4f}")

print("\nPerformance Metrics (Train):")
for key, value in metrics_train.items():
    print(f"{key}: {value:.4f}")

# 绘制校准曲线
def plot_calibration_curve(y_true, probs, title='Calibration Curve'):
    fraction_of_positives, mean_predicted_value = calibration_curve(y_true, probs, n_bins=10)
    plt.plot(mean_predicted_value, fraction_of_positives, "s-", label="Quantile Calibration")
    plt.plot([0, 1], [0, 1], "k--")
    plt.xlabel('Mean predicted value')
    plt.ylabel('Fraction of positives')
    plt.title(title)
    plt.legend()
    plt.show()

# 绘制校准曲线
plot_calibration_curve(y_test, calibrated_test_probs, title='Calibration Curve (Test)')
plot_calibration_curve(true_labels, np.array(calibrated_probs), title='Calibration Curve (Train)')

输出:

五、最后

各位可以去试一试在其他数据或者在其他机器学习分类模型中使用的效果。

数据不分享啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2235476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这款神器,运维绝杀 !!!

项目简介 CrowdSec 是一款开源的、基于社区协作的网络安全防护工具,它通过分析和共享IP信誉数据来对抗恶意行为。该软件不仅支持IPv6,而且相较于传统的Python实现,其采用Go语言编写,运行速度提升了60倍。CrowdSec 利用Grok模式解析…

Unreal5从入门到精通之如何在指定的显示器上运行UE程序

前言 我们有一个设备,是一个带双显示器的机柜,主显示器是一个小竖屏,可以触屏操作,大显示器是一个普通的横屏显示器。我们用这个机柜的原因就是可以摆脱鼠标和键盘,直接使用触屏操作,又可以在大屏观看,非常适合用于教学。 然后我们为这款机柜做了很多个VR项目,包括Uni…

R7:糖尿病预测模型优化探索

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、实验目的: 探索本案例是否还有进一步优化的空间 二、实验环境: 语言环境:python 3.8编译器:Jupyter notebo…

Django 框架:全方位技术分析

Django 框架:全方位技术分析 介绍 Django 是一个高级 Python Web 框架,鼓励快速开发和遵循设计的最佳实践。由经验丰富的开发人员打造,开源并可扩展,Django 旨在让构建 Web 应用更快、更轻松。 历史背景 Django 始于 2003 年,最初是 Lawrence Journal-World 报社的一个内…

如何用 ChatPaper.ai 打造完美的 AI 课堂笔记系统

作为学生,我们都遇到过这样的困扰:上课时记笔记太投入就听不进讲解,专注听讲又担心错过重要知识点。有了AI助手,这个问题就可以优雅地解决了。今天跟大家分享如何用ChatPaper.ai构建个人的智能课堂笔记系统。 为什么需要AI辅助记笔…

《手写Spring渐进式源码实践》实践笔记(第十六章 三级缓存解决循环依赖)

文章目录 第十六章 通过三级缓存解决循环依赖背景技术背景Spring循环依赖循环依赖类型三级缓存解决循环依赖 业务背景 目标设计一级缓存实现方案设计思路代码实现测试结果 三级缓存实现方案 实现代码结构类图实现步骤 测试事先准备属性配置文件测试用例测试结果: 总…

Java8新特性/java

1.lambda表达式 区别于js的箭头函数,python、cpp的lambda表达式,java8的lambda是一个匿名函数,java8运行把函数作为参数传递进方法中。 语法格式 (parameters) -> expression 或 (parameters...) ->{ statements; }实战 替代匿名内部类…

ubuntu双屏只显示一个屏幕另一个黑屏

简洁的结论: 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃,重新安装桌面安装不上,请IT帮忙,IT一番操作过后也表示…

Oracle OCP认证考试考点详解082系列15

题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 71. 第71题: 题目 解析及答案: 对于数据库,使用数据库配置助手(DBCA)可以执行…

为什么说SQLynx是链接国产数据库的最佳选择?

第一是因为SQLynx提供了广泛的国产数据库支持,除了市面上的主流数据库MYSQL、Oracle、PostgreSQL 、SQL Server、SQLite、MongoDB外、还支持达梦人大金仓等国产数据源! 近几年随着国产数据库市场的不断发展和成熟,越来越多的企业和机构开始选…

一个基于强大的 PostgreSQL 数据库构建的无代码数据库平台,快速构建应用程序,而无需编写一行代码(带私活源码)

随着企业和个人开发需求的不断增加,无代码平台成为了现代开发的重要组成部分,帮助那些没有技术背景的用户也能轻松创建和管理数据库应用程序。今天,我将向大家推荐一个非常出色的开源项目——Teable,它不仅支持无代码开发&#xf…

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的,对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务,但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…

计算网络信号

题目描述: 网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。注意:网络信号可以绕过阻隔物 array[m][n]的二维数组代表网格地图, array[i][j]0代表i行j列是空旷位置&…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件,支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定! 二、烧录说明 固件及工具打包下载地址: https://download.csdn.net/download/flyai…

数据结构与算法——Java实现 52.力扣98题——验证二叉搜索树

我将一直向前,带着你给我的淤青 —— 24.11.5 98. 验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的…

[mysql]DDL,DML综合案例,

综合案例 题目如下 目录 综合案例 ​编辑 ​编辑 # 1、创#1建数据库test01_library # 2、创建表 books,表结构如下: # 3、向books表中插入记录库存 # 4、将小说类型(novel)的书的价格都增加5。 # 5、将名称为EmmaT的书的价格改为40,并将…

书生实战营第四期-基础岛第三关-浦语提示词工程实践

一、基础任务 任务要求:利用对提示词的精确设计,引导语言模型正确回答出“strawberry”中有几个字母“r”。 1.提示词设计 你是字符计数专家,能够准确回答关于文本中特定字符数量的问题。 - 技能: - 📊 分析文本&…

国药准字生发产品有哪些?这几款不错

头秃不知道怎么选的朋友们看这,基本上市面上火的育发精华我都用了个遍了,陆陆续续也花了有大几w了,都是真金白银总结出来的,所以必须要给掉发人分享一些真正好用的育发产品,大家可以根据自己实际情况来选择。 1. 露卡菲…

构建基于 DCGM-Exporter, Node exporter,PROMETHEUS 和 GRAFANA 构建算力监控系统

目录 引言工具作用概述DCGM-ExporterNode exporterPROMETHEUSGRAFANA小结 部署单容器DCGM-ExporterNode exporterPROMETHEUSGRAFANANode exporterDCGM-Exporter 多容器Node exporterDCGM-ExporterDocker Compose 参考 引言 本文的是适用对象,是希望通过完全基于Doc…

Java入门14——动态绑定(含多态)

大家好,我们今天来学动态绑定和多态,话不多说,开始正题~ 但是要学动态绑定之前,我们要学习一下向上转型,方便后续更好地理解~ 一、向上转型 1.什么是向上转型 网上概念有很多,但其实通俗来讲&#xff0c…