Python 按组分为列车和测试+;sklearn cross_val_分数

Python 按组分为列车和测试+;sklearn cross_val_分数,python,scikit-learn,Python,Scikit Learn,我有一个python数据帧,如下所示: data labels group aa 1 x bb 1 x cc 2 y dd 1 y ee 3 y ff 3 x gg 3 z hh 1 z ii 2 z 随机分成70:

我有一个python数据帧,如下所示:

data    labels    group
 aa       1         x
 bb       1         x
 cc       2         y
 dd       1         y
 ee       3         y
 ff       3         x
 gg       3         z
 hh       1         z
 ii       2         z
随机分成70:30进行训练和测试是很简单的。在这里,我需要分为测试和训练两部分,这样每个
组中70%的数据应该在训练中,每个组中30%的数据应该作为测试数据。然后预测并发现各组测试数据的准确性

我发现,
cross\u val\u score
通过以下功能进行拆分、拟合模型和预引用:

>>> from sklearn.model_selection import cross_val_score
>>> model = LogisticRegression(random_state=0)
>>> scores = cross_val_score(model, data, labels, cv=5)
>>> scores   
cross\u val\u score
的文档具有
参数,该参数表示:

groups : array-like, with shape (n_samples,), optional
Group labels for the samples used while splitting the dataset into 
train/test set.
在这里,我需要分为测试和训练,以便每组中70%的数据应该在训练中,每组中30%的数据应该作为测试数据。然后预测并发现各组测试数据的准确性。以下面的方式使用groups参数是否将每个组中的数据分割为训练和测试数据并进行预测

>>> scores = cross_val_score(model, data, labels, groups= group, cv=5)

非常感谢您的帮助。

列车测试分割的
分层
参数采用标签对选择进行分层,以保持适当的等级平衡

X_train, X_test, y_train, y_test = train_test_split(df['data'], df['labels'],stratify=df['group'])

在你的玩具数据集上,它似乎是你想要的,但我会在您的完整数据集上尝试它,并通过检查您的训练集和测试集中的数据计数来验证这些类是否平衡

训练测试分割的
分层
参数带有标签,用于分层选择以保持适当的类平衡

X_train, X_test, y_train, y_test = train_test_split(df['data'], df['labels'],stratify=df['group'])

在您的玩具数据集上,这似乎是您想要的,但我会在您的完整数据集上尝试,并通过检查您的训练集和测试集中的数据计数来验证类是否平衡,但是您可以
训练测试\u分割
应用于组,然后将分割与
pd.concat
连接起来,如:

def train_test_split_group(x):
    X_train, X_test, y_train, y_test = train_test_split(x['data'],x['labels'])
    return pd.Series([X_train, X_test, y_train, y_test], index=['X_train', 'X_test', 'y_train', 'y_test'])

final = df.groupby('group').apply(train_test_split_group).apply(lambda x: pd.concat(x.tolist()))
final['X_train'].dropna()

1    bb
3    dd
4    ee
5    ff
6    gg
7    hh
Name: X_train, dtype: object

我无法直接从函数中知道,但您可以将
应用到组中,然后将拆分与
pd.concat连接起来,如:

def train_test_split_group(x):
    X_train, X_test, y_train, y_test = train_test_split(x['data'],x['labels'])
    return pd.Series([X_train, X_test, y_train, y_test], index=['X_train', 'X_test', 'y_train', 'y_test'])

final = df.groupby('group').apply(train_test_split_group).apply(lambda x: pd.concat(x.tolist()))
final['X_train'].dropna()

1    bb
3    dd
4    ee
5    ff
6    gg
7    hh
Name: X_train, dtype: object

要以这种方式指定训练集和验证集,您需要创建交叉验证对象,而不是使用
cv=5
参数来指定
交叉验证分数。诀窍在于,您希望对褶皱进行分层,但不是基于
y
中的类,而是基于另一列数据。我认为您可以使用
StratifiedShuffleSplit
来实现以下目的

from sklearn.model_selection import StratifiedShuffleSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], 
              [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1])

groups_to_stratify = np.array([1,2,3,1,2,3,1,2,3,1,2,3])

sss = StratifiedShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
sss.get_n_splits()

print(sss)       

# Note groups_to_stratify is used in the split() function not y as usual
for train_index, test_index in sss.split(X, groups_to_stratify):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    print("TRAIN indices:", train_index, 
          "train groups", groups_to_stratify[train_index],
          "TEST indices:", test_index, 
          "test groups", groups_to_stratify[test_index])

要以这种方式指定训练集和验证集,您需要创建交叉验证对象,而不是使用
cv=5
参数来指定
交叉验证分数。诀窍在于,您希望对褶皱进行分层,但不是基于
y
中的类,而是基于另一列数据。我认为您可以使用
StratifiedShuffleSplit
来实现以下目的

from sklearn.model_selection import StratifiedShuffleSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], 
              [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1])

groups_to_stratify = np.array([1,2,3,1,2,3,1,2,3,1,2,3])

sss = StratifiedShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
sss.get_n_splits()

print(sss)       

# Note groups_to_stratify is used in the split() function not y as usual
for train_index, test_index in sss.split(X, groups_to_stratify):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    print("TRAIN indices:", train_index, 
          "train groups", groups_to_stratify[train_index],
          "TEST indices:", test_index, 
          "test groups", groups_to_stratify[test_index])

您可以使用pandas根据组进行过滤,然后使用过滤后的数据进行右侧拆分?您是否在train\u test\u split中查找
stratify
参数?假设我们将数据随机拆分为70:30。但是分裂应该考虑来自每组的70%的数据进入训练,并且每组30%的数据应该去测试数据集,而不是使只有少数组的值的训练集(70%)。分层也一样吗?请注意这里的术语。在sklearn中,“组”的含义与OP使用的含义非常不同。在sklearn中,“组”(例如,作为
cross_val_score
的参数,或
GroupKFold
)将在拆分或折叠中分离,而不是在它们之间平衡。您可以使用pandas根据组进行筛选,然后使用过滤后的数据进行右侧拆分?您是否在train_test_split中查找
stratify
参数?假设我们将数据随机拆分为70:30。但是分裂应该考虑来自每组的70%的数据进入训练,并且每组30%的数据应该去测试数据集,而不是使只有少数组的值的训练集(70%)。分层也一样吗?请注意这里的术语。在sklearn中,“组”的含义与OP使用的含义非常不同。在sklearn中,“组”(例如作为
cross\u val\u score
的参数,或在
GroupKFold
中)将在拆分或折叠之间分离,而不是在它们之间平衡。
cross\u val\u score
还包含从文档中传递的
groups
参数“将数据集拆分为训练集/测试集时使用的样本分组标签。“所以,这也应该像我对原始问题的评论一样起作用,
groups
参数的作用与所问的完全相反,它将组放入训练或测试中。
cross\u val\u score
还包含
groups
参数,您可以从文档中通过该参数“将数据集拆分为训练集/测试集时使用的样本分组标签。“所以这也应该像我对原始问题的评论一样起作用,
groups
参数的作用和所问的完全相反,它将组放入训练或测试中。只是让大家知道,如果您想要集成一个目标(y),此解决方案不起作用。”要交叉验证的依赖管道转换。请让所有人都知道,如果要集成要交叉验证的目标(y)依赖管道转换,则此解决方案不起作用。