Machine Learning Mastery 不平衡数据教程(五)

原文:Machine Learning Mastery

协议:CC BY-NC-SA 4.0

大肠杆菌数据集的不平衡多类分类

原文:https://machinelearningmastery.com/imbalanced-multiclass-classification-with-the-e-coli-dataset/

最后更新于 2021 年 1 月 5 日

多类分类问题是指一个标签必须被预测,但是有两个以上的标签可以被预测。

这些都是具有挑战性的预测建模问题,因为一个模型学习问题需要足够数量的每个类的代表性例子。当每个类中的例子数量不平衡,或者偏向一个或几个类,而其他类的例子很少时,这就变得很有挑战性。

这类问题被称为不平衡多类分类问题,它们需要仔细设计评估指标和测试工具,并选择机器学习模型。大肠杆菌蛋白质定位位点数据集是探索不平衡多类分类挑战的标准数据集。

在本教程中,您将发现如何为不平衡的多类大肠杆菌数据集开发和评估模型。

完成本教程后,您将知道:

  • 如何加载和探索数据集,并为数据准备和模型选择产生想法。
  • 如何系统地评估一套具有强大测试工具的机器学习模型。
  • 如何拟合最终模型并使用它来预测特定示例的类标签。

用我的新书Python 不平衡分类启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2021 年 1 月更新:更新了 API 文档的链接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大肠杆菌数据集的不平衡多类分类
图片由马库斯提供,保留部分权利。

教程概述

本教程分为五个部分;它们是:

  1. 大肠杆菌数据集
  2. 浏览数据集
  3. 模型测试和基线结果
  4. 评估模型
    1. 评估机器学习算法
    2. 评估数据过采样
  5. 对新数据进行预测

大肠杆菌数据集

在这个项目中,我们将使用标准的不平衡机器学习数据集,称为“大肠杆菌”数据集,也称为“蛋白质定位位点”数据集。

该数据集描述了利用大肠杆菌蛋白质在细胞定位位点的氨基酸序列对其进行分类的问题。也就是说,根据蛋白质折叠前的化学成分来预测蛋白质如何与细胞结合。

该数据集归功于中井贤三,并由保罗·霍顿中井贤三在 1996 年发表的论文《预测蛋白质细胞定位位点的概率分类系统》中发展成目前的形式其中,他们达到了 81%的分类准确率。

336 个大肠杆菌蛋白被分为 8 类,准确率为 81%

——预测蛋白质细胞定位位点的概率分类系统,1996。

数据集由 336 个大肠杆菌蛋白质的例子组成,每个例子使用从蛋白质氨基酸序列计算的七个输入变量来描述。

忽略序列名称,输入特征描述如下:

  • mcg : McGeoch 的信号序列识别方法。
  • gvh :冯·海涅的信号序列识别方法。
  • lip :冯·海金氏信号肽酶 II 共有序列评分。
  • chg :预测脂蛋白的氮末端存在电荷。
  • aac :外膜和周质蛋白氨基酸含量判别分析得分。
  • ALM 1:ALOM 跨膜区预测项目得分。
  • alm2 :从序列中排除假定的可裂解信号区后的 ALOM 程序评分。

有八个类别描述如下:

  • cp :细胞质
  • im :内膜无信号序列
  • pp :周质
  • imU :内膜,不可分裂信号序列
  • om :外膜
  • omL :外膜脂蛋白
  • imL :内膜脂蛋白
  • imS :内膜,可裂解信号序列

各班级之间的范例分布不均衡,在某些情况下严重失衡。

例如,“ cp ”类有 143 个例子,而“ imL ”和“ imS ”类各只有两个例子。

接下来,让我们仔细看看数据。

浏览数据集

首先,下载并解压缩数据集,并将其保存在您当前的工作目录中,名称为“ ecoli.csv ”。

请注意,此版本的数据集删除了第一列(序列名称),因为它不包含建模的通用信息。

查看文件的内容。

文件的前几行应该如下所示:

0.49,0.29,0.48,0.50,0.56,0.24,0.35,cp
0.07,0.40,0.48,0.50,0.54,0.35,0.44,cp
0.56,0.40,0.48,0.50,0.49,0.37,0.46,cp
0.59,0.49,0.48,0.50,0.52,0.45,0.36,cp
0.23,0.32,0.48,0.50,0.55,0.25,0.35,cp
...

我们可以看到输入变量都是数字,类标签是字符串值,需要在建模之前进行标签编码。

可以使用 read_csv()熊猫函数将数据集加载为数据帧,指定文件的位置和没有标题行的事实。

...
# define the dataset location
filename = 'ecoli.csv'
# load the csv file as a data frame
dataframe = read_csv(filename, header=None)

加载后,我们可以通过打印数据框的形状来总结行数和列数。

...
# summarize the shape of the dataset
print(dataframe.shape)

接下来,我们可以为每个输入变量计算一个五位数的摘要。

...
# describe the dataset
set_option('precision', 3)
print(dataframe.describe())

最后,我们还可以使用 Counter 对象总结每个类中的示例数量。

...
# summarize the class distribution
target = dataframe.values[:,-1]
counter = Counter(target)
for k,v in counter.items():
	per = v / len(target) * 100
	print('Class=%s, Count=%d, Percentage=%.3f%%' % (k, v, per))

将这些联系在一起,下面列出了加载和汇总数据集的完整示例。

# load and summarize the dataset
from pandas import read_csv
from pandas import set_option
from collections import Counter
# define the dataset location
filename = 'ecoli.csv'
# load the csv file as a data frame
dataframe = read_csv(filename, header=None)
# summarize the shape of the dataset
print(dataframe.shape)
# describe the dataset
set_option('precision', 3)
print(dataframe.describe())
# summarize the class distribution
target = dataframe.values[:,-1]
counter = Counter(target)
for k,v in counter.items():
	per = v / len(target) * 100
	print('Class=%s, Count=%d, Percentage=%.3f%%' % (k, v, per))

运行该示例首先加载数据集并确认行数和列数,它们是 336 行、7 个输入变量和 1 个目标变量。

回顾每个变量的摘要,似乎变量已经居中,也就是说,移动到平均值为 0.5。看起来变量已经被标准化了,这意味着所有的值都在大约 0 到 1 的范围内;至少没有变量的值超出这个范围。

然后总结类别分布,确认每个类别的观测值存在严重偏差。我们可以看到“ cp ”类占优势,约占 42%的例子,少数类如“ imS ”、“ imL ”和“ omL ”约占数据集的 1%或更少。

可能没有足够的数据来概括这些少数群体。一种方法可能是简单地删除这些类的示例。

(336, 8)
             0        1        2        3        4        5        6
count  336.000  336.000  336.000  336.000  336.000  336.000  336.000
mean     0.500    0.500    0.495    0.501    0.500    0.500    0.500
std      0.195    0.148    0.088    0.027    0.122    0.216    0.209
min      0.000    0.160    0.480    0.500    0.000    0.030    0.000
25%      0.340    0.400    0.480    0.500    0.420    0.330    0.350
50%      0.500    0.470    0.480    0.500    0.495    0.455    0.430
75%      0.662    0.570    0.480    0.500    0.570    0.710    0.710
max      0.890    1.000    1.000    1.000    0.880    1.000    0.990

Class=cp, Count=143, Percentage=42.560%
Class=im, Count=77, Percentage=22.917%
Class=imS, Count=2, Percentage=0.595%
Class=imL, Count=2, Percentage=0.595%
Class=imU, Count=35, Percentage=10.417%
Class=om, Count=20, Percentage=5.952%
Class=omL, Count=5, Percentage=1.488%
Class=pp, Count=52, Percentage=15.476%

我们还可以通过为每个变量创建直方图来查看输入变量的分布。

下面列出了创建所有输入变量直方图的完整示例。

# create histograms of all variables
from pandas import read_csv
from matplotlib import pyplot
# define the dataset location
filename = 'ecoli.csv'
# load the csv file as a data frame
df = read_csv(filename, header=None)
# create a histogram plot of each variable
df.hist(bins=25)
# show the plot
pyplot.show()

我们可以看到,变量如 0、5 和 6 可能具有多模态分布。变量 2 和 3 可以具有二进制分布,而变量 1 和 4 可以具有类似于高斯分布

根据模型的选择,数据集可能会受益于标准化、规范化,也许还会受益于幂变换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大肠杆菌数据集中变量的直方图

现在我们已经回顾了数据集,让我们看看开发一个测试工具来评估候选模型。

模型测试和基线结果

k-fold 交叉验证程序对模型表现提供了一个良好的总体估计,至少与单个列车试验分割相比,不会过于乐观。我们将使用 k=5 ,这意味着每个折叠将包含大约 336/5 或大约 67 个示例。

分层意味着每个文件夹的目标是按类包含与整个训练数据集相同的混合示例。重复意味着评估过程将执行多次,以帮助避免侥幸结果,并更好地捕捉所选模型的方差。我们将使用三次重复。

这意味着单个模型将被拟合和评估 5 * 3 或 15 次,并且将报告这些运行的平均值和标准偏差。

这可以使用repeated stratifiedfoldSklearn 类来实现。

所有的课都同等重要。因此,在这种情况下,我们将使用分类准确率来评估模型。

首先,我们可以定义一个函数来加载数据集,并将输入变量分成输入和输出变量,并使用标签编码器来确保类标签按顺序编号。

# load the dataset
def 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

我们可以定义一个函数,使用分层重复的 5 重交叉验证来评估候选模型,然后返回一个在模型上为每次重复计算的分数列表。

下面的 evaluate_model() 函数实现了这一点。

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

然后我们可以调用 load_dataset() 函数加载并确认大肠杆菌数据集。

...
# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y = load_dataset(full_path)
# summarize the loaded dataset
print(X.shape, y.shape, Counter(y))

在这种情况下,我们将评估在所有情况下预测多数类的基线策略。

这可以通过使用 DummyClassifier 类并将“策略”设置为“最频繁”来自动实现,该策略将预测训练数据集中最常见的类(例如类’ cp ')。因此,鉴于这是训练数据集中最常见类别的分布,我们预计该模型将达到约 42%的分类准确率。

...
# define the reference model
model = DummyClassifier(strategy='most_frequent')

然后,我们可以通过调用我们的 evaluate_model() 函数来评估模型,并报告结果的平均值和标准差。

...
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

将所有这些结合在一起,下面列出了在大肠杆菌数据集上使用分类准确率评估基线模型的完整示例。

# baseline model and test harness for the ecoli dataset
from collections import Counter
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier

# load the dataset
def 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 model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y = load_dataset(full_path)
# summarize the loaded dataset
print(X.shape, y.shape, Counter(y))
# define the reference model
model = DummyClassifier(strategy='most_frequent')
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例首先加载数据集,并按照我们的预期正确地报告案例数为 336,以及类标签的分布。

然后使用重复分层的 k 倍交叉验证评估带有我们默认策略的Dummy 分类器,分类准确率的平均值和标准偏差报告为大约 42.6%。

(336, 7) (336,) Counter({0: 143, 1: 77, 7: 52, 4: 35, 5: 20, 6: 5, 3: 2, 2: 2})
Mean Accuracy: 0.426 (0.006)

模型评估期间会报告警告;例如:

Warning: The least populated class in y has only 2 members, which is too few. The minimum number of members in any class cannot be less than n_splits=5.

这是因为有些类没有足够数量的 5 重交叉验证示例,例如类“ imS ”和“ imL ”。

在这种情况下,我们将从数据集中移除这些示例。这可以通过更新 load_dataset() 来移除具有这些类的行来实现,例如四行。

# load the dataset
def load_dataset(full_path):
	# load the dataset as a numpy array
	df = read_csv(full_path, header=None)
	# remove rows for the minority classes
	df = df[df[7] != 'imS']
	df = df[df[7] != 'imL']
	# retrieve numpy array
	data = df.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

然后,我们可以重新运行该示例来建立分类准确性的基线。

下面列出了完整的示例。

# baseline model and test harness for the ecoli dataset
from collections import Counter
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier

# load the dataset
def load_dataset(full_path):
	# load the dataset as a numpy array
	df = read_csv(full_path, header=None)
	# remove rows for the minority classes
	df = df[df[7] != 'imS']
	df = df[df[7] != 'imL']
	# retrieve numpy array
	data = df.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 model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y = load_dataset(full_path)
# summarize the loaded dataset
print(X.shape, y.shape, Counter(y))
# define the reference model
model = DummyClassifier(strategy='most_frequent')
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例确认示例数量减少了四个,从 336 个减少到 332 个。

我们还可以看到班级数量从八个减少到六个(从 0 班到 5 班)。

表现的基线被确定为 43.1%。该分数提供了该数据集的基线,通过该基线可以比较所有其他分类算法。得分高于约 43.1%表示模型在此数据集上有技能,得分等于或低于此值表示模型在此数据集上没有技能。

(332, 7) (332,) Counter({0: 143, 1: 77, 5: 52, 2: 35, 3: 20, 4: 5})
Mean Accuracy: 0.431 (0.005)

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

评估模型

在本节中,我们将使用上一节中开发的测试工具来评估数据集上的一套不同技术。

报告的表现良好,但没有高度优化(例如,超参数没有调整)。

**你能做得更好吗?**如果你能用同样的测试装具达到更好的分类准确率,我很想听听。请在下面的评论中告诉我。

评估机器学习算法

让我们从评估数据集上的混合机器学习模型开始。

在数据集上抽查一套不同的非线性算法可能是一个好主意,以便快速找出哪些算法运行良好,值得进一步关注,哪些算法运行不佳。

我们将在大肠杆菌数据集上评估以下机器学习模型:

  • 线性判别分析
  • 支持向量机(SVM)
  • 袋装决策树
  • 随机森林
  • 额外树

我们将主要使用默认的模型超参数,除了集成算法中的树的数量,我们将设置为合理的默认值 1000。

我们将依次定义每个模型,并将它们添加到一个列表中,以便我们可以顺序评估它们。下面的 get_models() 函数定义了用于评估的模型列表,以及用于以后绘制结果的模型简称列表。

# define models to test
def get_models():
	models, names = list(), list()
	# LDA
	models.append(LinearDiscriminantAnalysis())
	names.append('LDA')
	# SVM
	models.append(LinearSVC())
	names.append('SVM')
	# Bagging
	models.append(BaggingClassifier(n_estimators=1000))
	names.append('BAG')
	# RF
	models.append(RandomForestClassifier(n_estimators=1000))
	names.append('RF')
	# ET
	models.append(ExtraTreesClassifier(n_estimators=1000))
	names.append('ET')
	return models, names

然后,我们可以依次列举模型列表,并对每个模型进行评估,存储分数供以后评估。

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

在运行结束时,我们可以将每个分数样本绘制成一个方框,并用相同的比例绘制晶须图,这样我们就可以直接比较分布。

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

下面列出了在大肠杆菌数据集上评估一套机器学习算法的完整示例。

# spot check machine learning algorithms on the ecoli dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.svm import LinearSVC
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import BaggingClassifier

# load the dataset
def load_dataset(full_path):
	# load the dataset as a numpy array
	df = read_csv(full_path, header=None)
	# remove rows for the minority classes
	df = df[df[7] != 'imS']
	df = df[df[7] != 'imL']
	# retrieve numpy array
	data = df.values
	# split into input and output elements
	X, y = data[:, :-1], data[:, -1]
	# label encode the target variable
	y = LabelEncoder().fit_transform(y)
	return X, y

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

# define models to test
def get_models():
	models, names = list(), list()
	# LDA
	models.append(LinearDiscriminantAnalysis())
	names.append('LDA')
	# SVM
	models.append(LinearSVC())
	names.append('SVM')
	# Bagging
	models.append(BaggingClassifier(n_estimators=1000))
	names.append('BAG')
	# RF
	models.append(RandomForestClassifier(n_estimators=1000))
	names.append('RF')
	# ET
	models.append(ExtraTreesClassifier(n_estimators=1000))
	names.append('ET')
	return models, names

# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y = load_dataset(full_path)
# define models
models, names = get_models()
results = list()
# evaluate each model
for i in range(len(models)):
	# evaluate the model and store results
	scores = evaluate_model(X, y, models[i])
	results.append(scores)
	# summarize performance
	print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))
# plot the results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例依次评估每个算法,并报告平均和标准偏差分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到所有测试的算法都有技巧,达到了高于默认的 43.1%的准确率。

结果表明,大多数算法在这个数据集上表现良好,决策树的集成表现最好,额外树达到 88%的准确率,随机森林达到 89.5%的准确率。

>LDA 0.886 (0.027)
>SVM 0.883 (0.027)
>BAG 0.851 (0.037)
>RF 0.895 (0.032)
>ET 0.880 (0.030)

创建一个图形,显示每个算法结果样本的一个方框和须图。方框显示中间 50%的数据,每个方框中间的橙色线显示样本的中值,每个方框中的绿色三角形显示样本的平均值。

我们可以看到,聚类在一起的决策树集合的分数分布与测试的其他算法是分开的。在大多数情况下,图中的平均值和中位数很接近,这表明分数的分布有些对称,这可能表明模型是稳定的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不平衡大肠杆菌数据集上机器学习模型的盒须图

评估数据过采样

由于许多类中的类如此之多,示例如此之少,数据集可能会受益于过采样。

我们可以测试适用于除多数类( cp )之外的所有类的 SMOTE 算法,从而提升表现。

一般来说,SMOTE 似乎不能帮助决策树的集成,因此我们将测试的算法集更改为以下内容:

  • 多项式逻辑回归
  • 线性判别分析
  • 支持向量机(SVM)
  • k 近邻(KNN)
  • 高斯过程

定义这些模型的 get_models() 函数的更新版本如下。

# define models to test
def get_models():
	models, names = list(), list()
	# LR
	models.append(LogisticRegression(solver='lbfgs', multi_class='multinomial'))
	names.append('LR')
	# LDA
	models.append(LinearDiscriminantAnalysis())
	names.append('LDA')
	# SVM
	models.append(LinearSVC())
	names.append('SVM')
	# KNN
	models.append(KNeighborsClassifier(n_neighbors=3))
	names.append('KNN')
	# GP
	models.append(GaussianProcessClassifier())
	names.append('GP')
	return models, names

我们可以使用不平衡学习库中的 SMOTE 实现和同一库中的管道首先将 SMOTE 应用于训练数据集,然后拟合给定的模型作为交叉验证过程的一部分。

SMOTE 将使用训练数据集中的 k 近邻合成新示例,其中默认情况下, k 设置为 5。

这对于我们数据集中的一些类来说太大了。因此,我们将尝试 2 的 k 值。

...
# create pipeline
steps = [('o', SMOTE(k_neighbors=2)), ('m', models[i])]
pipeline = Pipeline(steps=steps)
# evaluate the model and store results
scores = evaluate_model(X, y, pipeline)

综上所述,下面列出了在大肠杆菌数据集上使用 SMOTE 过采样的完整示例。

# spot check smote with machine learning algorithms on the ecoli dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.svm import LinearSVC
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neighbors import KNeighborsClassifier
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.linear_model import LogisticRegression
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE

# load the dataset
def load_dataset(full_path):
	# load the dataset as a numpy array
	df = read_csv(full_path, header=None)
	# remove rows for the minority classes
	df = df[df[7] != 'imS']
	df = df[df[7] != 'imL']
	# retrieve numpy array
	data = df.values
	# split into input and output elements
	X, y = data[:, :-1], data[:, -1]
	# label encode the target variable
	y = LabelEncoder().fit_transform(y)
	return X, y

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

# define models to test
def get_models():
	models, names = list(), list()
	# LR
	models.append(LogisticRegression(solver='lbfgs', multi_class='multinomial'))
	names.append('LR')
	# LDA
	models.append(LinearDiscriminantAnalysis())
	names.append('LDA')
	# SVM
	models.append(LinearSVC())
	names.append('SVM')
	# KNN
	models.append(KNeighborsClassifier(n_neighbors=3))
	names.append('KNN')
	# GP
	models.append(GaussianProcessClassifier())
	names.append('GP')
	return models, names

# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y = load_dataset(full_path)
# define models
models, names = get_models()
results = list()
# evaluate each model
for i in range(len(models)):
	# create pipeline
	steps = [('o', SMOTE(k_neighbors=2)), ('m', models[i])]
	pipeline = Pipeline(steps=steps)
	# evaluate the model and store results
	scores = evaluate_model(X, y, pipeline)
	results.append(scores)
	# summarize performance
	print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))
# plot the results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例依次评估每个算法,并报告平均和标准偏差分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,使用 SMOTE 的 LDA 导致了从 88.6%到大约 87.9%的小幅下降,而使用 SMOTE 的 SVM 看到了从大约 88.3%到大约 88.8%的小幅上升。

在这种情况下,使用 SMOTE 时,SVM 似乎也是表现最好的方法,尽管与上一节中的随机森林相比,它没有实现任何改进。

>LR 0.875 (0.024)
>LDA 0.879 (0.029)
>SVM 0.888 (0.025)
>KNN 0.835 (0.040)
>GP 0.876 (0.023)

为每个算法创建分类准确度分数的方框图和触须图。

我们可以看到,LDA 有许多表现异常值,90%的值都很高,这非常有趣。这可能表明,如果专注于丰富的课程,线性判别分析可以表现得更好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

非平衡大肠杆菌数据集上机器学习模型的 SMOTE 盒须图

既然我们已经看到了如何在这个数据集上评估模型,让我们看看如何使用最终模型来进行预测。

对新数据进行预测

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

我们将使用随机森林模型作为最终模型,该模型的分类准确率约为 89.5%。

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

...
# define model to evaluate
model = RandomForestClassifier(n_estimators=1000)

一旦定义好了,我们就可以在整个训练数据集中使用它。

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

一旦适合,我们可以通过调用 predict() 函数来使用它对新数据进行预测。这将返回每个示例的编码类标签。

然后我们可以使用标签编码器进行逆变换,得到字符串类标签。

例如:

...
# define a row of data
row = [...]
# predict the class label
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]

为了证明这一点,我们可以使用拟合模型对一些我们知道结果的情况下的标签进行一些预测。

下面列出了完整的示例。

# fit a model and make predictions for the on the ecoli dataset
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def load_dataset(full_path):
	# load the dataset as a numpy array
	df = read_csv(full_path, header=None)
	# remove rows for the minority classes
	df = df[df[7] != 'imS']
	df = df[df[7] != 'imL']
	# retrieve numpy array
	data = df.values
	# split into input and output elements
	X, y = data[:, :-1], data[:, -1]
	# label encode the target variable
	le = LabelEncoder()
	y = le.fit_transform(y)
	return X, y, le

# define the location of the dataset
full_path = 'ecoli.csv'
# load the dataset
X, y, le = load_dataset(full_path)
# define model to evaluate
model = RandomForestClassifier(n_estimators=1000)
# fit the model
model.fit(X, y)
# known class "cp"
row = [0.49,0.29,0.48,0.50,0.56,0.24,0.35]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected cp)' % (label))
# known class "im"
row = [0.06,0.61,0.48,0.50,0.49,0.92,0.37]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected im)' % (label))
# known class "imU"
row = [0.72,0.42,0.48,0.50,0.65,0.77,0.79]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected imU)' % (label))
# known class "om"
row = [0.78,0.68,0.48,0.50,0.83,0.40,0.29]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected om)' % (label))
# known class "omL"
row = [0.77,0.57,1.00,0.50,0.37,0.54,0.0]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected omL)' % (label))
# known class "pp"
row = [0.74,0.49,0.48,0.50,0.42,0.54,0.36]
yhat = model.predict([row])
label = le.inverse_transform(yhat)[0]
print('>Predicted=%s (expected pp)' % (label))

运行该示例首先在整个训练数据集上拟合模型。

然后,拟合模型用于预测从六个类别中的每一个类别中选取的一个示例的标签。

我们可以看到为每个选择的例子预测了正确的类标签。尽管如此,平均而言,我们预计 10 个预测中有 1 个是错误的,这些错误可能不会平均分布在各个班级。

>Predicted=cp (expected cp)
>Predicted=im (expected im)
>Predicted=imU (expected imU)
>Predicted=om (expected om)
>Predicted=omL (expected omL)
>Predicted=pp (expected pp)

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

报纸

蜜蜂

资料组

摘要

在本教程中,您发现了如何为不平衡的多类大肠杆菌数据集开发和评估模型。

具体来说,您了解到:

  • 如何加载和探索数据集,并为数据准备和模型选择产生想法。
  • 如何系统地评估一套具有强大测试工具的机器学习模型。
  • 如何拟合最终模型并使用它来预测特定示例的类标签。

你有什么问题吗?
在下面的评论中提问,我会尽力回答。

玻璃识别数据集的不平衡多类分类

原文:https://machinelearningmastery.com/imbalanced-multiclass-classification-with-the-glass-identification-dataset/

最后更新于 2020 年 8 月 21 日

多类分类问题是指一个标签必须被预测,但是有两个以上的标签可以被预测。

这些都是具有挑战性的预测建模问题,因为一个模型学习问题需要足够数量的每个类的代表性例子。当每个类中的例子数量不平衡,或者偏向一个或几个类,而其他类的例子很少时,这就变得很有挑战性。

这类问题被称为不平衡多类分类问题,它们需要仔细设计评估指标和测试工具,并选择机器学习模型。玻璃识别数据集是探索不平衡多类分类挑战的标准数据集。

在本教程中,您将发现如何为不平衡的多玻璃识别数据集开发和评估模型。

完成本教程后,您将知道:

  • 如何加载和探索数据集,并为数据准备和模型选择产生想法。
  • 如何系统地评估一套具有强大测试工具的机器学习模型。
  • 如何拟合最终模型并使用它来预测特定示例的类标签。

用我的新书Python 不平衡分类启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 更新君/2020 :增加了一个实现更好表现的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评估不平衡多玻璃识别数据集的模型
图片由莎拉·尼科尔斯提供,保留部分权利。

教程概述

本教程分为五个部分;它们是:

  1. 玻璃识别数据集
  2. 浏览数据集
  3. 模型测试和基线结果
  4. 评估模型
    1. 评估机器学习算法
    2. 改进的型号(新)
  5. 对新数据进行预测

玻璃识别数据集

在这个项目中,我们将使用一个标准的不平衡机器学习数据集,称为“玻璃识别”数据集,或简称为“玻璃

该数据集描述了玻璃的化学性质,并涉及使用玻璃样品的化学性质将其分类为六个类别之一。该数据集于 1987 年被记入维娜·斯皮勒名下。

忽略样本识别号,有九个输入变量总结了玻璃数据集的属性;它们是:

  • RI :折射率
  • na:钠
  • :镁
  • :铝
  • :硅
  • K :钾
  • :钙
  • :钡
  • :铁

化学成分以相应氧化物的重量百分比来测量。

列出了七种类型的玻璃;它们是:

  • 1 级:建筑窗户(彩车加工)
  • 2 级:建筑窗户(非浮法加工)
  • 3 级:车窗(浮法处理)
  • 4 级:车窗(非浮动加工)
  • 第 5 类:容器
  • 第 6 类:餐具
  • 7 级:大灯

浮法玻璃是指用来制作玻璃的工艺。

数据集中有 214 个观测值,每个类中的观测值数量不平衡。请注意,数据集中没有类别 4(非浮动处理的车窗)的示例。

  • 第 1 类 : 70 例
  • 第二类 : 76 例
  • 第三类 : 17 例
  • 第 4 类 : 0 例
  • 第 5 类 : 13 例
  • 第 6 类 : 9 例
  • 第 7 类 : 29 例

虽然有少数类,但在这个预测问题中,所有类都同等重要。

数据集可分为窗玻璃(1-4 类)和非窗玻璃(5-7 类)。窗玻璃有 163 个例子,非窗玻璃有 51 个例子。

  • 窗玻璃 : 163 个例子
  • 非窗玻璃 : 51 例

观察的另一个部分是浮法加工玻璃和非浮法加工玻璃,仅针对窗户玻璃。这种划分更加平衡。

  • 浮法玻璃 : 87 例
  • 非浮法玻璃 : 76 例

接下来,让我们仔细看看数据。

浏览数据集

首先,下载数据集并保存在您当前的工作目录中,名称为“ glass.csv ”。

请注意,此版本的数据集删除了第一个列(行)号,因为它不包含用于建模的通用信息。

查看文件的内容。

文件的前几行应该如下所示:

1.52101,13.64,4.49,1.10,71.78,0.06,8.75,0.00,0.00,1
1.51761,13.89,3.60,1.36,72.73,0.48,7.83,0.00,0.00,1
1.51618,13.53,3.55,1.54,72.99,0.39,7.78,0.00,0.00,1
1.51766,13.21,3.69,1.29,72.61,0.57,8.22,0.00,0.00,1
1.51742,13.27,3.62,1.24,73.08,0.55,8.07,0.00,0.00,1
...

我们可以看到输入变量是数字,类标签是整数,在最后一列。

所有的化学输入变量都有相同的单位,尽管第一个变量折射率有不同的单位。因此,一些建模算法可能需要数据缩放。

可以使用 read_csv()熊猫函数将数据集加载为数据帧,指定数据集的位置和没有标题行的事实。

...
# define the dataset location
filename = 'glass.csv'
# load the csv file as a data frame
dataframe = read_csv(filename, header=None)

加载后,我们可以通过打印数据框的形状来总结行数和列数。

...
# summarize the shape of the dataset
print(dataframe.shape)

我们还可以使用 Counter 对象总结每个类中的示例数量。

...
# summarize the class distribution
target = dataframe.values[:,-1]
counter = Counter(target)
for k,v in counter.items():
	per = v / len(target) * 100
	print('Class=%d, Count=%d, Percentage=%.3f%%' % (k, v, per))

将这些联系在一起,下面列出了加载和汇总数据集的完整示例。

# load and summarize the dataset
from pandas import read_csv
from collections import Counter
# define the dataset location
filename = 'glass.csv'
# load the csv file as a data frame
dataframe = read_csv(filename, header=None)
# summarize the shape of the dataset
print(dataframe.shape)
# summarize the class distribution
target = dataframe.values[:,-1]
counter = Counter(target)
for k,v in counter.items():
	per = v / len(target) * 100
	print('Class=%d, Count=%d, Percentage=%.3f%%' % (k, v, per))

运行该示例首先加载数据集并确认行数和列数,它们是 214 行、9 个输入变量和 1 个目标变量。

然后总结类别分布,确认每个类别的观测值存在严重偏差。

(214, 10)
Class=1, Count=70, Percentage=32.710%
Class=2, Count=76, Percentage=35.514%
Class=3, Count=17, Percentage=7.944%
Class=5, Count=13, Percentage=6.075%
Class=6, Count=9, Percentage=4.206%
Class=7, Count=29, Percentage=13.551%

我们还可以通过为每个变量创建直方图来查看输入变量的分布。

下面列出了创建所有变量直方图的完整示例。

# create histograms of all variables
from pandas import read_csv
from matplotlib import pyplot
# define the dataset location
filename = 'glass.csv'
# load the csv file as a data frame
df = read_csv(filename, header=None)
# create a histogram plot of each variable
df.hist()
# show the plot
pyplot.show()

我们可以看到,一些变量具有类似高斯分布,而其他变量似乎具有指数甚至双峰分布。

根据算法的选择,数据可能会受益于某些变量的标准化,或许还会受益于幂变换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

玻璃识别数据集中变量的直方图

现在我们已经回顾了数据集,让我们看看开发一个测试工具来评估候选模型。

模型测试和基线结果

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

k 倍交叉验证程序提供了一个良好的模型表现的总体估计,至少与单个列车测试分割相比,不会过于乐观。我们将使用 k=5,这意味着每个折叠将包含大约 214/5,或者大约 42 个示例。

分层意味着每个文件夹的目标是按类包含与整个训练数据集相同的混合示例。重复意味着评估过程将执行多次,以帮助避免侥幸结果,并更好地捕捉所选模型的方差。我们将使用三次重复。

这意味着单个模型将被拟合和评估 5 * 3 或 15 次,并且这些运行的平均值和标准偏差将被报告。

这可以使用repeated stratifiedfoldSklearn 类来实现。

所有的课都同等重要。少数类只占数据的 4%或 6%,但没有一个类在数据集中的优势超过 35%。

因此,在这种情况下,我们将使用分类准确率来评估模型。

首先,我们可以定义一个函数来加载数据集,并将输入变量分成输入和输出变量,并使用标签编码器来确保类标签从 0 到 5 按顺序编号。

# load the dataset
def 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

我们可以定义一个函数,使用分层重复的 5 重交叉验证来评估候选模型,然后返回在模型上为每次重复计算的分数列表。下面的 evaluate_model() 函数实现了这一点。

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

然后我们可以调用 load_dataset() 函数加载并确认玻璃标识数据集。

...
# define the location of the dataset
full_path = 'glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# summarize the loaded dataset
print(X.shape, y.shape, Counter(y))

在这种情况下,我们将评估在所有情况下预测多数类的基线策略。

这可以通过使用 DummyClassifier 类并将“策略”设置为“最频繁”来自动实现,这将预测训练数据集中最常见的类(例如,类 2)。

因此,鉴于这是训练数据集中最常见类别的分布,我们期望该模型达到大约 35%的分类准确率。

...
# define the reference model
model = DummyClassifier(strategy='most_frequent')

然后,我们可以通过调用我们的 evaluate_model() 函数来评估模型,并报告结果的平均值和标准差。

...
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

将所有这些结合起来,下面列出了使用分类准确率评估玻璃识别数据集基线模型的完整示例。

# baseline model and test harness for the glass identification dataset
from collections import Counter
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier

# load the dataset
def 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 model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define the location of the dataset
full_path = 'glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# summarize the loaded dataset
print(X.shape, y.shape, Counter(y))
# define the reference model
model = DummyClassifier(strategy='most_frequent')
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例首先加载数据集,并按照我们的预期正确地报告案例数为 214,以及类标签的分布。

然后使用重复的分层 k 倍交叉验证来评估带有我们默认策略的 DummyClassifier ,并且分类准确度的平均和标准偏差被报告为大约 35.5%。

该分数提供了该数据集的基线,通过该基线可以比较所有其他分类算法。达到大约 35.5%以上的分数表示模型在此数据集上有技能,达到或低于此值的分数表示模型在此数据集上没有技能。

(214, 9) (214,) Counter({1: 76, 0: 70, 5: 29, 2: 17, 3: 13, 4: 9})
Mean Accuracy: 0.355 (0.011)

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

评估模型

在本节中,我们将使用上一节中开发的测试工具来评估数据集上的一套不同技术。

报告的表现良好,但没有高度优化(例如,超参数没有调整)。

**你能做得更好吗?**如果你能用同样的测试装具达到更好的分类准确率,我很想听听。请在下面的评论中告诉我。

评估机器学习算法

让我们在数据集上评估机器学习模型的混合。

在数据集上抽查一套不同的非线性算法可能是一个好主意,以便快速找出哪些算法运行良好,值得进一步关注,哪些算法不运行。

我们将在玻璃数据集上评估以下机器学习模型:

  • 支持向量机(SVM)
  • k 近邻(KNN)
  • 袋装决策树
  • 随机森林
  • 额外树

我们将主要使用默认的模型超参数,除了集成算法中的树的数量,我们将设置为合理的默认值 1000。

我们将依次定义每个模型,并将它们添加到一个列表中,以便我们可以顺序评估它们。下面的 get_models() 函数定义了用于评估的模型列表,以及用于以后绘制结果的模型简称列表。

# define models to test
def get_models():
	models, names = list(), list()
	# SVM
	models.append(SVC(gamma='auto'))
	names.append('SVM')
	# KNN
	models.append(KNeighborsClassifier())
	names.append('KNN')
	# Bagging
	models.append(BaggingClassifier(n_estimators=1000))
	names.append('BAG')
	# RF
	models.append(RandomForestClassifier(n_estimators=1000))
	names.append('RF')
	# ET
	models.append(ExtraTreesClassifier(n_estimators=1000))
	names.append('ET')
	return models, names

然后,我们可以依次列举模型列表,并对每个模型进行评估,存储分数供以后评估。

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

在运行结束时,我们可以将每个分数样本绘制成一个方框,并用相同的比例绘制晶须图,这样我们就可以直接比较分布。

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

将所有这些结合起来,下面列出了在玻璃识别数据集上评估一套机器学习算法的完整示例。

# spot check machine learning algorithms on the glass identification dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import BaggingClassifier

# load the dataset
def 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 model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# SVM
	models.append(SVC(gamma='auto'))
	names.append('SVM')
	# KNN
	models.append(KNeighborsClassifier())
	names.append('KNN')
	# Bagging
	models.append(BaggingClassifier(n_estimators=1000))
	names.append('BAG')
	# RF
	models.append(RandomForestClassifier(n_estimators=1000))
	names.append('RF')
	# ET
	models.append(ExtraTreesClassifier(n_estimators=1000))
	names.append('ET')
	return models, names

# define the location of the dataset
full_path = 'glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define models
models, names = get_models()
results = list()
# evaluate each model
for i in range(len(models)):
	# evaluate the model and store results
	scores = evaluate_model(X, y, models[i])
	results.append(scores)
	# summarize performance
	print('>%s %.3f (%.3f)' % (names[i], mean(scores), std(scores)))
# plot the results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例依次评估每个算法,并报告平均和标准偏差分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到所有测试的算法都有技巧,达到了高于默认的 35.5%的准确率。

结果表明,决策树的集成在这个数据集上表现良好,也许随机森林表现最好,总体分类准确率约为 79.6%。

>SVM 0.669 (0.057)
>KNN 0.647 (0.055)
>BAG 0.767 (0.070)
>RF 0.796 (0.062)
>ET 0.776 (0.057)

创建一个图形,显示每个算法结果样本的一个方框和须图。方框显示中间 50%的数据,每个方框中间的橙色线显示样本的中值,每个方框中的绿色三角形显示样本的平均值。

我们可以看到,聚类在一起的决策树集合的分数分布与测试的其他算法是分开的。在大多数情况下,图中的平均值和中位数很接近,这表明分数的分布有些对称,这可能表明模型是稳定的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不平衡玻璃识别数据集上机器学习模型的盒须图

既然我们已经看到了如何在这个数据集上评估模型,让我们看看如何使用最终模型来进行预测。

改进的模型

本节列出了发现比上面列出的模型表现更好的模型,这些模型是在教程发布后添加的。

成本敏感型随机森林(80.8%)

发现具有自定义类权重的随机森林的成本敏感版本可以获得更好的表现。

# cost sensitive random forest with custom class weightings
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def 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
	y = LabelEncoder().fit_transform(y)
	return X, y

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

# define the location of the dataset
full_path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define the model
weights = {0:1.0, 1:1.0, 2:2.0, 3:2.0, 4:2.0, 5:2.0}
model = RandomForestClassifier(n_estimators=1000, class_weight=weights)
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例评估计法并报告平均值和标准偏差准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,模型达到了约 80.8%的准确率。

Mean Accuracy: 0.808 (0.059)

你能做得更好吗? 请在下面的评论中告诉我,如果我可以使用相同的测试线束复制结果,我会在这里添加您的模型。

对新数据进行预测

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

我们将使用随机森林模型作为最终模型,该模型的分类准确率约为 79%。

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

...
# define model to evaluate
model = RandomForestClassifier(n_estimators=1000)

一旦定义好了,我们就可以在整个训练数据集中使用它。

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

一旦适合,我们可以通过调用 predict() 函数来使用它对新数据进行预测。

这将返回每个示例的类标签。

例如:

...
# define a row of data
row = [...]
# predict the class label
yhat = model.predict([row])

为了证明这一点,我们可以使用拟合模型对一些我们知道结果的情况下的标签进行一些预测。

下面列出了完整的示例。

# fit a model and make predictions for the on the glass identification dataset
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def 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 dataset
full_path = 'glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define model to evaluate
model = RandomForestClassifier(n_estimators=1000)
# fit the model
model.fit(X, y)
# known class 0 (class=1 in the dataset)
row = [1.52101,13.64,4.49,1.10,71.78,0.06,8.75,0.00,0.00]
print('>Predicted=%d (expected 0)' % (model.predict([row])))
# known class 1 (class=2 in the dataset)
row = [1.51574,14.86,3.67,1.74,71.87,0.16,7.36,0.00,0.12]
print('>Predicted=%d (expected 1)' % (model.predict([row])))
# known class 2 (class=3 in the dataset)
row = [1.51769,13.65,3.66,1.11,72.77,0.11,8.60,0.00,0.00]
print('>Predicted=%d (expected 2)' % (model.predict([row])))
# known class 3 (class=5 in the dataset)
row = [1.51915,12.73,1.85,1.86,72.69,0.60,10.09,0.00,0.00]
print('>Predicted=%d (expected 3)' % (model.predict([row])))
# known class 4 (class=6 in the dataset)
row = [1.51115,17.38,0.00,0.34,75.41,0.00,6.65,0.00,0.00]
print('>Predicted=%d (expected 4)' % (model.predict([row])))
# known class 5 (class=7 in the dataset)
row = [1.51556,13.87,0.00,2.54,73.23,0.14,9.41,0.81,0.01]
print('>Predicted=%d (expected 5)' % (model.predict([row])))

运行该示例首先在整个训练数据集上拟合模型。

然后,拟合模型用于预测从六个类别中的每一个类别中选取的一个示例的标签。

我们可以看到为每个选择的例子预测了正确的类标签。然而,平均而言,我们预计五分之一的预测是错误的,这些错误可能不会在班级中平均分布。

>Predicted=0 (expected 0)
>Predicted=1 (expected 1)
>Predicted=2 (expected 2)
>Predicted=3 (expected 3)
>Predicted=4 (expected 4)
>Predicted=5 (expected 5)

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

蜜蜂

资料组

摘要

在本教程中,您发现了如何为不平衡的多玻璃识别数据集开发和评估模型。

具体来说,您了解到:

  • 如何加载和探索数据集,并为数据准备和模型选择产生想法。
  • 如何系统地评估一套具有强大测试工具的机器学习模型。
  • 如何拟合最终模型并使用它来预测特定示例的类标签。

你有什么问题吗?
在下面的评论中提问,我会尽力回答。

多类不平衡分类

原文:https://machinelearningmastery.com/multi-class-imbalanced-classification/

最后更新于 2021 年 1 月 5 日

不平衡分类是那些预测任务,其中示例在类标签上的分布不相等。

大多数不平衡分类的例子集中在二分类任务上,然而许多不平衡分类的工具和技术也直接支持多类分类问题。

在本教程中,您将发现如何在多类数据集上使用不平衡分类工具。

完成本教程后,您将知道:

  • 关于玻璃鉴定标准不平衡多类预测问题。
  • 如何使用 SMOTE 过采样进行不平衡多类分类?
  • 如何利用代价敏感学习进行不平衡多类分类?

用我的新书Python 不平衡分类启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

  • 2021 年 1 月更新:更新了 API 文档的链接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多类不平衡分类
图片由 istolethetv 提供,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. 玻璃多类别数据集
  2. 多类分类的过采样
  3. 面向多类分类的代价敏感学习

玻璃多类别数据集

在本教程中,我们将重点讨论标准不平衡多类分类问题,简称为“玻璃识别”或简称为“玻璃

该数据集描述了玻璃的化学性质,并涉及使用玻璃样品的化学性质将其分类为六个类别之一。该数据集于 1987 年被记入维娜·斯皮勒名下。

忽略样本识别号,有九个输入变量总结了玻璃数据集的属性;它们是:

  • 折射率
  • Na:钠
  • 镁:镁
  • 铝:铝
  • 硅:硅
  • 钾:钾
  • 钙:钙

化学成分以相应氧化物的重量百分比来测量。

列出了七种类型的玻璃;它们是:

  • 类别 1:构建窗口(浮动处理)
  • 类别 2:建筑窗户(非浮动处理)
  • 类别 3:车窗(浮动处理)
  • 第 4 类:车窗(非浮动处理)
  • 第 5 类:容器
  • 第 6 类:餐具
  • 第 7 类:前照灯

浮法玻璃是指用来制作玻璃的工艺。

数据集中有 214 个观测值,每个类中的观测值数量不平衡。请注意,数据集中没有类别 4(非浮动处理的车窗)的示例。

  • 第 1 类:70 个例子
  • 第二类:76 个例子
  • 第 3 课:17 个例子
  • 第 4 类:0 个例子
  • 第 5 类:13 个例子
  • 第 6 课:9 个例子
  • 第 7 课:29 个例子

虽然有少数类,但在这个预测问题中,所有类都同等重要。

数据集可分为窗玻璃(1-4 类)和非窗玻璃(5-7 类)。窗玻璃有 163 个例子,非窗玻璃有 51 个例子。

  • 窗玻璃:163 个例子
  • 非窗户玻璃:51 个例子

观察的另一个部分是浮法加工玻璃和非浮法加工玻璃,仅针对窗户玻璃。这种划分更加平衡。

  • 浮法玻璃:87 个例子
  • 非浮法玻璃:76 个例子

您可以在此了解有关数据集的更多信息:

不需要下载数据集;我们将自动下载它作为工作示例的一部分。

下面是前几行数据的示例。

1.52101,13.64,4.49,1.10,71.78,0.06,8.75,0.00,0.00,1
1.51761,13.89,3.60,1.36,72.73,0.48,7.83,0.00,0.00,1
1.51618,13.53,3.55,1.54,72.99,0.39,7.78,0.00,0.00,1
1.51766,13.21,3.69,1.29,72.61,0.57,8.22,0.00,0.00,1
1.51742,13.27,3.62,1.24,73.08,0.55,8.07,0.00,0.00,1
...

我们可以看到所有的输入都是数字,最后一列中的目标变量是整数编码的类标签。

在本教程中,您可以了解有关如何将此数据集作为项目的一部分进行处理的更多信息:

现在我们已经熟悉了玻璃多类类别数据集,让我们探索如何使用标准的不平衡分类工具。

多类分类的过采样

过采样是指复制或合成少数类的新示例,使少数类中的示例数量更接近或匹配多数类中的示例数量。

也许最广泛使用的合成新例子的方法叫做合成少数过采样技术,简称 SMOTE。Nitesh Chawla 等人在 2002 年的论文中描述了这种技术,该论文以名为“ SMOTE:合成少数过采样技术的技术命名

您可以在教程中了解有关 SMOTE 的更多信息:

不平衡学习库提供了一个我们可以使用的 SMOTE 的实现,它与流行的 Sklearn 库兼容。

首先,必须安装库。我们可以使用 pip 安装它,如下所示:

sudo pip 安装不平衡-学习

我们可以通过打印已安装库的版本来确认安装成功:

# check version number
import imblearn
print(imblearn.__version__)

运行该示例将打印已安装库的版本号;例如:

0.6.2

在应用 SMOTE 之前,让我们首先加载数据集,并确认每个类中的示例数量。

# load and summarize the dataset
from pandas import read_csv
from collections import Counter
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
# define the dataset location
url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the csv file as a data frame
df = read_csv(url, header=None)
data = df.values
# split into input and output elements
X, y = data[:, :-1], data[:, -1]
# label encode the target variable
y = LabelEncoder().fit_transform(y)
# summarize distribution
counter = Counter(y)
for k,v in counter.items():
	per = v / len(y) * 100
	print('Class=%d, n=%d (%.3f%%)' % (k, v, per))
# plot the distribution
pyplot.bar(counter.keys(), counter.values())
pyplot.show()

运行该示例首先下载数据集,并将其分成训练集和测试集。

然后报告每个类中的行数,确认某些类(如 0 和 1)比其他类(如 3 和 4(小于 15))有更多的示例(超过 70 个)。

Class=0, n=70 (32.710%)
Class=1, n=76 (35.514%)
Class=2, n=17 (7.944%)
Class=3, n=13 (6.075%)
Class=4, n=9 (4.206%)
Class=5, n=29 (13.551%)

创建了一个条形图,提供数据集的类细分的可视化。

这给出了一个更清晰的概念,即类 0 和 1 比类 2、3、4 和 5 有更多的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

玻璃多类类别数据集中每个类的示例直方图

接下来,我们可以应用 SMOTE 对数据集进行过采样。

默认情况下,SMOTE 将对所有类进行过采样,以使其实例数量与实例最多的类相同。

在这种情况下,类 1 的例子最多,为 76 个,因此,SMOTE 将对所有类进行过采样,以获得 76 个例子。

下面列出了使用 SMOTE 对玻璃数据集进行过采样的完整示例。

# example of oversampling a multi-class classification dataset
from pandas import read_csv
from imblearn.over_sampling import SMOTE
from collections import Counter
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
# define the dataset location
url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the csv file as a data frame
df = read_csv(url, header=None)
data = df.values
# split into input and output elements
X, y = data[:, :-1], data[:, -1]
# label encode the target variable
y = LabelEncoder().fit_transform(y)
# transform the dataset
oversample = SMOTE()
X, y = oversample.fit_resample(X, y)
# summarize distribution
counter = Counter(y)
for k,v in counter.items():
	per = v / len(y) * 100
	print('Class=%d, n=%d (%.3f%%)' % (k, v, per))
# plot the distribution
pyplot.bar(counter.keys(), counter.values())
pyplot.show()

运行该示例首先加载数据集,并对其应用 SMOTE。

然后报告每个班级中的例子分布,确认每个班级现在有 76 个例子,正如我们所期望的。

Class=0, n=76 (16.667%)
Class=1, n=76 (16.667%)
Class=2, n=76 (16.667%)
Class=3, n=76 (16.667%)
Class=4, n=76 (16.667%)
Class=5, n=76 (16.667%)

还创建了类别分布的条形图,提供了一个强有力的视觉指示,表明所有类别现在都有相同数量的示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

默认 SMOTE 过采样后玻璃多类类别数据集中每个类的示例直方图

我们可以指定每个类中要过采样的示例数,而不是使用 SMOTE 的默认策略将所有类过采样为多数类中的示例数。

例如,我们可以在类 0 和 1 中对 100 个示例进行过采样,在其余类中对 200 个示例进行过采样。这可以通过创建一个字典来实现,该字典将类标签映射到每个类中所需的示例数量,然后通过 SMOTE 类的“ sampling_strategy ”参数来指定。

...
# transform the dataset
strategy = {0:100, 1:100, 2:200, 3:200, 4:200, 5:200}
oversample = SMOTE(sampling_strategy=strategy)
X, y = oversample.fit_resample(X, y)

综上所述,下面列出了对 SMOTE 使用定制过采样策略的完整示例。

# example of oversampling a multi-class classification dataset with a custom strategy
from pandas import read_csv
from imblearn.over_sampling import SMOTE
from collections import Counter
from matplotlib import pyplot
from sklearn.preprocessing import LabelEncoder
# define the dataset location
url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the csv file as a data frame
df = read_csv(url, header=None)
data = df.values
# split into input and output elements
X, y = data[:, :-1], data[:, -1]
# label encode the target variable
y = LabelEncoder().fit_transform(y)
# transform the dataset
strategy = {0:100, 1:100, 2:200, 3:200, 4:200, 5:200}
oversample = SMOTE(sampling_strategy=strategy)
X, y = oversample.fit_resample(X, y)
# summarize distribution
counter = Counter(y)
for k,v in counter.items():
	per = v / len(y) * 100
	print('Class=%d, n=%d (%.3f%%)' % (k, v, per))
# plot the distribution
pyplot.bar(counter.keys(), counter.values())
pyplot.show()

运行该示例会创建所需的采样并总结对数据集的影响,从而确认预期的结果。

Class=0, n=100 (10.000%)
Class=1, n=100 (10.000%)
Class=2, n=200 (20.000%)
Class=3, n=200 (20.000%)
Class=4, n=200 (20.000%)
Class=5, n=200 (20.000%)

注意:对于本示例,您可能会看到可以安全忽略的警告,例如:

UserWarning: After over-sampling, the number of samples (200) in class 5 will be larger than the number of samples in the majority class (class #1 -> 76)

还会创建一个类别分布的条形图,用于在数据采样后确认指定的类别分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

定制 SMOTE 过采样后玻璃多类类别数据集中每个类的示例直方图

:使用 SMOTE 这样的数据采样时,必须只应用于训练数据集,不能应用于整个数据集。我建议使用管道来确保在评估模型和使用模型进行预测时正确使用 SMOTE 方法。

在本教程中,您可以看到在管道中正确使用 SMOTE 的示例:

面向多类分类的代价敏感学习

大多数机器学习算法假设所有的类都有相同数量的例子。

多类不平衡分类就不是这样了。可以修改算法来改变执行学习的方式,以偏向于那些在训练数据集中具有较少示例的类。这通常被称为成本敏感学习。

有关成本敏感学习的更多信息,请参见教程:

Sklearn 中的 RandomForestClassifier 类通过“ class_weight ”参数支持对成本敏感的学习。

默认情况下,随机森林类为每个类分配相同的权重。

我们可以在玻璃不平衡多类类别数据集上评估默认随机森林类权重的分类准确率。

下面列出了完整的示例。

# baseline model and test harness for the glass identification dataset
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def 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 model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=1)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1)
	return scores

# define the location of the dataset
full_path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define the reference model
model = RandomForestClassifier(n_estimators=1000)
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例使用重复分层 k 倍交叉验证评估玻璃数据集上具有 1000 棵树的默认随机森林算法。

平均和标准偏差分类准确度在运行结束时报告。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到默认模型实现了大约 79.6%的分类准确率。

Mean Accuracy: 0.796 (0.047)

我们可以将“ class_weight ”参数指定为值“ balanced ”,该值将自动计算类权重,以确保每个类在模型训练期间获得相等的权重。

...
# define the model
model = RandomForestClassifier(n_estimators=1000, class_weight='balanced')

将这些联系在一起,完整的示例如下所示。

# cost sensitive random forest with default class weights
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def 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
	y = LabelEncoder().fit_transform(y)
	return X, y

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

# define the location of the dataset
full_path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define the model
model = RandomForestClassifier(n_estimators=1000, class_weight='balanced')
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例报告了成本敏感型随机森林在玻璃数据集上的平均和标准偏差分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到默认模型在分类准确率上比成本不敏感的算法版本有所提高,分类准确率为 80.2%,而不是 79.6%。

Mean Accuracy: 0.802 (0.044)

类权重”参数获取映射到类权重值的类标签字典。

我们可以用它来指定一个自定义的权重,比如有很多例子的类 0 和 1.0 的默认权重,以及其他类的双类权重 2.0。

...
# define the model
weights = {0:1.0, 1:1.0, 2:2.0, 3:2.0, 4:2.0, 5:2.0}
model = RandomForestClassifier(n_estimators=1000, class_weight=weights)

将这些联系在一起,下面列出了在玻璃多类不平衡分类问题上使用自定义类权重进行成本敏感学习的完整示例。

# cost sensitive random forest with custom class weightings
from numpy import mean
from numpy import std
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier

# load the dataset
def 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
	y = LabelEncoder().fit_transform(y)
	return X, y

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

# define the location of the dataset
full_path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/glass.csv'
# load the dataset
X, y = load_dataset(full_path)
# define the model
weights = {0:1.0, 1:1.0, 2:2.0, 3:2.0, 4:2.0, 5:2.0}
model = RandomForestClassifier(n_estimators=1000, class_weight=weights)
# evaluate the model
scores = evaluate_model(X, y, model)
# summarize performance
print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

运行该示例报告了具有自定义权重的玻璃数据集上随机森林的成本敏感版本的均值和标准差分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,我们实现了准确性的进一步提升,从平衡类权重的 80.2%提升到更偏向类权重的 80.8%。

Mean Accuracy: 0.808 (0.059)

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

相关教程

蜜蜂

摘要

在本教程中,您发现了如何对多类数据集使用不平衡分类工具。

具体来说,您了解到:

  • 关于玻璃鉴定标准不平衡多类预测问题。
  • 如何使用 SMOTE 过采样进行不平衡多类分类?
  • 如何利用代价敏感学习进行不平衡多类分类?

你有什么问题吗?
在下面的评论中提问,我会尽力回答。

每个不平衡分类度量的朴素分类器是什么?

原文:https://machinelearningmastery.com/naive-classifiers-imbalanced-classification-metrics/

最后更新于 2020 年 8 月 27 日

初学者常犯的一个错误是在没有建立表现基线的情况下将机器学习算法应用到问题中。

一个表现基线提供了一个最小分数,超过这个分数,一个模型被认为在数据集上有技能。它还为数据集上评估的所有模型提供了一个相对改进点。可以使用简单的分类器建立基线,例如为测试数据集中的所有示例预测一个类标签。

初学者犯的另一个常见错误是使用分类准确率作为具有不平衡类分布的问题的表现度量。即使预测所有情况下的多数类,这也会导致高准确度分数。相反,必须在一组分类度量中选择一个替代表现度量。

挑战在于表现的基线取决于表现指标的选择。因此,为了选择合适的朴素分类器来建立表现基线,可能需要对每个表现度量有深入的了解。

在本教程中,您将发现为每个不平衡的分类表现度量使用哪个朴素分类器。

完成本教程后,您将知道:

  • 评估不平衡分类问题的机器学习模型时要考虑的指标。
  • 可用于计算模型表现基线的简单分类策略。
  • 用于每个度量的朴素分类器,包括基本原理和演示结果的工作示例。

用我的新书Python 不平衡分类启动你的项目,包括分步教程和所有示例的 Python 源代码文件。

我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个不平衡分类度量的朴素分类器是什么?
土地管理局摄影,版权所有。

教程概述

本教程分为四个部分;它们是:

  1. 不平衡分类的度量
  2. 朴素分类模型
  3. 分类度量的朴素分类器
    1. 准确性的朴素分类器
    2. G 均值的朴素分类器
    3. F-测度的朴素分类器
    4. ROC AUC 的朴素分类器
    5. 精确召回 AUC 的朴素分类器
    6. 布瑞尔分数的朴素分类器
  4. 映射摘要

不平衡分类的度量

不平衡分类有许多标准可供选择。

选择度量标准可能是项目最重要的一步,因为选择错误的度量标准可能会导致优化和选择一个模型来解决与您实际想要解决的问题不同的问题。

因此,从几十或几百个最常用的度量中,可能有 5 个度量用于不平衡分类。它们如下:

评估预测类别标签的指标:

  • 准确性。
  • 平均。
  • F1-测量。
  • f 0.5-测量。
  • F2-测量。

评估预测概率的指标:

  • 曲线下面积。
  • 曲线下精确召回区域。
  • 布瑞尔分数。

有关如何计算每个指标的更多信息,请参见教程:

朴素分类模型

朴素分类器是一种没有逻辑的分类算法,它为类别数据集提供了表现基线。

为类别数据集建立表现基线非常重要。它在沙地上提供了一条线,通过这条线可以比较所有其他算法。得分低于朴素分类模型的算法在数据集上没有技能,而得分高于朴素分类模型的算法在数据集上有一些技能。

也许有五种不同的朴素分类方法可以用来建立数据集的表现基线。

在不平衡两类(二进制)分类问题的背景下解释,朴素分类方法如下:

  • 均匀随机猜测:等概率预测 0 或 1。
  • 先验随机猜测:预测数据集中与先验概率成正比的 0 或 1。
  • 多数类:预测 0。
  • 少数民族类:预测 1。
  • 类先验:预测每个类的先验概率。

这些可以使用 Sklearn 库的DummyCollector类来实现。

这个类提供了策略参数,允许使用不同的朴素分类器技术。例子包括:

  • 齐刷刷随机猜测:将“战略参数设置为“齐刷刷”。
  • 先验随机猜测:将“战略论证设置为“分层”。
  • 多数类:将“战略论证设置为“最 _ 频繁”。
  • 少数民族类:将“战略”参数设置为“常量”,将“常量参数设置为 1。
  • 类优先:将“策略参数设置为“优先”。

有关朴素分类器的更多信息,请参见教程:

分类度量的朴素分类器

我们已经确定,对于不平衡的分类问题,有许多不同的度量可供选择。

我们还发现,使用一个简单的分类器来确定一个新分类问题的表现基线是至关重要的。

挑战在于,每个分类指标都需要谨慎选择特定的幼稚分类策略,以实现适当的“无技能”表现。这可以并且应该使用每个度量的知识来选择,并且可以通过仔细的实验来确认。

在本节中,我们将为每个不平衡的分类度量合理地选择合适的朴素分类器,然后在合成的二进制类别数据集上用经验结果来确认选择。

合成数据集有 10,000 个示例,其中 99%属于多数类(负案例或类别标签 0),1%属于少数类(正案例或类别标签 1)。

使用三次重复的分层 10 倍交叉验证评估每个朴素分类器策略,并使用这些运行的平均值和标准偏差总结表现。

从度量到朴素分类器的映射可以用于下一个不平衡分类项目,经验结果证实了理论基础,并有助于为每个映射建立直觉。

让我们开始吧。

准确性的朴素分类器

分类准确率是正确预测的总数除以所做预测的总数。

分类准确率的合适的朴素分类器是预测所有情况下的多数类。这将最大限度地增加真实底片,最小限度地减少假底片。

我们可以通过一个工作示例来演示这一点,该示例比较了二分类问题上的每个朴素分类器策略。我们预计,预测多数类将导致该数据集的分类准确率约为 99%。

下面列出了完整的示例。

# compare naive classifiers with classification accuracy metric
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from matplotlib import pyplot

# evaluate a model
def 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='accuracy', cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的分类准确率。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,如我们所料,多数策略实现了 99%的最佳分类准确率。我们还可以看到,先前的策略获得了相同的结果,因为它预测在所有情况下大多数为 0.01(正类为 1%),这被映射到多数类标签 0。

>Uniform 0.501 (0.015)
>Stratified 0.980 (0.003)
>Majority 0.990 (0.000)
>Minority 0.010 (0.000)
>Prior 0.990 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

利用分类准确率评估朴素分类器策略的盒须图

G 均值的朴素分类器

几何平均值,或称 G-Mean,是敏感性和特异性评分的几何平均值

敏感性总结了阳性分类的预测程度,特异性总结了阴性分类的预测程度。

在多数派或少数派上表现得非常好将会以另一个阶级的最差表现为代价,这将导致零平均分数。

因此,最合适的朴素分类策略是以相等的概率预测每个类,这将为每个类提供一个正确预测的机会。

我们可以通过一个工作示例来演示这一点,该示例比较了二分类问题上的每个朴素分类器策略。我们预计,预测一个均匀随机的类标签将导致这个数据集上的 G 均值约为 0.5。

下面列出了完整的示例。

# compare naive classifiers with g-mean metric
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from imblearn.metrics import geometric_mean_score
from sklearn.metrics import make_scorer
from matplotlib import pyplot

# evaluate a model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
	# define the model evaluation the metric
	metric = make_scorer(geometric_mean_score)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring=metric, cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的 G 均值。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,正如预期的那样,一致随机的朴素分类器的 G 均值为 0.5,所有其他策略的 G 均值得分为 0。

>Uniform 0.507 (0.074)
>Stratified 0.021 (0.079)
>Majority 0.000 (0.000)
>Minority 0.000 (0.000)
>Prior 0.000 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 G 均值评估的朴素分类器策略的盒须图

F-测度的朴素分类器

F-测度(也称为 F1-分数)被计算为精确度和召回率之间的调和平均值。

准确率总结了分配给正类的属于正类的例子的分数,回忆总结了在所有可能做出的正类预测中,正类被预测得有多好。

做出有利于精确度的预测(例如预测少数族裔)也会导致召回率的下限。

因此,F-测度的天真策略是预测所有情况下的少数阶级。

我们可以通过一个工作示例来演示这一点,该示例比较了二分类问题上的每个朴素分类器策略。

当只预测该数据集的少数类时,F 度量最初并不明显。回忆会很完美,还是 1.0。准确率相当于少数类的先验,即 1%或 0.01。因此,F 测度是 1.0 和 0.01 之间的谐波平均值,约为 0.02。

下面列出了完整的示例。

# compare naive classifiers with f1-measure
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from matplotlib import pyplot

# evaluate a model
def 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='f1', cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的 ROC AUC。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在评估只预测少数类的幼稚分类器时,您可能会收到警告,因为没有预测到任何阳性案例。您将看到如下警告:

UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 due to no predicted samples.

在这种情况下,我们可以看到,预测少数民族类别会产生大约 0.02 的预期 f 测度。我们还可以看到,当使用统一和分层策略时,我们近似这个分数。

>Uniform 0.020 (0.007)
>Stratified 0.020 (0.040)
>Majority 0.000 (0.000)
>Minority 0.020 (0.000)
>Prior 0.000 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用 F-测度评估朴素分类器策略的盒须图

当使用 F0.5 和 F2 度量时,这种预测少数类的相同的朴素分类器策略也是合适的。

ROC AUC 的朴素分类器

ROC 曲线是不同概率阈值范围内假阳性率与真阳性率的关系图。

曲线下的 ROC 面积是 ROC 曲线下的积分或面积的近似值,总结了算法在概率阈值范围内的表现。

无技能模型的 ROC AUC 为 0.5,可以通过随机预测类别标签来实现,但与它们的基本比率成比例(例如,无辨别能力)。这就是分层方法。

预测一个常数值,如多数类或少数类,将导致一个无效的 ROC 曲线(如一个点),进而导致一个无效的 ROC AUC 分数。预测常数值的模型分数应该忽略。

下面列出了完整的示例。

# compare naive classifiers with roc auc
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from matplotlib import pyplot

# evaluate a model
def 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 test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的 ROC AUC。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,正如预期的那样,预测分层随机标签会产生 0.5 的最坏情况 ROC AUC。

>Uniform 0.500 (0.000)
>Stratified 0.506 (0.020)
>Majority 0.500 (0.000)
>Minority 0.500 (0.000)
>Prior 0.500 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 ROC AUC 评估的朴素分类器策略的盒须图

精确召回 AUC 的朴素分类器

准确率-召回曲线(或称 PR 曲线)是一系列不同概率阈值下召回率与准确率的关系图。

曲线下的准确率-召回区域是准确率-召回曲线下的积分或区域的近似值,总结了算法在概率阈值范围内的表现。

无技能模型的 PR AUC 与正类的基本比率相匹配,例如 0.01。这可以通过随机预测类别标签来实现,但是与它们的基本速率成比例(例如,没有辨别能力)。这就是分层方法。

预测一个常数值,如多数类或少数类,将导致无效的 PR 曲线(如一个点),进而导致无效的 PR AUC 分数。预测常数值的模型分数应该忽略。

下面列出了完整的示例。

# compare naive classifiers with precision-recall auc metric
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import auc
from sklearn.metrics import make_scorer
from matplotlib import pyplot

# calculate precision-recall area under curve
def pr_auc(y_true, probas_pred):
	# calculate precision-recall curve
	p, r, _ = precision_recall_curve(y_true, probas_pred)
	# calculate area under curve
	return auc(r, p)

# evaluate a model
def evaluate_model(X, y, model):
	# define evaluation procedure
	cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
	# define the model evaluation the metric
	metric = make_scorer(pr_auc, needs_proba=True)
	# evaluate model
	scores = cross_val_score(model, X, y, scoring=metric, cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的 PR AUC 分数。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

在这种情况下,我们可以看到,正如预期的那样,预测分层随机类别标签会导致最差情况下的 PR AUC 接近 0.01。

>Uniform 0.505 (0.000)
>Stratified 0.015 (0.037)
>Majority 0.505 (0.000)
>Minority 0.505 (0.000)
>Prior 0.505 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用查准率-召回率 AUC 评估的朴素分类器策略的盒须图

布瑞尔分数的朴素分类器

Brier score 计算预期概率和预测概率之间的均方误差。

布瑞尔分数的合适的朴素分类器是预测测试集中每个例子的类先验。对于涉及预测二项式分布的二分类问题,这将是 0 类的先验和 1 类的先验。

我们可以通过一个工作示例来演示这一点,该示例比较了二分类问题上的每个朴素分类器策略。

该模型可以预测所有情况下的概率[0.99,0.01]。我们预计这将导致少数类的均方误差接近先验值,例如,在这个数据集上为 0.01。这是因为大多数示例的二项式概率为 0.0,只有 1%的示例具有 1.0,这导致 1%的情况下最大误差为 0.01,或者 Brier 评分为 0.01。

下面列出了完整的示例。

# compare naive classifiers with brier score metric
from numpy import mean
from numpy import std
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.dummy import DummyClassifier
from matplotlib import pyplot

# evaluate a model
def 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='brier_score_loss', cv=cv, n_jobs=-1)
	return scores

# define models to test
def get_models():
	models, names = list(), list()
	# Uniformly Random Guess
	models.append(DummyClassifier(strategy='uniform'))
	names.append('Uniform')
	# Prior Random Guess
	models.append(DummyClassifier(strategy='stratified'))
	names.append('Stratified')
	# Majority Class: Predict 0
	models.append(DummyClassifier(strategy='most_frequent'))
	names.append('Majority')
	# Minority Class: Predict 1
	models.append(DummyClassifier(strategy='constant', constant=1))
	names.append('Minority')
	# Class Prior
	models.append(DummyClassifier(strategy='prior'))
	names.append('Prior')
	return models, names

# define dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
	n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=4)
# define models
models, names = get_models()
results = list()
# evaluate each model
for 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 results
pyplot.boxplot(results, labels=names, showmeans=True)
pyplot.show()

运行该示例会报告每个朴素分类器策略的 Brier 分数。

:考虑到算法或评估程序的随机性,或数值准确率的差异,您的结果可能会有所不同。考虑运行该示例几次,并比较平均结果。

Brier 分数被最小化,0.0 代表可能的最低分数。

因此,Sklearn 通过使分数为负来反转分数,因此每个朴素分类器的负平均 Brier 分数为负。因此,这个标志可以忽略。

不出所料,我们可以看到预测先验概率会得到最好的分数。我们还可以看到,预测多数类也会得到相同的最佳 Brier 分数。

>Uniform -0.250 (0.000)
>Stratified -0.020 (0.003)
>Majority -0.010 (0.000)
>Minority -0.990 (0.000)
>Prior -0.010 (0.000)

还创建了每个朴素分类器的方框图和触须图,允许直观地比较分数的分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Brier 评分评估的朴素分类器策略的盒须图

映射摘要

我们可以总结一下不平衡分类度量到朴素分类方法的映射。

这提供了一个查找表,您可以在下一个不平衡分类项目中查阅。

  • 准确度:预测多数类(0 类)。
  • G 均值:预测一个一致随机类。
  • F1-测量:预测少数类(1 类)。
  • f 0.5-测量:预测少数类(1 类)。
  • F2-测量:预测少数类(1 类)。
  • ROC AUC :预测一个分层随机类。
  • PR ROC :预测一个分层随机类。
  • Brier 评分:预测多数类优先。

进一步阅读

如果您想更深入地了解这个主题,本节将提供更多资源。

教程

蜜蜂

摘要

在本教程中,您发现了为每个不平衡的分类表现度量使用哪个简单的分类器。

具体来说,您了解到:

  • 评估不平衡分类问题的机器学习模型时要考虑的指标。
  • 可用于计算模型表现基线的简单分类策略。
  • 用于每个度量的朴素分类器,包括基本原理和演示结果的工作示例。

你有什么问题吗?
在下面的评论中提问,我会尽力回答。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值