Python 如何分割测试和训练数据,使每个类中至少有一个类
我有一些相当不平衡的数据,我正试图分类。 然而,它的分类相当好 为了准确评估效果,我必须将数据分成训练和测试子集 现在,我通过非常简单的方法来实现这一点:Python 如何分割测试和训练数据,使每个类中至少有一个类,python,pandas,machine-learning,scikit-learn,classification,Python,Pandas,Machine Learning,Scikit Learn,Classification,我有一些相当不平衡的数据,我正试图分类。 然而,它的分类相当好 为了准确评估效果,我必须将数据分成训练和测试子集 现在,我通过非常简单的方法来实现这一点: 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[tr
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)]
这很简单,但有些类很少出现:
在50000多个病例的语料库中,约有15个病例每次发生不到100次,其中两个仅发生一次
我希望将我的数据集划分为测试和培训子集,以便:
- 如果一个类出现的次数少于两次,则它将从这两个类中排除
- 在测试和培训中,每节课至少进行一次
- 分为测试和培训是随机的
我认为这样做不行,但它的存在表明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: []
而forloop不应该:它应该是
train\u索引,test\u index=list(*splitter);train_data=common_corpus.iloc[train_index,:];test_data=common_corpus.iloc[test_index,:]
你说得对@oxiabox这是一种更干净的方法。如果对数据进行多次拆分,则循环对于StratifiedShuffleSplit()
中大于1的n\u iter
值非常有用。我将使用您建议的替换项修改答案。它不应该是iloc
而不是loc
,因此如果索引不是一个简单的范围,它就可以正常工作?iloc
是更好的答案,我修改了答案以反映这一点。谢谢