Как сделать выборку из одного класса на каждой итерации

1

Я хотел бы обучить классификатор на одном наборе данных ImageNet (1000 классов каждый с примерно 1300 изображениями). По какой-то причине мне нужна каждая партия, содержащая 64 изображения из одного класса и последовательные партии из разных классов. Возможно ли (и эффективно) с последним TensorFlow?

tf.contrib.data.sample_from_datasets в TF 1.9 позволяет выборку из списка объектов tf.data.Dataset с weights указывающими вероятности. Интересно, имеет ли смысл следующая идея:

  • Сохраните данные каждого класса в виде отдельного файла tfrecord.
  • Передайте объект tf.data.Dataset.from_generator как weights. Образцы объектов из категориального распределения, так что каждый образец выглядит как [0,...,0,1,0,...,0] с 999 0 и 1 1;
  • Создайте 1000 объектов tf.data.Dataset, каждый из которых связан с файлом tfrecord.

Я подумал, что таким образом, возможно, на каждой итерации sample_from_datasets сначала sample_from_datasets разреженный вектор веса, который указывает, какой tf.data.Dataset для выборки, а затем тот же из этого класса.

Правильно ли это? Существуют ли другие эффективные способы?

Обновить

Как любезно предлагается P-Gn, одним из способов отбора данных из одного класса было бы:

dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(some_parser_fun)  # parse one datum from tfrecord
dataset = dataset.shuffle(buffer_size)

if sample_same_class:
    group_fun = tf.contrib.data.group_by_window(
        key_func=lambda data_x, data_y: data_y,
        reduce_func=lambda key, d: d.batch(batch_size),
        window_size=batch_size)
    dataset = dataset.apply(group_fun)
else:
    dataset = dataset.batch(batch_size)

dataset = dataset.repeat()
data_batch = dataset.make_one_shot_iterator().get_next()

Следующий вопрос можно найти в разделе "Как выбрать пакет из определенного класса?

Теги:
tensorflow

1 ответ

2
Лучший ответ

Я не думаю, что ваше решение может работать, если я его правильно понимаю, потому что sample_from_dataset ожидает список значений его weights, а не Tensor.

Однако, если вы не против иметь 1000 Dataset как в предлагаемом вами решении, я бы предложил просто

  • создать один Dataset каждого класса,
  • batch каждого из этих наборов данных - каждая партия имеет выборки из одного класса,
  • zip все из них в один большой Dataset пакетов,
  • shuffle этот Dataset - перетасовка будет происходить на партиях, а не на образцах, так что это не изменит того факта, что партии являются отдельными классами.

Более сложный способ - полагаться на tf.contrib.data.group_by_window. Позвольте мне проиллюстрировать это с помощью синтетического примера.

import numpy as np
import tensorflow as tf

def gen():
  while True:
    x = np.random.normal()
    label = np.random.randint(10)
    yield x, label

batch_size = 4
batch = (tf.data.Dataset
  .from_generator(gen, (tf.float32, tf.int64), (tf.TensorShape([]), tf.TensorShape([])))
  .apply(tf.contrib.data.group_by_window(
    key_func=lambda x, label: label,
    reduce_func=lambda key, d: d.batch(batch_size),
    window_size=batch_size))
  .make_one_shot_iterator()
  .get_next())

sess = tf.InteractiveSession()
sess.run(batch)
# (array([ 0.04058843,  0.2843775 , -1.8626076 ,  1.1154234 ], dtype=float32),
# array([6, 6, 6, 6], dtype=int64))
sess.run(batch)
# (array([ 1.3600663,  0.5935658, -0.6740045,  1.174328 ], dtype=float32),
# array([3, 3, 3, 3], dtype=int64))
  • 0
    Спасибо вам большое за ваш ответ. Я могу подтвердить, tf.contrib.data.group_by_window tf.contrib.data.group_by_window до сих пор работает с набором данных cifar10 ... Я сделаю еще тест, чтобы убедиться, что он эффективен в ImageNet.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню