无法在多标签分类器上使用分层-K倍



以下代码用于进行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折。请帮助我。

MultiLabelBinarizer返回一个为您的类数的向量。

如果您查看StratifiedKFold如何拆分数据集,则会发现它仅接受一维目标变量,而您试图通过尺寸[n_samples, n_classes]

传递目标变量

策略拆分基本上保留了您的班级分布。而且,如果您考虑一下,如果您有多标签分类问题,那将没有很多意义。

如果您想根据目标变量中的类别组合来保留分布,则答案说明了两种方式,您可以定义自己的战略性拆分功能。

更新:

逻辑就是这样:

假设您有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]

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

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

代码样本:

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])

只是为了扩展@panktijk工作的出色工作,这是一个完整的示例。也许这可以合并为他的回答?

import numpy as np
from sklearn.model_selection import StratifiedGroupKFold, StratifiedKFold
from sklearn.preprocessing import LabelEncoder

np.random.seed(1)
N = 1000
X = np.random.random((N, 100))
y = np.random.randint(0, 2, (N, 7))

def get_new_labels(y):
    """ Convert each multilabel vector to a unique string """
    yy = [''.join(str(l)) for l in y]
    y_new = LabelEncoder().fit_transform(yy)
    return y_new
y_new = get_new_labels(y)
folder = StratifiedKFold(n_splits=2)
for train_indices, test_indices in folder.split(X, y_new):
    # Do stuff with train and test indices

带有github项目'迭代分离'的 MultilabelStratifiedKFold() [...]也存在 scikit-learn兼容实现:

https://github.com/trent-b/iterative-spratification

最新更新