Использовать вновь выбранные примеры проверки с подгонкой TensorFlow Keras при использовании `validation_steps`? - PullRequest
0 голосов
/ 02 апреля 2020
Метод

TensorFlow Keras Model.fit имеет два параметра для ограничения количества шагов в течение периода обучения: steps_per_epoch для количества шагов обучения и validation_steps для количества шагов проверки. Однако основное различие между этими двумя аргументами (помимо того, что они предназначены для обучения или проверки) состоит в том, как они выбирают данные из набора данных. Для обучения steps_per_epoch будет использовать следующие доступные выборки каждую эпоху, и поэтому каждая эпоха продвигается дальше по набору данных. Для проверки validation_steps всегда будет начинаться с начала проверки. Причина, по которой validation_steps работает по-разному, заключается в том, что разработчики хотели убедиться, что одни и те же данные используются для каждого запуска проверки. В моем случае я бы предпочел, чтобы это не так, как validation_steps работал. Мой набор данных (как обучающий, так и проверочный) довольно большой, и я хотел бы проверять его часто, а не требовать от него лишнего времени. Однако я также не хочу проверять только ограниченный набор данных проверки. Мне бы хотелось, чтобы валидация просто отбирала случайное подмножество общего набора данных для каждого прогона валидации, чтобы сглаженная кривая валидации дала общее приближение. Это было бы возможно путем перетасовки всего набора проверки, но опять же, поскольку набор данных очень большой, все пути файлов примеров не могут быть загружены в память одновременно для перемешивания.

Есть ли способ получить validation_steps работает так же, как steps_per_epoch, в том смысле, что используемые данные непрерывно проходят через набор данных в каждую эпоху? Либо с помощью какого-либо параметра fit, либо каким-либо образом оборачивая набор данных таким образом, что когда fit пытается сбросить набор данных, он вместо этого производит выборку следующих элементов в наборе данных?

Просто чтобы уточнить, мой конвейер данных начинается с pathlib.Path.glob. Это производит генератор. Этот генератор не может быть преобразован в список, так как в памяти слишком много путей. Этот генератор используется в качестве источника TensorFlow Dataset. Через API набора данных я загружаю отдельные файлы и предварительно обрабатываю их. API делает это асинхронно из графического процессора, используя несколько процессов. API набора данных также тасует небольшой буфер загруженных примеров. Это обеспечивает постоянную подачу предварительно выбранных данных для обучения на GPU.

1 Ответ

1 голос
/ 07 апреля 2020

Это зависит от того, какой генератор вы используете.

Если это keras.utils.Sequence (стандартный генератор Keras, который вы получаете с ImageDataGenerator и такие методы, как flow_from_dataframe, flow et c.), Они имеют свойство len и могут их партии получают по индексу.

Итак, для них вы создаете массив индексов:

batches = len(val_generator)
indices = np.arange(batches)

Затем вы можете создать свой собственный генератор Python :

def my_gen(val_generator):
    batches = len(val_generator)
    indices = np.arange(batches)

    while True: #these non standard generators using "yield" must be infinite

        #shuffle the batches
        np.random.shuffle(indices)

        #iterate the indices:
        for i in indices:
            yield val_generator[i]

Подходит для вашего нового "неприкасаемого" генератора. Keras не может запустить его заново, потому что эта опция не существует.

model.fit(.... validation_data = my_gen(val_generator), validation_steps = choose)

Если это уже генератор Python (который использует yield), вы можете быть уверены, что Keras не сбросить это невозможно Это специальный генератор, и все, что вам нужно, это перемешивать ваши данные каждый цикл, как описано выше. Но вместо того, чтобы перетасовывать все данные, перетасуйте индексы. Примерно так же, как я делал выше, но вместо того, чтобы получать от генератора Keras, получайте данные.

def my_gen(dataX, dataY, batch_size):
    samples = len(dataX)
    indices = np.arange(samples)

    batches = samples // batch_size
    if samples % batch_size > 0:
        batches += 1

    while True:
        np.random.shuffle(indices)

        for b in range(batches):
            start = b * batch_size
            end = (b+1) * batch_size

            batchX = dataX[indices[start:end]]
            batchY = dataY[indices[start:end]]
            yield batchX, batchY
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...