注意
Go to the end 下载完整示例代码。
在人脸识别任务中基准过采样方法#
在这个面部识别示例中,使用了LFW(野外人脸)数据集中的两张人脸。为了通过使用过采样器来检查分类器输出质量的改进,几种实现的过采样方法与3NN分类器结合使用。
# Authors: Christos Aridas
# Guillaume Lemaitre <g.lemaitre58@gmail.com>
# License: MIT
print(__doc__)
import seaborn as sns
sns.set_context("poster")
加载数据集#
我们将使用一个包含已知人物图像的数据集,我们将构建一个模型来识别图像中的人物。我们将通过仅拍摄乔治·W·布什和比尔·克林顿的照片,将这个问题变成一个二元问题。
import numpy as np
from sklearn.datasets import fetch_lfw_people
data = fetch_lfw_people()
george_bush_id = 1871 # Photos of George W. Bush
bill_clinton_id = 531 # Photos of Bill Clinton
classes = [george_bush_id, bill_clinton_id]
classes_name = np.array(["B. Clinton", "G.W. Bush"], dtype=object)
mask_photos = np.isin(data.target, classes)
X, y = data.data[mask_photos], data.target[mask_photos]
y = (y == george_bush_id).astype(np.int8)
y = classes_name[y]
我们可以检查两个类别之间的比率。
import matplotlib.pyplot as plt
import pandas as pd
class_distribution = pd.Series(y).value_counts(normalize=True)
ax = class_distribution.plot.barh()
ax.set_title("Class distribution")
pos_label = class_distribution.idxmin()
plt.tight_layout()
print(f"The positive label considered as the minority class is {pos_label}")

The positive label considered as the minority class is B. Clinton
我们看到我们有一个不平衡的分类问题,大约95%的数据属于G.W. Bush类。
比较过采样方法#
我们将使用不同的过采样方法,并使用kNN分类器来检查我们是否能识别出这2位总统。评估将通过交叉验证进行,并且我们将绘制平均ROC曲线。
我们将创建不同的管道并对其进行评估。
from sklearn.neighbors import KNeighborsClassifier
from imblearn import FunctionSampler
from imblearn.over_sampling import ADASYN, SMOTE, RandomOverSampler
from imblearn.pipeline import make_pipeline
classifier = KNeighborsClassifier(n_neighbors=3)
pipeline = [
make_pipeline(FunctionSampler(), classifier),
make_pipeline(RandomOverSampler(random_state=42), classifier),
make_pipeline(ADASYN(random_state=42), classifier),
make_pipeline(SMOTE(random_state=42), classifier),
]
from sklearn.model_selection import StratifiedKFold
cv = StratifiedKFold(n_splits=3)
我们将使用由StratifiedKFold交叉验证提供的不同分割来计算每个管道的平均ROC曲线。
from sklearn.metrics import RocCurveDisplay, auc, roc_curve
disp = []
for model in pipeline:
# compute the mean fpr/tpr to get the mean ROC curve
mean_tpr, mean_fpr = 0.0, np.linspace(0, 1, 100)
for train, test in cv.split(X, y):
model.fit(X[train], y[train])
y_proba = model.predict_proba(X[test])
pos_label_idx = np.flatnonzero(model.classes_ == pos_label)[0]
fpr, tpr, thresholds = roc_curve(
y[test], y_proba[:, pos_label_idx], pos_label=pos_label
)
mean_tpr += np.interp(mean_fpr, fpr, tpr)
mean_tpr[0] = 0.0
mean_tpr /= cv.get_n_splits(X, y)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
# Create a display that we will reuse to make the aggregated plots for
# all methods
disp.append(
RocCurveDisplay(
fpr=mean_fpr,
tpr=mean_tpr,
roc_auc=mean_auc,
estimator_name=f"{model[0].__class__.__name__}",
)
)
在前一个单元格中,我们创建了不同的平均ROC曲线,并且可以在同一个图上绘制它们。
fig, ax = plt.subplots(figsize=(9, 9))
for d in disp:
d.plot(ax=ax, linestyle="--")
ax.plot([0, 1], [0, 1], linestyle="--", color="k")
ax.axis("square")
fig.suptitle("Comparison of over-sampling methods \nwith a 3NN classifier")
ax.set_xlim([0, 1])
ax.set_ylim([0, 1])
sns.despine(offset=10, ax=ax)
plt.legend(loc="lower right", fontsize=16)
plt.tight_layout()
plt.show()

我们看到,对于这项任务,使用某种插值生成新样本的方法(即ADASYN和SMOTE)比随机过采样或不进行重采样表现更好。
脚本的总运行时间: (0 分钟 35.343 秒)
预计内存使用量: 482 MB