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']])
您获得重复的原因是因为
11
最终将地层定义为您传递到3
参数的任何内容的型inique集值。 由于地层是从两列定义的,因此一行数据可能代表多个层,因此抽样可以选择两次相同的行,因为它认为它是从不同类中进行采样的。
函数
函数calls
1
在
13
上(这是您通过113
的内容)。 从源代码: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
现在,您可以通过简单地传递像我在下面一样使用的列列表来实现这一目标。假设您有2列sex_m和sex_f,您可以尝试做类似的事情。
df.b
在train_test_split文档中所述。