簡體   English   中英

如何在保持屬性比率固定的情況下將數據集拆分為多個折疊

[英]How to split the dataset into mutiple folds while keeping the ratio of an attribute fixed

假設我有一個具有多個輸入特征和一個 output 的數據集。為了簡單起見,假設 output 是二進制的。 要么是零,要么是一。

我想將此數據集拆分為k個部分,並使用 k 折交叉驗證 model 來學習從輸入特征到 output 的映射。 如果數據集不平衡,則 output 01的記錄數之間的比率不會是 1。 具體來說,假設 90% 的記錄為0 ,只有 10% 為1

我認為重要的是,在 k-folds 的每個部分中,我們應該看到相同的0 s 和1 s 比例,以便成功訓練(相同的 9 比 1 比例)。 我知道如何在 Pandas 中執行此操作,但我的問題是如何在 TFX 中執行此操作。

閱讀TFX 文檔,我知道我可以通過將output_config指定到加載示例的 class 來拆分數據集:

output = tfx.proto.Output(
             split_config=tfx.proto.SplitConfig(splits=[
                 tfx.proto.SplitConfig.Split(name='fold_1', hash_buckets=1),
                 tfx.proto.SplitConfig.Split(name='fold_2', hash_buckets=1),
                 tfx.proto.SplitConfig.Split(name='fold_3', hash_buckets=1),
                 tfx.proto.SplitConfig.Split(name='fold_4', hash_buckets=1),
                 tfx.proto.SplitConfig.Split(name='fold_5', hash_buckets=1)
             ]))
example_gen = CsvExampleGen(input_base=input_dir, output_config=output)

但是,上述例子在每一折中的比例充其量是隨機的。 我的問題是:有什么方法可以指定每次拆分的內容嗎? 我可以以某種方式強制執行功能的比率嗎?

順便說一句,我已經看到並試驗了SplitConfig class 的partition_feature_name參數。它在這里沒有用,除非每個示例都有一個帶有折疊 ID 的功能,我認為這是不實用的,因為我可能想將折疊數更改為部分實驗不改變數據集。

我將回答我自己的問題,但只是作為一種解決方法。 我很高興看到有人為這個問題開發出真正的解決方案。

此時我能想到的是將數據集拆分為多個 tfrecord 文件。 我選擇了一個“復合”數量的文件,這樣我就可以將它們分成(幾乎)任何我想要的數量。 為此,我選擇了 60,因為它可以除以 2、3、4、5、6、10 和 12(我認為沒有人會想要 k 大於 12 的 KFold)。 然后在加載它們時,我必須以某種方式 select 將哪些文件 go 放入每個拆分中。 這里有兩件事需要考慮。

首先,來自 TFX 的 ImportExampleGen class 支持 glob 文件模式。 這意味着我們可以為每個拆分加載多個文件:

input = tfx.proto.Input(splits=[
    tfx.proto.Input.Split(name="fold_1", pattern="fold_1*"),
    tfx.proto.Input.Split(name="fold_2", pattern="fold_2*")
])
example_gen = tfx.components.ImportExampleGen(input_base=_dataset_folder,
                                              input_config=input)

接下來,我們需要一些獨創性來在加載文件時將文件拆分成我們喜歡的任何數量。 這是我的方法:

fold_3.0_4.0_5.0_6.0_10.0/part-###.tfrecords.gz
fold_3.0_4.0_5.1_6.0_10.6/part-###.tfrecords.gz
fold_3.0_4.0_5.2_6.0_10.2/part-###.tfrecords.gz
fold_3.0_4.0_5.3_6.0_10.8/part-###.tfrecords.gz
...

文件模式是這樣的。 在每兩個_之間包括除數 a . ,然后是余數。 我將擁有盡可能多的這些,因為我希望稍后在加載數據集時具有“拆分可能性”。

在上面的示例中,我可以選擇將它們加載到 3、4、5、6 和 10 折中。 如果我想將數據集拆分成任意數量的折疊,第一個文件將作為第 0 次拆分的一部分加載,而第二個文件將在第 5 次拆分和第 6 次 10 次拆分中加載。

這就是我加載它們的方式:

NUM_FOLDS = 5

input = tfx.proto.Input(splits=[
    tfx.proto.Input.Split(name=f'fold_{index + 1}',
                          pattern=f"fold_*{str(NUM_FOLDS)+'.'+str(index)}*/*")
    for index in range(NUM_FOLDS)
])
example_gen = tfx.components.ImportExampleGen(input_base=_dataset_folder,
                                              input_config=input)

我可以將NUM_FOLDS更改為選項 3、4、5、6 或 10 中的任何一個,加載的數據集將包含預先策划的 k 折拆分。 值得一提的是,我在創建文件時已經確定了每個文件中樣本的比例。 所以它們的任何組合也將具有相同的比率。

同樣,在沒有實際解決方案的情況下,這只是一個技巧。 這種方法的主要缺點是您必須自己手動拆分數據集。 我這樣做了,在這種情況下,使用 pandas。這意味着我必須將整個數據集加載到 memory。這可能不適用於所有數據集。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM