размер буфера

сно TensorFlowдокументация ,prefetch а такжеmap методыtf.contrib.data.Dataset класс, оба имеют параметр с именемbuffer_size.

Заprefetch Метод, параметр известен какbuffer_size и согласно документации:

buffer_size: скалярный tf.Tensor tf.int64, представляющий максимальное количество элементов, которые будут буферизироваться при предварительной выборке.

Дляmap Метод, параметр известен какoutput_buffer_size и согласно документации:

output_buffer_size: (Необязательно.) Скалярный tf.Tensor tf.int64, представляющий максимальное количество обработанных элементов, которые будут буферизованы.

Аналогично дляshuffle Метод, такое же количество появляется и согласно документации:

buffer_size: скалярный tf.Tensor tf.int64, представляющий количество элементов из этого набора данных, из которого будет сэмплирован новый набор данных.

Какова связь между этими параметрами?

Предположим, я создаюDataset объект следующим образом:

 tr_data = TFRecordDataset(trainfilenames)
    tr_data = tr_data.map(providefortraining, output_buffer_size=10 * trainbatchsize, num_parallel_calls\
=5)
    tr_data = tr_data.shuffle(buffer_size= 100 * trainbatchsize)
    tr_data = tr_data.prefetch(buffer_size = 10 * trainbatchsize)
    tr_data = tr_data.batch(trainbatchsize)

Какую роль играетbuffer параметры в приведенном фрагменте?

Ответы на вопрос(5)

Решение Вопроса

TL; DR Несмотря на схожие названия, эти аргументы имеют совершенно разные значения.buffer_size вDataset.shuffle() может повлиять на случайность вашего набора данных и, следовательно, порядок, в котором создаются элементы.buffer_size вDataset.prefetch() влияет только на время, необходимое для создания следующего элемента.

buffer_size аргумент вtf.data.Dataset.prefetch() иoutput_buffer_size аргумент вtf.contrib.data.Dataset.map() обеспечить способ настройкипредставление вашего входного конвейера: оба аргумента говорят TensorFlow создать максимум буферbuffer_size элементы и фоновый поток для заполнения этого буфера в фоновом режиме. (Обратите внимание, что мы удалилиoutput_buffer_size аргумент отDataset.map() когда он переехал изtf.contrib.data вtf.data, Новый код должен использоватьDataset.prefetch() послеmap() чтобы получить такое же поведение.)

Добавление буфера предварительной выборки может повысить производительность, перекрывая предварительную обработку данных и последующие вычисления. Как правило, наиболее полезно добавить небольшой буфер предварительной выборки (возможно, с одним элементом) в самом конце конвейера, но более сложные конвейеры могут выиграть от дополнительной предварительной выборки, особенно когда время для создания одного элемента может изменяться.

В отличие отbuffer_size аргументtf.data.Dataset.shuffle() влияет нахаотичность трансформации. Мы разработалиDataset.shuffle() преобразование (например,tf.train.shuffle_batch() функция, которую он заменяет) для обработки наборов данных, которые слишком велики, чтобы поместиться в памяти. Вместо того, чтобы перетасовывать весь набор данных, он поддерживает буферbuffer_size элементы и случайным образом выбирает следующий элемент из этого буфера (заменяя его следующим входным элементом, если таковой имеется). Изменение значенияbuffer_size влияет на равномерность перетасовки: еслиbuffer_size больше, чем количество элементов в наборе данных, вы получите равномерное перемешивание; если это1 тогда вы не будете тасовать вообще. Для очень больших наборов данных типичный «достаточно хороший» подход состоит в том, чтобы случайным образом разбить данные на несколько файлов перед началом обучения, затем равномерно перемешать имена файлов и затем использовать меньший буфер перемешивания. Тем не менее, правильный выбор будет зависеть от точного характера вашей учебной работы.

 Bs He10 июл. 2018 г., 23:20
Для этого объяснения у меня все еще есть некоторые беспорядки w.r.ttf.data.Dataset.shuffle(), Я хотел бы знать точный процесс перетасовки. Скажи первыйbatch_size образцы случайным образом выбираются из первогоbuffer_size элементы и так далее.
 max04 янв. 2019 г., 07:45
@mrry IIUC перемешивание имен файлов важно, потому что в противном случае каждая эпоха будет видеть один и тот же элемент в пакетах 0 ... 999; и партиями 1000.1999; и т.д., где я предполагаю, что 1 файл = 1000 пакетов. Даже с перестановкой имен файлов все же есть некоторая неслучайность: это потому, что примеры из файла #k все близки друг к другу в каждую эпоху. Это может быть не так уж плохо, поскольку сам файл #k является случайным; все же в некоторых случаях даже это может испортить обучение. Единственный способ получить идеальное перемешивание - установитьbuffer_size равный размер файла (и, конечно, перемешать файлы).
Важностьbuffer_size вshuffle()

важность изbuffer_size вtf.data.Dataset.shuffle().

Имея низкийbuffer_size не просто даст вамнизшая перетасовка в некоторых случаях: это может испортить всю вашу подготовку.

Практический пример: классификатор кошек

Предположим, например, что вы обучаете классификатора кошек на изображениях, и ваши данные организованы следующим образом (с10000 изображения в каждой категории):

train/
    cat/
        filename_00001.jpg
        filename_00002.jpg
        ...
    not_cat/
        filename_10001.jpg
        filename_10002.jpg
        ...

Стандартный способ ввода данных сtf.data может иметь список имен файлов и список соответствующих меток, и использоватьtf.data.Dataset.from_tensor_slices() чтобы создать набор данных:

filenames = ["filename_00001.jpg", "filename_00002.jpg", ..., 
             "filename_10001.jpg", "filename_10002.jpg", ...]
labels = [1, 1, ..., 0, 0...]  # 1 for cat, 0 for not_cat

dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.shuffle(buffer_size=1000)  # 1000 should be enough right?
dataset = dataset.map(...)  # transform to images, preprocess, repeat, batch...

большая проблема С помощью приведенного выше кода набор данных на самом деле не будет перетасовываться правильным образом. Примерно в первой половине эпохи мы будем видеть только изображения кошек, а во второй половине только изображения не кошек. Это сильно повредит тренировкам.
В начале обучения набор данных примет первый1000 имена файлов и поместите их в свой буфер, затем выберите один из них случайным образом. Так как все первые1000 изображения являются изображениями кошки, мы только выберем изображения кошки в начале.

Исправление здесь, чтобы убедиться, чтоbuffer_size больше чем20000или перемешать заранееfilenames а такжеlabels (с такими же показателями, очевидно).

Поскольку хранение всех имен файлов и меток в памяти не является проблемой, мы можем использоватьbuffer_size = len(filenames) чтобы убедиться, что все будет перемешано вместе. Обязательно позвониtf.data.Dataset.shuffle() перед применением тяжелых преобразований (таких как чтение изображений, их обработка, пакетная обработка ...).

dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.shuffle(buffer_size=len(filenames)) 
dataset = dataset.map(...)  # transform to images, preprocess, repeat, batch...

Вывод состоит в том, чтобы всегда перепроверять, что будет делать тасование. Хорошим способом отловить эти ошибки может быть построение графика распределения пакетов по времени (убедитесь, что пакеты содержат примерно то же распределение, что и обучающий набор, наполовину кошка и наполовину не кошка в нашем примере).

 Olivier Moindrot11 июл. 2018 г., 11:07
Следующий образец всегда выбирается из буфера (размером 1000 здесь). Таким образом, первый образец взят из первых 1000 имен файлов. Буфер уменьшается до размера 999, поэтому он принимает следующий вход (filename_01001) и добавляет это. Вторая выборка берется случайным образом из этих 1000 имен файлов (1001 первых имен файлов минус первая выборка).
 Olivier Moindrot11 июл. 2018 г., 11:08
Проблема с этим небольшим размером буфера в том, что у вас будут только кошки в ваших первых партиях. Так что модель будет тривиально научиться прогнозировать только «кота». Лучший способ тренировать сеть - это иметь партии с одинаковым количеством «кошек» и «не кошек».
 Elona Mishmika11 сент. 2018 г., 09:05
Есть ли у tenorflow прямой способ составления графика распределения партий?
 Ujjwal04 янв. 2018 г., 19:15
Спасибо. Это феноменально четкий ответ :)
 Bs He10 июл. 2018 г., 23:32
Тогда скажите, как выбран второй образец? Случайно выбранный из массива[filename_01001, ...filename_02000]? Или быть выбранным по-другому? Между тем, я не понимаю, почему использование изображения кошки в самом начале проблематично, и почему так важна самая первая выборка?

что @ olivier-moindrot действительно правильный, я попробовал код, предоставленный @Houtarou Oreki, используя модификации, указанные @max. Код, который я использовал, был следующим:

fake_data = np.concatenate((np.arange(1,500,1),np.zeros(500)))

dataset = tf.data.Dataset.from_tensor_slices(fake_data)
dataset=dataset.shuffle(buffer_size=100)
dataset = dataset.batch(batch_size=10)
iterator = dataset.make_initializable_iterator()
next_element=iterator.get_next()

init_op = iterator.initializer

with tf.Session() as sess:
    sess.run(init_op)
    for i in range(50):
        print(i)
        salida = np.array(sess.run(next_element))
        print(salida)
        print(salida.max())

Выходной код был действительно числом в диапазоне от 1 до (buffer_size + (i * batch_size)), гдеi это количество раз вы бежалиnext_element, Я думаю, что это работает следующим образом. Первый,размер буфера образцы выбираются в порядке отfake_data, Затем один за другимразмер партии образцы выбираются из буфера. Каждый раз, когда пакетный образец выбирается из буфера, он заменяется новым, взятым в порядке отfake_data, Я проверил эту последнюю вещь, используя следующий код:

aux = 0
for j in range (10000):
    with tf.Session() as sess:
        sess.run(init_op)
        salida = np.array(sess.run(next_element))
        if salida.max() > aux:
            aux = salida.max()

print(aux)

Максимальное значение, полученное с помощью кода, составило 109. Поэтому вам необходимо обеспечить сбалансированный образец в пределах вашегоразмер партии обеспечить равномерный отбор проб во время обучения.

Я также проверил, что @mrry говорит о производительности, я обнаружил, чторазмер партии будет предварительно загружать это количество сэмплов в память. Я проверил это, используя следующий код:

dataset = dataset.shuffle(buffer_size=20)
dataset = dataset.prefetch(10)
dataset = dataset.batch(batch_size=5)

Изменениеdataset.prefetch (10) сумма не привела к изменению используемой памяти (RAM). Это важно, когда ваши данные не помещаются в оперативную память. Я думаю, что лучший способ - перетасовать ваши data / file_names перед передачей их в tf.dataset, а затем контролировать размер буфера, используяразмер буфера.

Вы можете проверить это путем создания имен файлов и меток, которые он / она упоминает, и распечатывать значения в случайном порядке.

Вы увидите, что каждая процедура случайного выбора будет генерировать выборку случайным образом с размером, равным размеру буфера из набора данных.

dataset = dataset.shuffle(buffer_size=1000)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
    for i in range(1000):
        print(sess.run(next_element))

Код

import tensorflow as tf
def shuffle():
    ds = list(range(0,1000))
    dataset = tf.data.Dataset.from_tensor_slices(ds)
    dataset=dataset.shuffle(buffer_size=500)
    dataset = dataset.batch(batch_size=1)
    iterator = dataset.make_initializable_iterator()
    next_element=iterator.get_next()
    init_op = iterator.initializer
    with tf.Session() as sess:
        sess.run(init_op)
        for i in range(100):
            print(sess.run(next_element), end='')

shuffle()

Выход

[298] [326] [2] [351] [92] [398] [72] [134] [404] [378] [238] [131] [369] [324] [35] [182] [441 ] [370] [372] [144] [77] [11] [199] [65] [346] [418] [493] [343] [444] [470] [222] [83] [61] [ 81] [366] [49] [295] [399] [177] [507] [288][524][401] [386] [89] [371] [181] [489] [172] [159] [195] [232] [160] [352] [495] [241] [435] [127] [268 ] [429] [382] [479][519][116] [395] [165] [233] [37] [486][553][111][525][170][571][215][530][47] [291][558][21] [245][514][103] [45][545][219] [468] [338] [392] [54] [139] [339] [448] [471][589][321] [223] [311] [234] [314]

 Alex18 февр. 2019 г., 22:32
Это указывает на то, что для каждого элемента, полученного итератором, буфер заполняется соответствующим следующим элементом набора данных, которого раньше не было в буфере.

Ваш ответ на вопрос