机器学习中不平衡数据集分类模型示例:乳腺钼靶微钙化摄影数据集(二)

简介: 机器学习中不平衡数据集分类模型示例:乳腺钼靶微钙化摄影数据集(二)

模型测试与基准结果

我们将使用重复的分层k折交叉验证来评估候选模型。

k-fold交叉验证程序可以提供一个良好的模型性能总体估计值,与单次的留出验证相比,这种方法不容易带来过高的偏差。我们取k=10,这意味着每折将包含约11183/10或约1118个示例。

分层意味着每折的数据分布将与整体数据分布保持一致,即大约98%的无癌症对象与2%的有癌症对象。重复则意味着会进行多次重复实验,以帮助避免侥幸结果并更好地确定所选模型的方差。我们将重复进行三次实验。这意味着将对单个模型进行10×3即30次拟合和评估,并统计运行结果的平均值和标准差。这可以通过使用重复的scikit-learn库的RepeatedStratifiedKFold类来实现。

我们将使用roc_auc_score()函数计算的AUC来评估和比较模型效果。

我们可以定义一个函数来加载数据集,并将列拆分为输入和输出变量。我们将类标签重新编码为0和1。下面的load_dataset()函数实现了这一点。


# load the datasetdef load_dataset(full_path):  # load the dataset as a numpy array data = read_csv(full_path, header=None) # retrieve numpy array  data = data.values  # split into input and output elements  X, y = data[:, :-1], data[:, -1]  # label encode the target variable to have the classes 0 and 1  y = LabelEncoder().fit_transform(y) return X, y

然后,我们可以定义一个函数,用于在数据集上评估给定模型,并返回每折和与每次重复实验的AUC列表。

下面的evaluate_model()函数实现了这一点,将数据集和模型作为参数并返回分数列表。


# evaluate a modeldef evaluate_model(X, y, model):  # define evaluation procedure cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)  # evaluate model  scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)  return scores

最后,我们可以使用这个测试工具评估数据集上的基准模型。对每个样本进行随机预测的分类器的AUC期望值为0.5,这是该数据集性能的基线。这个随机预测的分类器一个所谓的“无效”分类器。

这可以通过scikit-learn库的DummyClassifier类来实现,将参数“strategy”设置为‘stratified‘。


...# define the reference modelmodel = DummyClassifier(strategy='stratified')

一旦模型评估完成,我们就可以直接获得AUC得分的平均值和标准差。


...# evaluate the modelscores = evaluate_model(X, y, model)# summarize performanceprint('Mean ROC AUC: %.3f (%.3f)' % (mean(scores), std(scores)))

将这几部分结合起来,下面列出了加载数据集、评估基准模型和报告分类器性能的完整示例。


# test harness and baseline model evaluationfrom collections import Counterfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.preprocessing import LabelEncoderfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.dummy import DummyClassifier
# load the datasetdef load_dataset(full_path):  # load the dataset as a numpy array data = read_csv(full_path, header=None) # retrieve numpy array  data = data.values  # split into input and output elements  X, y = data[:, :-1], data[:, -1]  # label encode the target variable to have the classes 0 and 1  y = LabelEncoder().fit_transform(y) return X, y
# evaluate a modeldef evaluate_model(X, y, model):  # define evaluation procedure cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)  # evaluate model  scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)  return scores
# define the location of the datasetfull_path = 'mammography.csv'# load the datasetX, y = load_dataset(full_path)# summarize the loaded datasetprint(X.shape, y.shape, Counter(y))# define the reference modelmodel = DummyClassifier(strategy='stratified')# evaluate the modelscores = evaluate_model(X, y, model)# summarize performanceprint('Mean ROC AUC: %.3f (%.3f)' % (mean(scores), std(scores)))

运行示例,首先加载并汇总数据集。我们可以看到加载的行数是正确的,并且有6个输入变量。重要的是,我们可以看到类标签具有到整数的正确映射,多数类记为0,少数类记为1,通常用于不平衡的二分类数据集。

接下来,报告AUC得分的平均值。

如预期的那样,无效分类器获得了平均AUC约为0.5的最坏性能。这为性能提供了一个基线,在这个基线之上,可以认为模型在这个数据集是有效的。


(11183, 6) (11183,) Counter({0: 10923, 1: 260})Mean ROC AUC: 0.503 (0.016)

现在我们有了测试工具和基准性能,我们可以开始在这个数据集上评估一些模型。

模型评估

在本节中,我们将使用上一节中开发的测试工具在数据集上评估不同的分类算法。

我们的目的是演示如何系统地解决问题,并展示某些专门为不平衡分类问题设计的算法的效果。我们获得的模型性能良好,但是仍未高度优化(例如,我们没有优化模型超参数)。

你能做得更好吗?我很乐意看到读者们能用同样的测试工具获得更好的AUC,欢迎在评论区留言。

机器学习算法评估

首先,我们在这个数据集上评估一些普通的机器学习模型。

我们可以在数据集上检测一系列不同的线性或非线性算法,这会很有用:这样我们可以快速了解到哪些算法在数据集上表现良好,而哪些算法则不值得我们关注。我们将在乳腺摄影数据集上评估以下机器学习模型:

  • 逻辑回归(LR)
  • 支持向量机(SVM)
  • Bagging算法(BAG)
  • 随机森林(RF)
  • 梯度提升机(GBM)

我们将主要使用默认的模型超参数,除了集成学习算法中的n_estimator,我们将其设置为1000。

我们将依次定义每个模型并将它们添加到列表中,以便可以按顺序对它们进行评估。我们定义下面的*get_models()*函数来评估模型效果并绘图。


# define models to testdef get_models():  models, names = list(), list()  # LR  models.append(LogisticRegression(solver='lbfgs')) names.append('LR')  # SVM models.append(SVC(gamma='scale')) names.append('SVM') # Bagging models.append(BaggingClassifier(n_estimators=1000)) names.append('BAG') # RF  models.append(RandomForestClassifier(n_estimators=1000))  names.append('RF')  # GBM models.append(GradientBoostingClassifier(n_estimators=1000))  names.append('GBM') return models, names

然后,我们可以依次列举模型列表中的每个模型并进行评估,记录AUC并存储在列表中以供以后绘制。


...# define modelsmodels, names = get_models()results = list()# evaluate each modelfor i in range(len(models)): # evaluate the model and store results  scores = evaluate_model(X, y, models[i])  results.append(scores)  # summarize and store print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))

在运行结束时,我们可以绘制模型表现的箱线图,以便直接比较模型表现。


# plot the resultspyplot.boxplot(results, labels=names, showmeans=True)pyplot.show()

将这些结合起来,下面列出了评估乳腺摄影数据集上一套机器学习算法的完整示例。


# spot check machine learning algorithms on the mammography datasetfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom matplotlib import pyplotfrom sklearn.preprocessing import LabelEncoderfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.linear_model import LogisticRegressionfrom sklearn.svm import SVCfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.ensemble import GradientBoostingClassifierfrom sklearn.ensemble import BaggingClassifier # load the datasetdef load_dataset(full_path): # load the dataset as a numpy array data = read_csv(full_path, header=None) # retrieve numpy array  data = data.values  # split into input and output elements  X, y = data[:, :-1], data[:, -1]  # label encode the target variable to have the classes 0 and 1  y = LabelEncoder().fit_transform(y) return X, y # evaluate a modeldef evaluate_model(X, y, model):  # define evaluation procedure cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)  # evaluate model  scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)  return scores # define models to testdef get_models():  models, names = list(), list()  # LR  models.append(LogisticRegression(solver='lbfgs')) names.append('LR')  # SVM models.append(SVC(gamma='scale')) names.append('SVM') # Bagging models.append(BaggingClassifier(n_estimators=1000)) names.append('BAG') # RF  models.append(RandomForestClassifier(n_estimators=1000))  names.append('RF')  # GBM models.append(GradientBoostingClassifier(n_estimators=1000))  names.append('GBM') return models, names # define the location of the datasetfull_path = 'mammography.csv'# load the datasetX, y = load_dataset(full_path)# define modelsmodels, names = get_models()results = list()# evaluate each modelfor i in range(len(models)):  # evaluate the model and store results  scores = evaluate_model(X, y, models[i])  results.append(scores)  # summarize and store print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))# plot the resultspyplot.boxplot(results, labels=names, showmeans=True)pyplot.show()

运行该示例以依次评估每个算法并报告AUC的平均值和标准差。由于学习算法的随机性,您的特定结果会有所不同;您可以考虑多次运行这一程序。

我们看到,我们评估的所有算法都是有效的,都实现了高于基准值0.5的AUC。

结果表明,基于决策树的集成学习算法(包括Bagging算法与随机森林)在这个数据集上表现得更好,其中随机森林表现最好,AUC约为0.950。

值得注意的是,我们获取的结果好于论文中描述的结果(0.93),虽然我们的评估流程略有不同。

评估结果对LR和支持向量机算法有点不公平,因为我们在拟合模型之前没有缩放输入变量。我们可以在下一节探讨这个问题。


>LR 0.919 (0.040)>SVM 0.880 (0.049)>BAG 0.941 (0.041)>RF 0.950 (0.036)>GBM 0.918 (0.037)

我们为每一个算法创建一个箱线图。箱线图中的“箱子”显示了数据的中间50%的分布范围,每个框中间的橙色线显示样本的中位数,每个框中的绿色三角形显示样本的平均值。

我们可以看到,BAG和RF的分布都很紧密,平均值和中位数也很接近,这意味着得分的分布可能为无偏的高斯分布,如稳定分布。

image.png

箱型图

现在我们已经有了一组很好的结果,让我们看看是否可以使用代价敏感的分类器来改进它们。

评估代价敏感算法

一些机器学习算法在拟合模型时可以更注意其中的某一类,这些模型被称为代价敏感的机器学习模型,通过指定与类分布成反比的代价值,它们可以用于不平衡分类。例如,对于多数类和少数类,它们的比例分别为98%和2%,因此我们可以指定少数类分类错误的代价为98,多数类分类错误的代价为2。

能够实现此功能的三种算法是:

  • 逻辑回归(LR)
  • 支持向量机(SVM)
  • 随机森林(RF)

这可以在scikit-learn中实现,方法是将*"class_weight"参数设置为“balanced”*,赋予这些算法代价敏感性。

例如,下面更新的get_models()函数定义了要在数据集上进行计算的三种算法的代价敏感版本。


# define models to testdef get_models():  models, names = list(), list()  # LR  models.append(LogisticRegression(solver='lbfgs', class_weight='balanced'))  names.append('LR')  # SVM models.append(SVC(gamma='scale', class_weight='balanced'))  names.append('SVM') # RF  models.append(RandomForestClassifier(n_estimators=1000))  names.append('RF')  return models, names

此外,在探索数据集时,我们注意到许多变量的数据分布呈指数分布。有时我们可以通过对每个变量使用幂变换来取得更好的数据分布。这将特别有助于LR和SVM算法,也可能有助于RF算法。

我们可以使用Pipeline类在交叉验证模型评估的每一折上中实现它。Pipeline的第一步定义PowerTransformer,然后应用于每一折的训练集和测试集;第二步则是我们正在评估的模型。然后可以使用evaluate_model()函数直接对Pipeline进行计算,示例代码如下:


...# defines pipeline stepssteps = [('p', PowerTransformer()), ('m',models[i])]# define pipelinepipeline = Pipeline(steps=steps)# evaluate the pipeline and store resultsscores = evaluate_model(X, y, pipeline)

把这一步结合在我们之前的代码中,下面列出了在乳腺摄影数据集上评估进行幂变换后的代价敏感型机器学习算法的完整示例。


# cost-sensitive machine learning algorithms on the mammography datasetfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom matplotlib import pyplotfrom sklearn.preprocessing import LabelEncoderfrom sklearn.preprocessing import PowerTransformerfrom sklearn.pipeline import Pipelinefrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.linear_model import LogisticRegressionfrom sklearn.svm import SVCfrom sklearn.ensemble import RandomForestClassifier # load the datasetdef load_dataset(full_path): # load the dataset as a numpy array data = read_csv(full_path, header=None) # retrieve numpy array  data = data.values  # split into input and output elements  X, y = data[:, :-1], data[:, -1]  # label encode the target variable to have the classes 0 and 1  y = LabelEncoder().fit_transform(y) return X, y # evaluate a modeldef evaluate_model(X, y, model):  # define evaluation procedure cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)  # evaluate model  scores = cross_val_score(model, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)  return scores # define models to testdef get_models():  models, names = list(), list()  # LR  models.append(LogisticRegression(solver='lbfgs', class_weight='balanced'))  names.append('LR')  # SVM models.append(SVC(gamma='scale', class_weight='balanced'))  names.append('SVM') # RF  models.append(RandomForestClassifier(n_estimators=1000))  names.append('RF')  return models, names # define the location of the datasetfull_path = 'mammography.csv'# load the datasetX, y = load_dataset(full_path)# define modelsmodels, names = get_models()results = list()# evaluate each modelfor i in range(len(models)):  # defines pipeline steps  steps = [('p', PowerTransformer()), ('m',models[i])]  # define pipeline pipeline = Pipeline(steps=steps)  # evaluate the pipeline and store results scores = evaluate_model(X, y, pipeline) results.append(scores)  # summarize and store print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))# plot the resultspyplot.boxplot(results, labels=names, showmeans=True)pyplot.show()

运行该示例以依次评估每个算法并报告AUC的平均值和标准差。由于学习算法的随机性,您的特定结果会有所不同;您可以考虑多次运行这一程序。

在这种情况下,我们可以看到,相比进行幂变换与添加代价敏感性之前,所有三个被测试的算法在AUC上都实现了提升。读者还可以试着在不进行幂变换的情况下进行重复实验,来探索算法性能提升的原因是幂变换,还是代价敏感算法,亦或是二者皆有。

在这种情况下,我们可以看到支持向量机取得了最好的性能,在本节和上一节中的性能优于RF,并且实现了大约0.957的平均AUC。


>LR 0.922 (0.036)>SVM 0.957 (0.024)>RF 0.951 (0.035)

我们绘制了箱线图来对比不同算法AUC的分布。与其它两种模型相比,支持向量机的分布更为紧凑。因此,它的性能可能是最稳定的,可以作为最终模型的一个良好候选。

image.png

代价敏感箱线图

接下来,让我们看看如何使用最终模型对新数据进行预测。

对新数据进行预测

在本节中,我们将拟合一个最终模型,并使用它对单行数据进行预测。

我们将使用代价敏感的支持向量机模型作为最终模型,在对模型进行拟合和预测之前对数据进行幂变换。使用pipeline将确保始终正确地对输入数据执行转换。

首先,我们可以将模型定义为pipeline。


...# define model to evaluatemodel = SVC(gamma='scale', class_weight='balanced')# power transform then fit modelpipeline = Pipeline(steps=[('t',PowerTransformer()), ('m',model)])

定义之后,我们可以在整个训练集上拟合模型。

...# fit the modelpipeline.fit(X, y)

拟合完成后,我们可以调用*predict()*函数来对新数据进行预测。函数将返回0(意味着没有癌症)或1(意味着癌症)。示例代码如下:


...# define a row of datarow = [...]# make predictionyhat = model.predict([row])

为了演示上述流程,我们使用拟合后的模型对我们已经知道癌症与否的部分数据进行预测。示例代码如下:


# fit a model and make predictions for the on the mammography datasetfrom pandas import read_csvfrom sklearn.preprocessing import LabelEncoderfrom sklearn.preprocessing import PowerTransformerfrom sklearn.svm import SVCfrom sklearn.pipeline import Pipeline # load the datasetdef load_dataset(full_path): # load the dataset as a numpy array data = read_csv(full_path, header=None) # retrieve numpy array  data = data.values  # split into input and output elements  X, y = data[:, :-1], data[:, -1]  # label encode the target variable to have the classes 0 and 1  y = LabelEncoder().fit_transform(y) return X, y # define the location of the datasetfull_path = 'mammography.csv'# load the datasetX, y = load_dataset(full_path)# define model to evaluatemodel = SVC(gamma='scale', class_weight='balanced')# power transform then fit modelpipeline = Pipeline(steps=[('t',PowerTransformer()), ('m',model)])# fit the modelpipeline.fit(X, y)# evaluate on some no cancer cases (known class 0)print('No Cancer:')data = [[0.23001961,5.0725783,-0.27606055,0.83244412,-0.37786573,0.4803223],  [0.15549112,-0.16939038,0.67065219,-0.85955255,-0.37786573,-0.94572324],  [-0.78441482,-0.44365372,5.6747053,-0.85955255,-0.37786573,-0.94572324]]for row in data:  # make prediction yhat = pipeline.predict([row])  # get the label label = yhat[0] # summarize print('>Predicted=%d (expected 0)' % (label))# evaluate on some cancer (known class 1)print('Cancer:')data = [[2.0158239,0.15353258,-0.32114211,2.1923706,-0.37786573,0.96176503],  [2.3191888,0.72860087,-0.50146835,-0.85955255,-0.37786573,-0.94572324], [0.19224721,-0.2003556,-0.230979,1.2003796,2.2620867,1.132403]]for row in data: # make prediction yhat = pipeline.predict([row])  # get the label label = yhat[0] # summarize print('>Predicted=%d (expected 1)' % (label))

运行该示例,首先会在整个培训数据集上拟合模型。接下来,从数据集中选择一些没有癌症的数据进行预测,我们可以看到所有的情况都被正确地预测了;然后我们输入一些癌症数据再对标签进行预测,正如我们所希望的那样,在这两种情况下数据的标签都得到了正确的预测。


No Cancer:>Predicted=0 (expected 0)>Predicted=0 (expected 0)>Predicted=0 (expected 0)Cancer:>Predicted=1 (expected 1)>Predicted=1 (expected 1)>Predicted=1 (expected 1)

延伸阅读

如果您想深入了解,本节将提供有关此主题的更多资源。

论文

  • Comparative Evaluation Of Pattern Recognition Techniques For Detection Of Microcalcifications In Mammography, 1993.
  • SMOTE: Synthetic Minority Over-sampling Technique, 2002.

API

  • sklearn.model_selection.RepeatedStratifiedKFold API.
  • sklearn.metrics.roc_auc_score API.
  • sklearn.dummy.DummyClassifier API.
  • sklearn.svm.SVC API.

数据集

  • Mammography Dataset.
  • Mammography Dataset Description

总结

在本教程中,您学习了如何开发和评估乳腺摄影数据集的不平衡分类模型。具体来说,您学到了:

  • 如何加载和探索数据集,并从中获得预处理数据与选择模型的灵感。
  • 如何使用代价敏感算法评估一组机器学习模型并提高其性能。
  • 如何拟合最终模型并使用它预测特定情况下的类标签。

还有什么问题吗?欢迎在评论区提出你的问题,我会尽力回答。

代码较多,需要pdf版本请关注后索取百度网盘下载地址

目录
相关文章
|
6月前
|
人工智能 自然语言处理 IDE
模型微调不再被代码难住!PAI和Qwen3-Coder加速AI开发新体验
通义千问 AI 编程大模型 Qwen3-Coder 正式开源,阿里云人工智能平台 PAI 支持云上一键部署 Qwen3-Coder 模型,并可在交互式建模环境中使用 Qwen3-Coder 模型。
1113 109
|
7月前
|
人工智能 自然语言处理 运维
【新模型速递】PAI-Model Gallery云上一键部署Kimi K2模型
月之暗面发布开源模型Kimi K2,采用MoE架构,参数达1T,激活参数32B,具备强代码能力及Agent任务处理优势。在编程、工具调用、数学推理测试中表现优异。阿里云PAI-Model Gallery已支持云端部署,提供企业级方案。
418 0
【新模型速递】PAI-Model Gallery云上一键部署Kimi K2模型
|
10月前
|
人工智能 JSON 算法
【解决方案】DistilQwen2.5-DS3-0324蒸馏小模型在PAI-ModelGallery的训练、评测、压缩及部署实践
DistilQwen 系列是阿里云人工智能平台 PAI 推出的蒸馏语言模型系列,包括 DistilQwen2、DistilQwen2.5、DistilQwen2.5-R1 等。本文详细介绍DistilQwen2.5-DS3-0324蒸馏小模型在PAI-ModelGallery的训练、评测、压缩及部署实践。
|
8月前
|
机器学习/深度学习 算法 安全
差分隐私机器学习:通过添加噪声让模型更安全,也更智能
本文探讨在敏感数据上应用差分隐私(DP)进行机器学习的挑战与实践。通过模拟DP-SGD算法,在模型训练中注入噪声以保护个人隐私。实验表明,该方法在保持71%准确率和0.79 AUC的同时,具备良好泛化能力,但也带来少数类预测精度下降的问题。研究强调差分隐私应作为模型设计的核心考量,而非事后补救,并提出在参数调优、扰动策略选择和隐私预算管理等方面的优化路径。
563 3
差分隐私机器学习:通过添加噪声让模型更安全,也更智能
|
7月前
|
人工智能 自然语言处理 运维
【新模型速递】PAI-Model Gallery云上一键部署gpt-oss系列模型
阿里云 PAI-Model Gallery 已同步接入 gpt-oss 系列模型,提供企业级部署方案。
|
8月前
|
机器学习/深度学习 人工智能 算法
Post-Training on PAI (4):模型微调SFT、DPO、GRPO
阿里云人工智能平台 PAI 提供了完整的模型微调产品能力,支持 监督微调(SFT)、偏好对齐(DPO)、强化学习微调(GRPO) 等业界常用模型微调训练方式。根据客户需求及代码能力层级,分别提供了 PAI-Model Gallery 一键微调、PAI-DSW Notebook 编程微调、PAI-DLC 容器化任务微调的全套产品功能。
|
9月前
|
存储 人工智能 运维
企业级MLOps落地:基于PAI-Studio构建自动化模型迭代流水线
本文深入解析MLOps落地的核心挑战与解决方案,涵盖技术断层分析、PAI-Studio平台选型、自动化流水线设计及实战构建,全面提升模型迭代效率与稳定性。
381 6
|
9月前
|
存储 机器学习/深度学习 自然语言处理
避坑指南:PAI-DLC分布式训练BERT模型的3大性能优化策略
本文基于电商搜索场景下的BERT-Large模型训练优化实践,针对数据供给、通信效率与计算资源利用率三大瓶颈,提出异步IO流水线、梯度压缩+拓扑感知、算子融合+混合精度等策略。实测在128卡V100集群上训练速度提升3.2倍,GPU利用率提升至89.3%,训练成本降低70%。适用于大规模分布式深度学习任务的性能调优。
454 3
|
8月前
|
机器学习/深度学习 分布式计算 Java
Java 大视界 -- Java 大数据机器学习模型在遥感图像土地利用分类中的优化与应用(199)
本文探讨了Java大数据与机器学习模型在遥感图像土地利用分类中的优化与应用。面对传统方法效率低、精度差的问题,结合Hadoop、Spark与深度学习框架,实现了高效、精准的分类。通过实际案例展示了Java在数据处理、模型融合与参数调优中的强大能力,推动遥感图像分类迈向新高度。

热门文章

最新文章

相关产品

  • 人工智能平台 PAI