Я хотел бы обучить классификатор на одном наборе данных ImageNet (1000 классов каждый с примерно 1300 изображениями). По какой-то причине мне нужна каждая партия, содержащая 64 изображения из одного класса и последовательные партии из разных классов. Возможно ли (и эффективно) с последним TensorFlow?
tf.contrib.data.sample_from_datasets
в TF 1.9 позволяет выборку из списка объектов tf.data.Dataset
с weights
указывающими вероятности. Интересно, имеет ли смысл следующая идея:
tf.data.Dataset.from_generator
как weights
. Образцы объектов из категориального распределения, так что каждый образец выглядит как [0,...,0,1,0,...,0]
с 999 0
и 1 1
;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()
Следующий вопрос можно найти в разделе "Как выбрать пакет из определенного класса?
Я не думаю, что ваше решение может работать, если я его правильно понимаю, потому что 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))
tf.contrib.data.group_by_window
tf.contrib.data.group_by_window до сих пор работает с набором данных cifar10 ... Я сделаю еще тест, чтобы убедиться, что он эффективен в ImageNet.