通常,建议对数据集进行采样,以便在多次运行代码时测试集和训练集保持相同,以便进行比较,同时也将算法隐藏在整个数据集中。由于数据集发生更改,并且可能会从数据库中重新获取更新的数据集,因此一种稳定的过程是在ID或唯一标识符上使用哈希。例如,假设要在测试和训练之间按分别为0.2和0.8的比率划分数据集。在计算完ID的散列后,由于散列应导致均匀分布,因此可能会占用最后一个字节,如果该字节小于0.2*256
,则分配给数据集,否则分配给训练集。
此过程的一个示例是以下代码:
import hashlib
def test_set_check(identifier,test_ratio,hash):
return hash(np.int64(identifier)).digest()[-1] < 256 * test_ratio
def split_train_test_by_id(data,id_column,hash=hashlib.md5):
ids = data[id_column]
in_test_set = ids.apply(lambda id_: test_set_check(id_,hash))
return data.loc[~in_test_set],data.loc[in_test_set]
通过这种方式,即使添加了新条目,先前运行中分配给测试集的行也将始终分配给测试集。分配给训练集的行也是如此。
但是,同一本书指出,重要的是要在训练集和测试集之间保持重要分类值的原始比率。例如,如果女性占全球人口的60%,我的培训和测验应该反映出这一点。这称为分层抽样,并且scikit-learn库具有用于以下目的的功能:
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1,test_size=0.2,random_state=42)
#this loop is executed just once because n_splits=1?
for train_index,test_index in split.split(dataFrame,dataFrame["important_categorical_variable"]):
train_set = dataFrame.loc[train_index]
test_set = dataFrame.loc[test_index]
如果我多次运行,由于固定的随机状态,它将产生相同的训练和测试集。但是,当数据库被更新或更改时,情况可能并非如此,我的训练和测试集可能看起来非常不同。
是否有一种方法可以结合分层抽样以保持比率,即使在更新数据时也保持(几乎)相同的训练和测试集?