Создавайте сбалансированные мини-партии с помощью Dataset API

У меня вопрос о новом API набора данных (tensorflow 1.4rc1). У меня несбалансированный набор данных по меткам 0 и 1. Моя цель - создать сбалансированные мини-партии во время предварительной обработки.

Предположим, у меня есть два отфильтрованных набора данных:

ds_pos = dataset.filter(lambda l, x, y, z: tf.reshape(tf.equal(l, 1), []))
ds_neg = dataset.filter(lambda l, x, y, z: tf.reshape(tf.equal(l, 0), [])).repeat()

Есть ли способ объединить эти два набора данных так, чтобы результирующий набор данных выглядел как ds = [0, 1, 0, 1, 0, 1]:

Что-то вроде этого:

dataset = tf.data.Dataset.zip((ds_pos, ds_neg))
dataset = dataset.apply(...)
# dataset looks like [0, 1, 0, 1, 0, 1, ...]
dataset = dataset.batch(20)

Мой текущий подход:

def _concat(x, y):
   return tf.cond(tf.random_uniform(()) > 0.5, lambda: x, lambda: y)
dataset = tf.data.Dataset.zip((ds_pos, ds_neg))
dataset = dataset.map(_concat)

Но мне кажется, что есть более элегантный способ.

Заранее спасибо!


person lhlmgr    schedule 25.10.2017    source источник
comment
Возможный дубликат Использование набора данных tenorflow со стратифицированной выборкой   -  person Ismael EL ATIFI    schedule 23.09.2019


Ответы (1)


Ты на правильном пути. В следующем примере Dataset.flat_map() используется для превращения каждой пары положительного и отрицательного примеров в два последовательных примера в результате:

dataset = tf.data.Dataset.zip((ds_pos, ds_neg))

# Each input element will be converted into a two-element `Dataset` using
# `Dataset.from_tensors()` and `Dataset.concatenate()`, then `Dataset.flat_map()`
# will flatten the resulting `Dataset`s into a single `Dataset`.
dataset = dataset.flat_map(
    lambda ex_pos, ex_neg: tf.data.Dataset.from_tensors(ex_pos).concatenate(
        tf.data.Dataset.from_tensors(ex_neg)))

dataset = dataset.batch(20)
person mrry    schedule 04.12.2017
comment
Большое спасибо! Теперь я могу убрать шаг выборки для каждой точки данных :) - person lhlmgr; 05.12.2017
comment
Я хотел использовать тот же подход для задачи классификации нескольких классов. Однако это мучительно медленно. Есть ли более эффективный способ создания сбалансированных мини-партий в задаче небинарной классификации? - person aseipel; 08.12.2017
comment
@aseipel Один из вариантов - разделить ваши примеры на один файл для каждого класса, а затем использовать Dataset.range(NUM_CLASSES).interleave(dataset_for_class, cycle_length=NUM_CLASSES) (где dataset_for_class(c) - функция, загружающая этот файл для класса c). - person mrry; 08.12.2017
comment
@aseipel - Вы знаете, какая часть медленная в случае мультикласса? Обычно повторная инициализация итераторов происходит очень медленно, поэтому я думаю, что решение zip и flat_map будет лучше, чем наличие итератора для каждого класса. - person Avi; 03.02.2018
comment
При использовании этого решения следует иметь в виду, что zip создаст набор данных с размером, равным наименьшему из архивируемых. Я думаю, поэтому OP использовал repeat на ds_neg. Я предполагаю, что это было сделано для того, чтобы использовать все данные большинства классов, ds_pos. - person Avi; 03.02.2018
comment
@mrry, не могли бы вы использовать interleave для производства преднамеренно несбалансированных партий? stackoverflow.com/questions/57331048/ - person SumNeuron; 02.08.2019