在张量流中对不平衡数据集进行子采样
Subsampling an unbalanced dataset in tensorflow
这里是 Tensorflow 初学者。这是我的第一个项目,我正在使用预定义的估算器。
我有一个极度不平衡的数据集,其中积极结果大约占总数据的 0.1%,我怀疑这种不平衡会显着影响我的模型的性能。作为解决这个问题的第一次尝试,因为我有大量数据,所以我想扔掉大部分底片以创建一个平衡的数据集。我可以看到两种方法:预处理数据以仅保留千分之一的底片,然后将其保存在一个新文件中,然后再将其传递给 tensorflow,例如使用 pyspark;并要求 tensorflow 只使用它找到的一千个负数中的一个。
我试图对最后一个想法进行编码,但没有成功。我将输入函数修改为
def train_input_fn(data_file="../data/train_input.csv", shuffle_size=100_000, batch_size=128):
"""Generate an input function for the Estimator."""
dataset = tf.data.TextLineDataset(data_file) # Extract lines from input files using the Dataset API.
dataset = dataset.map(parse_csv, num_parallel_calls=3)
dataset = dataset.shuffle(shuffle_size).repeat().batch(batch_size)
iterator = dataset.make_one_shot_iterator()
features, labels = iterator.get_next()
# TRY TO IMPLEMENT THE SELECTION OF NEGATIVES
thrown = 0
flag = np.random.randint(1000)
while labels == 0 and flag != 0:
features, labels = iterator.get_next()
thrown += 1
flag = np.random.randint(1000)
print("I've thrown away {} negative examples before going for label {}!".format(thrown, labels))
return features, labels
这当然是行不通的,因为迭代器不知道它们里面有什么,所以永远不会满足 labels==0 条件。此外,stdout 中只有一个打印,这意味着该函数仅被调用一次(这意味着我仍然不明白 tensorflow 的真正工作原理)。不管怎样,有没有办法实现我想要的?
PS:我怀疑之前的代码,即使它按预期工作,也会 return 少于初始负数的千分之一,因为每次找到正数时都会重新开始计数.这是一个小问题,到目前为止,我什至可以在标志内找到一个神奇的数字,它可以给我预期的结果,而不必太担心它的数学美感。
您可能会通过 过度采样 您的 under-represented class 而不是丢弃 over-represented class 中的数据获得更好的结果].这样你就可以保持 over-represented class 的方差。您不妨使用您拥有的数据。
实现这一点的最简单方法可能是创建两个数据集,每个 class。然后您可以使用 Dataset.interleave
从两个数据集中平均采样。
https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave
可以使用以下代码轻松实现过采样:
resampled_ds = tf.data.experimental.sample_from_datasets([pos_ds, neg_ds], weights=[0.7, 0.3])
Tensorflow 有一个很好的处理不平衡数据的指南,您可以在这里找到更多的想法:
https://www.tensorflow.org/tutorials/structured_data/imbalanced_data#oversampling
这里是 Tensorflow 初学者。这是我的第一个项目,我正在使用预定义的估算器。
我有一个极度不平衡的数据集,其中积极结果大约占总数据的 0.1%,我怀疑这种不平衡会显着影响我的模型的性能。作为解决这个问题的第一次尝试,因为我有大量数据,所以我想扔掉大部分底片以创建一个平衡的数据集。我可以看到两种方法:预处理数据以仅保留千分之一的底片,然后将其保存在一个新文件中,然后再将其传递给 tensorflow,例如使用 pyspark;并要求 tensorflow 只使用它找到的一千个负数中的一个。
我试图对最后一个想法进行编码,但没有成功。我将输入函数修改为
def train_input_fn(data_file="../data/train_input.csv", shuffle_size=100_000, batch_size=128):
"""Generate an input function for the Estimator."""
dataset = tf.data.TextLineDataset(data_file) # Extract lines from input files using the Dataset API.
dataset = dataset.map(parse_csv, num_parallel_calls=3)
dataset = dataset.shuffle(shuffle_size).repeat().batch(batch_size)
iterator = dataset.make_one_shot_iterator()
features, labels = iterator.get_next()
# TRY TO IMPLEMENT THE SELECTION OF NEGATIVES
thrown = 0
flag = np.random.randint(1000)
while labels == 0 and flag != 0:
features, labels = iterator.get_next()
thrown += 1
flag = np.random.randint(1000)
print("I've thrown away {} negative examples before going for label {}!".format(thrown, labels))
return features, labels
这当然是行不通的,因为迭代器不知道它们里面有什么,所以永远不会满足 labels==0 条件。此外,stdout 中只有一个打印,这意味着该函数仅被调用一次(这意味着我仍然不明白 tensorflow 的真正工作原理)。不管怎样,有没有办法实现我想要的?
PS:我怀疑之前的代码,即使它按预期工作,也会 return 少于初始负数的千分之一,因为每次找到正数时都会重新开始计数.这是一个小问题,到目前为止,我什至可以在标志内找到一个神奇的数字,它可以给我预期的结果,而不必太担心它的数学美感。
您可能会通过 过度采样 您的 under-represented class 而不是丢弃 over-represented class 中的数据获得更好的结果].这样你就可以保持 over-represented class 的方差。您不妨使用您拥有的数据。
实现这一点的最简单方法可能是创建两个数据集,每个 class。然后您可以使用 Dataset.interleave
从两个数据集中平均采样。
https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave
可以使用以下代码轻松实现过采样:
resampled_ds = tf.data.experimental.sample_from_datasets([pos_ds, neg_ds], weights=[0.7, 0.3])
Tensorflow 有一个很好的处理不平衡数据的指南,您可以在这里找到更多的想法: https://www.tensorflow.org/tutorials/structured_data/imbalanced_data#oversampling