我是一个相对较新的用户,可以从

问题描述 投票:0回答:3

sklearn.model_selection

如果我按任一列进行分层,则似乎正常工作:
dataframe
但是,当我尝试通过这两个列进行
stratify
时,我都会得到重复的值:
dataframe
	

如果您希望

sklearn

按照预期的方式行事(通过无重复的多个列进行分层),请创建一个新列,该列是其他列中值的串联,并在新列上分层。

from sklearn.model_selection import train_test_split a = np.array([i for i in range(1000000)]) b = [i%10 for i in a] c = [i%5 for i in a] df = pd.DataFrame({'a':a, 'b':b, 'c':c})

如果您担心诸如
train, test = train_test_split(df, test_size=0.2, random_state=0, stratify=df[['b']]) print(len(train.a.values)) # prints 800000 print(len(set(train.a.values))) # prints 800000 train, test = train_test_split(df, test_size=0.2, random_state=0, stratify=df[['c']]) print(len(train.a.values)) # prints 800000 print(len(set(train.a.values))) # prints 800000

stratify
train, test = train_test_split(df, test_size=0.2, random_state=0, stratify=df[['b', 'c']]) print(len(train.a.values)) # prints 800000 print(len(set(train.a.values))) # prints 640000

等值引起的碰撞,并且都创建一个串联值

train_test_split
,那么您可以在中间添加一些任意字符串:

df['bc'] = df['b'].astype(str) + df['c'].astype(str)
train, test = train_test_split(df, test_size=0.2, random_state=0, stratify=df[['bc']])
python pandas scikit-learn
3个回答
65
投票

您获得重复的原因是因为

11
最终将地层定义为您传递到

3
参数的任何内容的
型inique集值。 由于地层是从两列定义的,因此一行数据可能代表多个层,因此抽样可以选择两次相同的行,因为它认为它是从不同类中进行采样的。

函数

函数
calls
1
13

上(这是您通过
113
的内容)。 从源代码:

37
投票
df['bc'] = df['b'].astype(str) + "_" + df['c'].astype(str)

there是一个简化的样本案例,您提供的示例的变体:

train_test_split()

分层功能认为有四个类要分配:
stratify

train_test_split()

StratifiedShuffleSplit
np.unique()。 但是,由于这些类本质上是嵌套的,含义
y
stratify都出现在
classes, y_indices = np.unique(y, return_inverse=True)
n_classes = classes.shape[0]
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd

N = 20
a = np.arange(N)
b = np.random.choice(["foo","bar"], size=N)
c = np.random.choice(["y","z"], size=N)
df = pd.DataFrame({'a':a, 'b':b, 'c':c})

print(df)
     a    b  c
0    0  bar  y
1    1  foo  y
2    2  bar  z
3    3  bar  y
4    4  foo  z
5    5  bar  y
...
中,因此当分离器尝试从每个类中采样时,我们将获得重复。
foo

这里是一个较大的设计问题:您是否要使用嵌套的分层采样,还是实际上只是想将每个班级视为
bar

y

作为单独的班级以进行样品? 如果是后者,那就是您已经得到的。 前者更加复杂,这不是要做的。
您可能会发现嵌套分层采样的讨论很有用。  

您正在使用哪种版本的Scikit-Learn?您可以使用
z
进行检查。
在版本0.19.0之前,Scikit-Learn不能正确处理二维分层。它以0.19.0进行修补。

sissue#9044
中描述。
aups up upr your scikit-learn应该解决问题。如果您无法更新Scikit-Learn,请参阅此提交历史记录
HEREIDE。
    
您需要迭代分配数据。 Scikit-Multilearn有一个课程。有点烦人的是它只能在numpy阵列上起作用,但是您能做什么?
there是一个应该执行您要求的功能:
y

输出

z

对于您的示例,我们可以添加此代码:
b == foo
在您的示例中,

b == bar

成为1e6 x 3e5的矩阵,这有点多。如果有人想出更好的方式,那么我全都是耳朵。

现在,您可以通过简单地传递像我在下面一样使用的列列表来实现这一目标。假设您有2列sex_m和sex_f,您可以尝试做类似的事情。

11
投票
this之所以起作用,是因为

df.b

train_test_split

文档中所述。

© www.soinside.com 2019 - 2025. All rights reserved.