GPU не хватает памяти при обучении сверточной нейронной сети на Tensorflow

Я использую сверточную нейронную сеть для обучения набора из ~ 9000 изображений (300x500) на GTX1080 Ti с использованием Tensorflow 1.9, но каждый раз сталкиваюсь с проблемой превышения памяти. Я получаю предупреждение о превышении системной памяти на 10%, и через несколько минут процесс завершается. Мой код ниже.

import tensorflow as tf
from os import listdir

train_path = '/media/NewVolume/colorizer/img/train/'  
col_train_path = '/media/NewVolume/colorizer/img/colored/train/'
val_path = '/media/NewVolume/colorizer/img/val/'
col_val_path = '/media/NewVolume/colorizer/img/colored/val/'

def load_image(image_file):
    image = tf.read_file(image_file)
    image = tf.image.decode_jpeg(image)
    return image

train_dataset = []
col_train_dataset = []
val_dataset = []
col_val_dataset = []

for i in listdir(train_path): 
    train_dataset.append(load_image(train_path + i))
    col_train_dataset.append(load_image(col_train_path + i))

for i in listdir(val_path): 
    val_dataset.append(load_image(val_path + i))
    col_val_dataset.append(load_image(col_val_path + i))

train_dataset = tf.stack(train_dataset)
col_train_dataset = tf.stack(col_train_dataset)
val_dataset = tf.stack(val_dataset)
col_val_dataset = tf.stack(col_val_dataset)

input1 = tf.placeholder(tf.float32, [None, 300, 500, 1])
color = tf.placeholder(tf.float32, [None, 300, 500, 3])

#MODEL

conv1 = tf.layers.conv2d(inputs = input1, filters = 8, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
pool1 = tf.layers.max_pooling2d(inputs = conv1, pool_size=[2, 2], strides=2)
conv2 = tf.layers.conv2d(inputs = pool1, filters = 16, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
pool2 = tf.layers.max_pooling2d(inputs = conv2, pool_size=[2, 2], strides=2)
conv3 = tf.layers.conv2d(inputs = pool2, filters = 32, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
pool3 = tf.layers.max_pooling2d(inputs = conv3, pool_size=[2, 2], strides=2)

flat = tf.layers.flatten(inputs = pool3)
dense = tf.layers.dense(flat, 2432, activation = tf.nn.relu)
reshaped = tf.reshape(dense, [tf.shape(dense)[0],38, 64, 1])

conv_trans1 = tf.layers.conv2d_transpose(inputs = reshaped, filters = 32, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
upsample1 = tf.image.resize_nearest_neighbor(conv_trans1, (2*tf.shape(conv_trans1)[1],2*tf.shape(conv_trans1)[2]))

conv_trans2 = tf.layers.conv2d_transpose(inputs = upsample1, filters = 16, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
upsample2 = tf.image.resize_nearest_neighbor(conv_trans2, (2*tf.shape(conv_trans2)[1],2*tf.shape(conv_trans2)[2]))
conv_trans3 = tf.layers.conv2d_transpose(inputs = upsample2, filters = 8, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')
upsample3 = tf.image.resize_nearest_neighbor(conv_trans3, (2*tf.shape(conv_trans3)[1],2*tf.shape(conv_trans3)[2]))

conv_trans4 = tf.layers.conv2d_transpose(inputs = upsample3, filters = 3, kernel_size=[5, 5], activation=tf.nn.relu, padding = 'same')

reshaped2 = tf.reshape(dense, [tf.shape(conv_trans4)[0],300,500,3])

#TRAINING

loss = tf.losses.mean_squared_error(color, reshaped2)
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)

EPOCHS = 10
BATCH_SIZE = 3

dataset = tf.data.Dataset.from_tensor_slices((train_dataset,col_train_dataset)).repeat().batch(BATCH_SIZE)
iterator = dataset.make_one_shot_iterator()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(EPOCHS):
        x,y=iterator.get_next()
        _, loss_value = sess.run([train_step, loss],feed_dict={input1:x.eval(session=sess),color:y.eval(session=sess)})
        print("Iter: {}, Loss: {:.4f}".format(i, loss_value))

person Cheshta Dhingra    schedule 20.08.2018    source источник
comment
Если вы получаете ту же ошибку даже с размером пакета 1, это означает, что вы загружаете слишком много изображений, и ваша оперативная память не может их обработать. Рассмотрите возможность использования tfrecord.   -  person HSK    schedule 20.08.2018
comment
Рассматриваемый код имеет входную форму [300,500,1] и размер пакета 3. Карта 1080 Ti имеет около 12 ГБ ОЗУ. Я почти уверен, что они не загружают слишком много изображений. Но я подозреваю, что сама их сеть может быть слишком большой.   -  person Mad Wombat    schedule 20.08.2018
comment
Не могли бы вы поместить краткое описание модели, например model.summary() в Keras. Сколько у вас обучаемых параметров?   -  person Nathan Explosion    schedule 20.08.2018


Ответы (1)


Я думаю, что ваша проблема заключается в следующем фрагменте кода.

def load_image(image_file):
    image = tf.read_file(image_file)
    image = tf.image.decode_jpeg(image)
    return image
...

for i in listdir(train_path): 
    train_dataset.append(load_image(train_path + i))
    col_train_dataset.append(load_image(col_train_path + i))

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

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

person Mad Wombat    schedule 20.08.2018