У меня проблема с вычислением сокращения функции сети, представленной большой (200000x200000) матрицей, сгенерированной как матрица расстояний между парами точек.Управление памятью Tensorflow - chunking?
Минимальный пример, вход X A 200000x2 Numpy массив декартовых координат:
x = tf.constant(X[:,0], shape=[X.shape[0],1])
y = tf.constant(X[:,1], shape=[X.shape[0],1])
dx = x - tf.transpose(x)
dy = y - tf.transpose(y)
D = tf.sqrt(dx*dx + dy*dy)
M = 0.1 * 5.0/tf.pow(4.0 + D, 1.5)
res = tf.reduce_sum(betaM)
, работающие на процессоре, памяти (16 Гб на моем MBP) быстро превысил предложение, и система перемалывает к остановке. Предположительно tf пытается хранить в памяти все D (и M?).
Если бы я писал это на C/C++, я бы, скорее всего, переместил строки матрицы, суммируя каждую строку, когда я иду, и никогда не сохраняю всю матрицу. Тоже GPU - я бы разделил (виртуальную) матрицу и выполнил сокращение кусков.
Есть ли трюк, чтобы получить tf, чтобы следить за более частым поведением, экономя память?
Приветствия,
Криса
РЕДАКТИРОВАТЬ:
Альтернативный подход, который справляется с проблемой памяти является использование tf.map_fn
:
rowsums = tf.map_fn(lambda i: tf.reduce_sum(tf.sqrt(tf.reduce_sum(tf.pow(i - x,2),1))) , x)
res = tf.reduce_sum(rowsums)
Таким образом, только rowsums сохраняются в виде тензор, а не матрицу полного расстояния. Однако, хотя этот подход хорошо работает на процессоре, он останавливается на GPU.
Привет, Ярослав, не могли бы вы немного подробнее узнать, как вы оцениваете использование памяти? У меня, что D максимально требует хранения 8 * 200000^2 ~ 300 ГБ, и примерно половину этого (игнорируя диагональ) в виде треугольной матрицы. Благодаря! –
Дох, я был на 1000. Да, это кажется неосуществимым для хранения в памяти. Вы можете обрабатывать свои данные так же, как TF обрабатывает наборы данных во время обучения, загружая их только в куски. Вы можете использовать два набора 'SliceInputProducer' +' batch' для создания фрагментов и дважды вложенный цикл для их итерации по ним. –
Чтобы быть более подробным, вы можете использовать 'SliceInputProducer' +' batch' + 'assign' для сохранения подмножества указывает на переменную 'subset1' при каждом вызове run (run1), тогда у вас также есть отдельный' SliceInputProducer' + 'batch' +' assign', чтобы сохранить подмножество точек в переменной 'subset2' для каждого вызова вызова (run2). Вы выполняете run1 во внешнем цикле и run2 во внутреннем цикле. Наконец, у вас есть некоторая логика, которая принимает переменные 'subset1' и' subset2' и вычисляет все попарные расстояния между ними и добавляет к вашей общей сумме, это ваша третья команда запуска (run3) –