Python在糖尿病分类问题上寻找具有最佳 ROC AUC 分数和 PR AUC 分数(决策树、逻辑回归、KNN、SVM)

发布于:2025-04-14 ⋅ 阅读:(24) ⋅ 点赞:(0)

问题

我们建议您使用 4 种不同的算法来解决糖尿病数据集上的二元分类问题:

Decision Tree (1) Logistic Regression (2) KNN (3) SVC (4)
您的任务是找到具有最佳 ROC AUC 分数和 PR AUC 分数的算法。作为答案,请指出数字 a b,其中 a 是 ROC AUC 分数方面的最佳算法,b 是 PR AUC 分数方面的最佳算法。

例如,答案 43 将被解释如下:算法 4(SVM)在 roc_auc_score 方面是最好的,算法 3(KNN)在 pr_auc_score 方面是最好的。

选择默认设置作为参数。对于 KNN,选择 k=5。将随机状态设置为 42。分成训练和测试,参数 test_size=0.3。

不要忘记对数据进行额外的预处理,使用 StandardScaler 将其调整到单一比例。

注意

  1. 请注意,StandardScaler 可能会影响算法的结果。因此,我们建议使用它。

  2. 当我们将数据分成训练和测试时,我们必须明白所有算法都必须仅在训练上进行训练。训练期间不使用测试。而且,在现实生活中我们对测试根本就一无所知。因此,StandardScaler 应该仅在 X_train 上进行训练,并且只应对 X_test 进行变换(而不是 fit_transform)。

模板

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
"""
TODO: make additional imports here
TODO:在此处进行额外导入
"""

data = fetch_openml(data_id=42608)
X, y = data['data'].drop(columns='Outcome').values, data['data']['Outcome'].astype(int).values

X_train, x_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

"""
In the following part of code specify algorithms with their own parameters by yourself
在下面的代码部分中,您可以自己指定具有自己参数的算法
"""
tree = DecisionTreeClassifier()
lr = LogisticRegression()
knn = KNeighborsClassifier()
svm = SVC(probability=True)

"""
TODO: fit estimators and find best one
TODO:拟合估算器并找到最佳估算器
"""

解题思路

1. 导入必要的库

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

from sklearn.metrics import roc_auc_score, auc
from sklearn.metrics import precision_recall_curve
import numpy as np

这些库的作用分别为:

  • fetch_openml:从 OpenML 平台加载数据集。
  • train_test_split:把数据集划分成训练集和测试集。
  • KNeighborsClassifierLogisticRegressionDecisionTreeClassifierSVC:四种不同的机器学习分类算法。
  • StandardScaler:对数据进行标准化处理。
  • roc_auc_scoreaucprecision_recall_curve:用于计算评估指标。
  • numpy:用于数值计算。

2. 加载数据

data = fetch_openml(data_id=42608)
X, y = data['data'].drop(columns='Outcome').values, data['data']['Outcome'].astype(int).values
  • 借助 fetch_openml 加载 ID 为 42608 的数据集,把特征数据存于 X 中,目标变量存于 y 中,同时将目标变量转换为整数类型。
  • 特征数据 X
    • data['data'] 取出的是数据集的特征数据部分,这是一个 pandasDataFrame 对象。
    • drop(columns='Outcome') 会从特征数据中移除名为 Outcome 的列,因为 Outcome 通常代表目标变量。
    • .valuesDataFrame 转换为 NumPy 数组,这样更适合用于机器学习模型的输入。
  • 目标变量 y
    • data['data']['Outcome'] 提取出 Outcome 列的数据,它同样是一个 pandasSeries 对象。
    • .astype(int) 将目标变量的数据类型转换为整数类型。
    • .valuesSeries 转换为 NumPy 数组。

3. 划分训练集和测试集

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

使用 train_test_split 函数按 7:3 的比例将数据集划分为训练集和测试集,并且设置随机种子为 42 以保证结果的可重复性。

4. 数据预处理

scaler = StandardScaler() 
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
  • 利用 StandardScaler 对训练集和测试集的数据进行标准化处理,保证所有特征具有相同的尺度。(StandardScaler 是 sklearn 库中用于数据标准化的类,它可以将数据转换为均值为 0,标准差为 1 的标准正态分布。)
  • fit_transform 方法结合了 fittransform 两个步骤:
    • fit 方法:计算训练集的均值和标准差。具体来说,它会遍历训练集中的每个特征,计算其均值和标准差,这些统计信息会被存储在 scaler 对象中,后续用于对测试集进行转换。
    • transform 方法:使用计算得到的均值和标准差对训练集进行标准化处理。标准化的公式为:
      x s c a l e d = x − μ σ x_{scaled} = \frac{x - \mu}{\sigma} xscaled=σxμ
      其中, x x x 是原始数据, μ \mu μ 是均值, σ \sigma σ 是标准差。经过标准化处理后,每个特征的均值变为 0,标准差变为 1。
  • scaler.transform(X_test):这里只使用了 transform 方法,而没有再次使用 fit 方法。这是因为在机器学习中,我们必须使用训练集的统计信息(均值和标准差)来对测试集进行标准化处理,以保证训练集和测试集具有相同的尺度。如果对测试集也使用 fit_transform 方法,那么 scaler 会重新计算测试集的均值和标准差,这会导致训练集和测试集的尺度不一致,从而影响模型的性能。

5. 定义算法及其参数

tree = DecisionTreeClassifier(random_state=42)
lr = LogisticRegression(random_state=42, max_iter=1000)
knn = KNeighborsClassifier(n_neighbors=5)
svm = SVC(probability=True, random_state=42)

定义了四种分类算法,分别是决策树、逻辑回归、K 近邻和支持向量机,同时设置了相应的参数。

6. 存储算法和对应指标

algorithms = [tree, lr, knn, svm]
roc_aucs = []
pr_aucs = []

把四种算法存于 algorithms 列表中,并且创建两个空列表 roc_aucspr_aucs 用于存储每种算法的 ROC AUC 和 PR AUC 指标。

7. 训练模型并计算指标

for algorithm in algorithms:
    algorithm.fit(X_train, y_train)
    y_score = algorithm.predict_proba(X_test)[:, 1]

    # 计算ROC AUC
    roc_auc = roc_auc_score(y_test, y_score)
    roc_aucs.append(roc_auc)

    # 计算PR AUC
    precision, recall, _ = precision_recall_curve(y_test, y_score)
    pr_auc = auc(recall, precision)
    pr_aucs.append(pr_auc)
  • 通过循环依次对每种算法进行训练,接着预测测试集的概率得分,计算 ROC AUC 和 PR AUC 指标,并将结果分别存储在 roc_aucspr_aucs 列表中。
  • algorithm.fit(X_train, y_train):对当前算法进行训练,使用训练集的特征数据 X_train 和对应的目标变量 y_train 来学习特征和目标之间的关系。
  • algorithm.predict_proba(X_test)[:, 1]:使用训练好的模型对测试集 X_test 进行预测,得到每个样本属于正类的概率。[:, 1] 表示只取属于正类的概率值

8. 找出最佳算法

best_roc_algorithm = np.argmax(roc_aucs) + 1
best_pr_algorithm = np.argmax(pr_aucs) + 1

运用 np.argmax 函数找出 roc_aucspr_aucs 列表中最大值的索引,加 1 后得到对应的算法编号。

9. 输出结果

result = int(str(best_roc_algorithm) + str(best_pr_algorithm))
print(result)

把最佳 ROC AUC 算法编号和最佳 PR AUC 算法编号拼接成一个字符串,再转换为整数后输出。

代码

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

from sklearn.metrics import roc_auc_score, auc
from sklearn.metrics import precision_recall_curve
import numpy as np

# 加载数据
data = fetch_openml(data_id=42608)
X, y = data['data'].drop(columns='Outcome').values, data['data']['Outcome'].astype(int).values

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

# 数据预处理
scaler = StandardScaler() # 对数据进行标准化处理,确保所有特征具有相同的尺度。
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 定义算法及其参数
tree = DecisionTreeClassifier(random_state=42)
lr = LogisticRegression(random_state=42, max_iter=1000)
knn = KNeighborsClassifier(n_neighbors=5)
svm = SVC(probability=True, random_state=42)

# 存储算法和对应指标
algorithms = [tree, lr, knn, svm]
roc_aucs = []
pr_aucs = []

# 训练模型并计算指标
for algorithm in algorithms:
    algorithm.fit(X_train, y_train)
    y_score = algorithm.predict_proba(X_test)[:, 1]

    # 计算ROC AUC
    roc_auc = roc_auc_score(y_test, y_score)
    roc_aucs.append(roc_auc)

    # 计算PR AUC
    precision, recall, _ = precision_recall_curve(y_test, y_score)
    pr_auc = auc(recall, precision)
    pr_aucs.append(pr_auc)

# 找出最佳算法
best_roc_algorithm = np.argmax(roc_aucs) + 1
best_pr_algorithm = np.argmax(pr_aucs) + 1

# 输出结果
result = int(str(best_roc_algorithm) + str(best_pr_algorithm))
print(result)

输出:21