分类器链

我们看在多标签数据集上使用分类器链的示例。

在此示例中,我们将使用酵母数据集,其中包含2417个数据点,每个数据点具有103个特征和14个可能的标签。每个数据点至少具有一个标签。作为基线,我们首先为14个标签中的每个标签训练逻辑回归分类器。为了评估这些分类器的性能,我们对保留的测试集进行了预测,并计算了每个样本的jaccard得分。

接下来,我们创建10个分类器链。每个分类器链包含14个标签中每个标签的逻辑回归模型。每个链中的模型都是随机排序的。除了数据集中的103个要素外,每个模型还将链中先前模型的预测作为要素(请注意,默认情况下,在训练时,每个模型都将真实标签作为要素)。这些附加功能允许每个链利用类之间的相关性。每条链的Jaccard相似性得分往往要高于所设置的独立逻辑模型的得分。

因为每个链中的模型都是随机排列的,所以链之间的性能存在显着差异。大概链中的类有最佳排序,这将产生最佳性能。但是,我们不知道先验顺序。相反,我们可以通过平均分类器链的二进制预测并应用阈值0.5来构建分类器链的投票合奏。集成的Jaccard相似度得分高于独立模型的Jaccard相似度得分,并且往往超过集成中每个链的得分(尽管随机排序的链不能保证这一点)。

输入:

# 作者: Adam Kleczewski
# 执照: BSD 3 clause

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.multioutput import ClassifierChain
from sklearn.model_selection import train_test_split
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import jaccard_score
from sklearn.linear_model import LogisticRegression

print(__doc__)

# 从页面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=.2,
                                                    random_state=0)

# 使用OneVsRestClassifie打包的方式,为每个标签类别拟合一个独立的逻辑回归模型
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')

# 拟合逻辑回归分类器链的集合,并对所有链进行平均预测
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(X_test) for chain in
                          chains])
chain_jaccard_scores = [jaccard_score(Y_test, Y_pred_chain >= .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 >= .5,
                                       average='samples')

model_scores = [ovr_jaccard_score] + chain_jaccard_scores
model_scores.append(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))

# 绘制独立模型,计算每个链和集合的Jaccard相似度得分
#(请注意,此图的垂直轴并非始于0)。

fig, ax = plt.subplots(figsize=(74))
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) * .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()

输出:

脚本的总运行时间:(0分钟6.911秒)。