无法在多标签分类器上使用 Stratified-K-Fold
Not able to use Stratified-K-Fold on multi label classifier
以下代码用于执行 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())
我不知道该怎么办。我想在我的模型上使用 Stratified K Fold。请帮助我。
MultiLabelBinarizer
returns 一个向量,其长度为 classes.
如果您查看 StratifiedKFold
splits 您的数据集,您会发现它只接受一维目标变量,而您正试图传递尺寸为 [n_samples, n_classes]
Stratefied split 基本上保留了您的 class 分布。如果你仔细想想,如果你有一个多标签 classification 问题,它没有多大意义。
如果您想根据目标变量中 classes 的不同组合来保留分布,那么答案 here 解释了您可以定义自己的策略化拆分的两种方法功能。
更新:
逻辑是这样的:
假设您有 n
class 并且您的目标变量是这些 n
class 的组合。您将有 (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]
将所有标签映射到这个新的目标变量。您现在可以将问题视为简单的 multi-class class化,而不是 multi-label class化.
现在您可以直接使用 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]])
标签编码你的class向量:
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])
以下代码用于执行 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())
我不知道该怎么办。我想在我的模型上使用 Stratified K Fold。请帮助我。
MultiLabelBinarizer
returns 一个向量,其长度为 classes.
如果您查看 StratifiedKFold
splits 您的数据集,您会发现它只接受一维目标变量,而您正试图传递尺寸为 [n_samples, n_classes]
Stratefied split 基本上保留了您的 class 分布。如果你仔细想想,如果你有一个多标签 classification 问题,它没有多大意义。
如果您想根据目标变量中 classes 的不同组合来保留分布,那么答案 here 解释了您可以定义自己的策略化拆分的两种方法功能。
更新:
逻辑是这样的:
假设您有 n
class 并且您的目标变量是这些 n
class 的组合。您将有 (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]
将所有标签映射到这个新的目标变量。您现在可以将问题视为简单的 multi-class class化,而不是 multi-label class化.
现在您可以直接使用 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]])
标签编码你的class向量:
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])