备注
Go to the end 下载完整的示例代码。或者通过浏览器中的MysterLite或Binder运行此示例
使用分类器链的多标签分类#
此示例说明如何使用 ClassifierChain
以解决多标签分类问题。
解决此类任务的最天真的策略是在每个标签(即目标变量的每列)上独立训练二进制分类器。在预测时,使用二进制分类器的集合来组装多任务预测。
该策略不允许对不同任务之间的关系进行建模。的 ClassifierChain
是实现更高级策略的元估计器(即采用内部估计器的估计器)。二进制分类器的集合用作链,其中链中分类器的预测用作在新标签上训练下一个分类器的特征。因此,这些额外的功能允许每个链利用标签之间的相关性。
的 Jaccard similarity 链的得分往往大于集合独立基础模型的得分。
# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause
加载数据集#
对于这个示例,我们使用 yeast 数据集包含2,417个数据点,每个数据点包含103个特征和14个可能的标签。每个数据点至少有一个标签。作为基线,我们首先为14个标签中的每个标签训练逻辑回归分类器。为了评估这些分类器的性能,我们在已完成的测试集上进行预测,并计算每个样本的Jaccard相似性。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
# Load a multi-label dataset from https://www.openml.org/d/40597
X, Y = fetch_openml("yeast", version=4, return_X_y=True)
Y = Y == "TRUE"
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
试衣模特#
我们拟合 LogisticRegression
包裹 OneVsRestClassifier
和多个的集合 ClassifierChain
.
由OneVsRestClassifier包装的LogisticRegulation#
由于默认情况 LogisticRegression
无法处理具有多个目标的数据,我们需要使用 OneVsRestClassifier
.对模型进行匹配后,我们计算Jaccard相似度。
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import jaccard_score
from sklearn.multiclass import OneVsRestClassifier
base_lr = LogisticRegression()
ovr = OneVsRestClassifier(base_lr)
ovr.fit(X_train, Y_train)
Y_pred_ovr = ovr.predict(X_test)
ovr_jaccard_score = jaccard_score(Y_test, Y_pred_ovr, average="samples")
二元分类器链#
由于每个链中的模型是随机排列的,因此链之间的性能存在显着差异。据推测,链中的类存在一个最佳顺序,从而产生最佳性能。然而,我们不知道先验排序。相反,我们可以通过平均分类器链的二进制预测并应用0.5的阈值来构建分类器链的投票集成。集成的Jaccard相似性分数大于独立模型的Jaccard相似性分数,并且往往超过集成中每个链的分数(尽管这对于随机排序的链来说并不能保证)。
from sklearn.multioutput import ClassifierChain
chains = [ClassifierChain(base_lr, order="random", random_state=i) for i in range(10)]
for chain in chains:
chain.fit(X_train, Y_train)
Y_pred_chains = np.array([chain.predict_proba(X_test) for chain in chains])
chain_jaccard_scores = [
jaccard_score(Y_test, Y_pred_chain >= 0.5, average="samples")
for Y_pred_chain in Y_pred_chains
]
Y_pred_ensemble = Y_pred_chains.mean(axis=0)
ensemble_jaccard_score = jaccard_score(
Y_test, Y_pred_ensemble >= 0.5, average="samples"
)
图结果#
绘制独立模型、每个链和总体的Jaccard相似性分数(请注意,此图上的垂直轴不是从0开始)。
model_scores = [ovr_jaccard_score] + chain_jaccard_scores + [ensemble_jaccard_score]
model_names = (
"Independent",
"Chain 1",
"Chain 2",
"Chain 3",
"Chain 4",
"Chain 5",
"Chain 6",
"Chain 7",
"Chain 8",
"Chain 9",
"Chain 10",
"Ensemble",
)
x_pos = np.arange(len(model_names))
fig, ax = plt.subplots(figsize=(7, 4))
ax.grid(True)
ax.set_title("Classifier Chain Ensemble Performance Comparison")
ax.set_xticks(x_pos)
ax.set_xticklabels(model_names, rotation="vertical")
ax.set_ylabel("Jaccard Similarity Score")
ax.set_ylim([min(model_scores) * 0.9, max(model_scores) * 1.1])
colors = ["r"] + ["b"] * len(chain_jaccard_scores) + ["g"]
ax.bar(x_pos, model_scores, alpha=0.5, color=colors)
plt.tight_layout()
plt.show()

结果解释#
这个情节有三个主要要点:
独立模型包裹
OneVsRestClassifier
性能比分类器链的集合和一些单个链的集合更差。这是由于逻辑回归没有对标签之间的关系进行建模而导致的。ClassifierChain
利用标签之间的相关性,但由于标签排序的随机性,它可能会产生比独立模型更差的结果。链的集合表现更好,因为它不仅捕捉标签之间的关系,而且不会对其正确顺序做出强烈假设。
Total running time of the script: (0分1.821秒)
相关实例
Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>
_