如何拆分测试和训练数据,以保证每个 Class 中至少有一个
How to split Test and Train data such that there is garenteed at least one of each Class in each
我尝试 class 验证一些相当不平衡的数据。
但是,它 class 相当好。
为了准确评估效果,我必须将数据分成训练和测试子集。
现在我正在通过以下非常简单的措施来做到这一点:
import numpy as np
corpus = pandas.DataFrame(..., columns=["data","label"]) # My data, simplified
train_index = np.random.rand(len(corpus))>0.2
training_data = corpus[train_index]
test_data = corpus[np.logical_not(train_index)]
这很好也很简单,但有些 classes 很少出现:
在超过 50,000 个案例的语料库中,大约有 15 个案例出现次数少于 100 次,其中两个案例每个案例只出现一次。
我想将我的数据语料库划分为测试和训练子集,以便:
- 如果 class 出现少于两次,则将其排除在两者之外
- 每个 class 在测试和训练中至少出现一次
- 测试和训练的拆分是随机的
我可以拼凑一些东西来做这件事,
(可能最简单的方法是删除出现次数少于 2 次的东西),然后重新采样直到吐出的两边都有),但我想知道是否已经存在一种干净的方法。
我不认为 sklearn.cross_validation.train_test_split 可以做到这一点,但它的存在表明 sklearn 可能具有这种功能。
以下满足您将数据划分为测试和训练的 3 个条件:
#get rid of items with fewer than 2 occurrences.
corpus=corpus[corpus.groupby('label').label.transform(len)>1]
from sklearn.cross_validation import StratifiedShuffleSplit
sss=StratifiedShuffleSplit(corpus['label'].tolist(), 1, test_size=0.5, random_state=None)
train_index, test_index =list(*sss)
training_data=corpus.iloc[train_index]
test_data=corpus.iloc[test_index]
我已经使用以下虚构的数据帧测试了上面的代码:
#create random data with labels 0 to 39, then add 2 label case and one label case.
corpus=pd.DataFrame({'data':np.random.randn(49998),'label':np.random.randint(40,size=49998)})
corpus.loc[49998]=[random.random(),40]
corpus.loc[49999]=[random.random(),40]
corpus.loc[50000]=[random.random(),41]
测试代码时产生以下输出:
test_data[test_data['label']==40]
Out[110]:
data label
49999 0.231547 40
training_data[training_data['label']==40]
Out[111]:
data label
49998 0.253789 40
test_data[test_data['label']==41]
Out[112]:
Empty DataFrame
Columns: [data, label]
Index: []
training_data[training_data['label']==41]
Out[113]:
Empty DataFrame
Columns: [data, label]
Index: []
我尝试 class 验证一些相当不平衡的数据。 但是,它 class 相当好。
为了准确评估效果,我必须将数据分成训练和测试子集。
现在我正在通过以下非常简单的措施来做到这一点:
import numpy as np
corpus = pandas.DataFrame(..., columns=["data","label"]) # My data, simplified
train_index = np.random.rand(len(corpus))>0.2
training_data = corpus[train_index]
test_data = corpus[np.logical_not(train_index)]
这很好也很简单,但有些 classes 很少出现: 在超过 50,000 个案例的语料库中,大约有 15 个案例出现次数少于 100 次,其中两个案例每个案例只出现一次。
我想将我的数据语料库划分为测试和训练子集,以便:
- 如果 class 出现少于两次,则将其排除在两者之外
- 每个 class 在测试和训练中至少出现一次
- 测试和训练的拆分是随机的
我可以拼凑一些东西来做这件事, (可能最简单的方法是删除出现次数少于 2 次的东西),然后重新采样直到吐出的两边都有),但我想知道是否已经存在一种干净的方法。
我不认为 sklearn.cross_validation.train_test_split 可以做到这一点,但它的存在表明 sklearn 可能具有这种功能。
以下满足您将数据划分为测试和训练的 3 个条件:
#get rid of items with fewer than 2 occurrences.
corpus=corpus[corpus.groupby('label').label.transform(len)>1]
from sklearn.cross_validation import StratifiedShuffleSplit
sss=StratifiedShuffleSplit(corpus['label'].tolist(), 1, test_size=0.5, random_state=None)
train_index, test_index =list(*sss)
training_data=corpus.iloc[train_index]
test_data=corpus.iloc[test_index]
我已经使用以下虚构的数据帧测试了上面的代码:
#create random data with labels 0 to 39, then add 2 label case and one label case.
corpus=pd.DataFrame({'data':np.random.randn(49998),'label':np.random.randint(40,size=49998)})
corpus.loc[49998]=[random.random(),40]
corpus.loc[49999]=[random.random(),40]
corpus.loc[50000]=[random.random(),41]
测试代码时产生以下输出:
test_data[test_data['label']==40]
Out[110]:
data label
49999 0.231547 40
training_data[training_data['label']==40]
Out[111]:
data label
49998 0.253789 40
test_data[test_data['label']==41]
Out[112]:
Empty DataFrame
Columns: [data, label]
Index: []
training_data[training_data['label']==41]
Out[113]:
Empty DataFrame
Columns: [data, label]
Index: []