Я пытаюсь обучить нейронные сети, используя TensorFlow 1.12.0 и Keras API.
Настройка следующая.У меня есть большое количество точек данных: каждая точка состоит из контекста (назовите его 24 числами с плавающей запятой) и метки (1 числа с плавающей запятой).Общий объем данных составляет O (10 ^ 7) баллов.Тестовые сети различаются, но довольно простой может выглядеть так:
v=[keras.layers.Input(shape=input_shape)]
v.append(keras.layers.Dense(4,use_bias=False,activation=tf.nn.tanh)(v[-1]))
v.append(keras.layers.Dense(1,use_bias=False)(v[-1]))
model=keras.models.Model(inputs=v[0],outputs=v[-1])
optimizer = tf.train.RMSPropOptimizer(0.001)
model.compile(loss='mse', optimizer=optimizer, metrics=['mae'])
(...)
history=model.fit(x=train_data,y=train_labels,epochs=EPOCHS,verbose=1,batch_size=10000, shuffle=True)
Я получаю приличные результаты, храня данные в массивах и передавая их в model.fit () как есть.Тем не менее, я не доволен производительностью.Это кажется узким местом в коде Python (я даже пытался профилировать его, а метод Python slice_arrays в python / keras / utils / generic_utils.py выступает в качестве основного узкого места, причем до половины всего времени там проводится.) Графический процессор (GeForce 1080 Ti) используется, но его использование (как сообщает nvidia-smi) редко превышает 10-15%.
В поисках способа ускорить процесс я попытался преобразовать данные в тензоры:
features=tf.convert_to_tensor(train_data)
labels=tf.convert_to_tensor(train_labels)
history=model.fit(x=features,y=labels,epochs=EPOCHS,verbose=1,steps_per_epoch=20, shuffle=True)
model.fit требует аргумент batch_size при передаче массивов numpy, но steps_per_epoch при передаче тензоров.Документация не ясна, но, похоже, мне нужно установить steps_per_epoch на количество точек данных, деленное на batch_size.Таким образом, я получаю сопоставимые показатели конвергенции.Каким бы ни было значение, загрузка графического процессора составляет 100%, и это хорошо.
Но теперь есть проблема.С массивными массивами время выполнения в эпоху относительно не зависит от размера пакета.Я вижу 8 секунд на эпоху при размере партии 10 тыс., 5 секунд при размере партии 100 тыс. И 7 секунд на эпоху при размере партии 1 млн.Конвергенция обычно лучше, если размер партии небольшой.Таким образом, я обычно начинаю с размера партии 100 КБ или меньше.С другой стороны, при вводе тензора время выполнения для эпох увеличивается экспоненциально с steps_per_epoch.С размером партии 1M (10-20 шагов в эпоху) я нахожусь на уровне 2 с / эпоха, но скорость сходимости ужасна.При размере пакета 10 Кбайт скорость сходимости хорошая, но время до 30 с / эпоха (на самом деле медленнее, чем при numpy, несмотря на 100% использование графического процессора.)
По сути, единственный сценарий, когда ввод тензора на самом делезаканчивается быстрее, это тот, где я не хочу использовать его в первую очередь.
Что происходит и есть ли способ обойти это?