【问题标题】:Not able to use Stratified-K-Fold on multi label classifier无法在多标签分类器上使用 Stratified-K-Fold
【发布时间】:2019-07-20 07:33:13
【问题描述】:

以下代码用于进行 KFold 验证,但我要在模型抛出错误时对其进行训练

ValueError: Error when checking target: expected dense_14 to have shape (7,) but got array with shape (1,)

我的目标变量有 7 个类。我正在使用LabelEncoder 将类编码为数字。

通过看到此错误,如果我将 MultiLabelBinarizer 更改为对类进行编码。我收到以下错误

ValueError: Supported target types are: ('binary', 'multiclass'). Got 'multilabel-indicator' instead.

以下是KFold验证的代码

skf = StratifiedKFold(n_splits=10, shuffle=True)
scores = np.zeros(10)
idx = 0
for index, (train_indices, val_indices) in enumerate(skf.split(X, y)):
    print("Training on fold " + str(index+1) + "/10...")
    # Generate batches from indices
    xtrain, xval = X[train_indices], X[val_indices]
    ytrain, yval = y[train_indices], y[val_indices]
    model = None
    model = load_model() //defined above

    scores[idx] = train_model(model, xtrain, ytrain, xval, yval)
    idx+=1
print(scores)
print(scores.mean())

我不知道该怎么办。我想在我的模型上使用分层 K 折叠。请帮帮我。

【问题讨论】:

    标签: keras scikit-learn deep-learning cross-validation


    【解决方案1】:

    MultiLabelBinarizer 返回一个与您的类数长度相同的向量。

    如果您查看StratifiedKFold splits 您的数据集,您会发现它只接受一维目标变量,而您尝试传递维度为[n_samples, n_classes] 的目标变量

    策略性拆分基本上可以保留您的班级分布。而且仔细想想,多标签分类问题也没多大意义。

    如果您想根据目标变量中的不同类组合来保留分布,那么答案here 解释了您可以定义自己的分层拆分函数的两种方法。

    更新:

    逻辑是这样的:

    假设您有n 类并且您的目标变量是这些n 类的组合。您将拥有 (2^n) - 1 组合(不包括全 0)。您现在可以创建一个新的目标变量,将每个组合视为一个新标签。

    例如,如果n=3,您将拥有7 唯一组合:

     1. [1, 0, 0]
     2. [0, 1, 0]
     3. [0, 0, 1]
     4. [1, 1, 0]
     5. [1, 0, 1]
     6. [0, 1, 1]
     7. [1, 1, 1]
    

    将所有标签映射到这个新的目标变量。您现在可以将问题视为简单的多类分类,而不是多标签分类。

    现在您可以直接使用StartefiedKFold,使用y_new 作为您的目标。拆分完成后,您可以将标签映射回来。

    代码示例:

    import numpy as np
    
    np.random.seed(1)
    y = np.random.randint(0, 2, (10, 7))
    y = y[np.where(y.sum(axis=1) != 0)[0]]
    

    输出:

    array([[1, 1, 0, 0, 1, 1, 1],
           [1, 1, 0, 0, 1, 0, 1],
           [1, 0, 0, 1, 0, 0, 0],
           [1, 0, 0, 1, 0, 0, 0],
           [1, 0, 0, 0, 1, 1, 1],
           [1, 1, 0, 0, 0, 1, 1],
           [1, 1, 1, 1, 0, 1, 1],
           [0, 0, 1, 0, 0, 1, 1],
           [1, 0, 1, 0, 0, 1, 1],
           [0, 1, 1, 1, 1, 0, 0]])
    

    标签编码你的类向量:

    from sklearn.preprocessing import LabelEncoder
    
    def get_new_labels(y):
        y_new = LabelEncoder().fit_transform([''.join(str(l)) for l in y])
        return y_new
    
    y_new = get_new_labels(y)
    

    输出:

    array([7, 6, 3, 3, 2, 5, 8, 0, 4, 1])
    

    【讨论】:

    • 我无法理解链接中给出的解决方案。太复杂了。您能向我解释一下如何在我的问题中使用该功能吗?
    • @SaiPavan 更新了答案。
    • 非常感谢
    • 我分享的代码有效。但我似乎不明白它背后的逻辑。
    • @SaiPavan 到底是哪一部分?我建议您阅读有关分层拆分的工作原理以及为什么sklearn 不支持它来解决多标签问题。这里的主要思想是将您的问题转换为多类问题,以便您可以应用策略拆分。
    猜你喜欢
    • 2020-04-03
    • 2021-08-17
    • 2020-08-02
    • 2015-01-20
    • 2017-05-04
    • 2019-10-30
    • 2018-12-26
    • 2018-12-01
    • 2016-02-25
    相关资源
    最近更新 更多