Проблемы производительности для сети на базе Keras 1D ResNeXT - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь использовать архитектуру типа ResNeXT для классификации некоторых пар сигналов длиной 77.Тем не менее, даже при относительно скромных 38 тыс. Параметрах, модель непристойно медленно запускается, около 12 дней в течение 60 млн. Тренировочных примеров.Использование памяти также колеблется вверх и вниз на ~ 10 ГБ, что говорит о том, что что-то не так с распределением и сборкой мусора.

Я бы ожидал, что 1D-модель будет относительно быстрой, учитывая, что эти модели обычно применяются к изображениям гораздо большего размера и с большим количеством слоев.

Я пробовал профилировать Keras с помощьюtenorflow-chrome, но получают только пустые выходные файлы.Есть ли что-то не так с подходом, который я использую, и как я могу эффективно диагностировать и оптимизировать проблемы с производительностью в моделях keras?

Кроме того, модель немного сходит с ума (занимая 100% ЦП и блокируявесь компьютер, если только для ядер ЦП не установлено ограничение 1)

Увеличение размера пакета с 5000 до 50000 увеличивает колебания использования памяти и занимает всю доступную (64 ГБ) память).Уменьшение его до 500 останавливает большие колебания, но оценки времени обучения все еще находятся в диапазоне 200+ часов для эпохи.

Правильная установка CUDA9 + cudnn + tenorflow-gpu уменьшает ожидаемое время выполнения примерно в 2–100 раз.часов в эпоху.Загрузка процессора все еще высока, а загрузка графического процессора низкая, но больше не блокируется.

Я без проблем запускаю другие модели с большим количеством параметров, поэтому я предполагаю, что это как-то связано с необычной структурой этой конкретной модели..

Код модели:

def relubn(b): 
  return BatchNormalization()(  ReLU()( b ) )


def resnext_1d( layer_in, n_in, n_paths, n_bottleneck, kernel_size ):
  paths = []
  b = Conv1D(n_bottleneck * n_paths,1)( layer_in )  
  b = relubn(b)
  for i in range(0,n_paths):
    group = Lambda(lambda z: z[:, :, i * n_bottleneck:(i + 1) * n_bottleneck])( b )
    c = Conv1D(n_bottleneck,kernel_size, padding='same')( group )
    paths.append( c )

  con  = concatenate(paths)
  comb = Conv1D(n_in,1)( con )  
  comb = relubn( comb )

  return relubn( add( [layer_in, comb] ) )

in1 = Input(shape=(77,2))

l1 = Conv1D(64, (9,), padding='same')( in1 )
l2 = resnext_1d( l1, 64, 8, 4, 9 )
l3 = resnext_1d( l2, 64, 8, 4, 9 )
l4 = resnext_1d( l3, 64, 8, 4, 9 )
l5 = resnext_1d( l4, 64, 8, 4, 9 )
l6 = resnext_1d( l5, 64, 8, 4, 9 )
l7 = resnext_1d( l6, 64, 8, 4, 9 )
l8 = resnext_1d( l6, 64, 8, 4, 9 )
ap = GlobalAveragePooling1D()( relubn(l8) ) # 64x1

out_class = Dense(28, activation='softmax')( ap ) 

1 Ответ

0 голосов
/ 20 декабря 2018

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

Что касается вашего случая, это выглядитчто приведенный вами частичный, не запускаемый пример не включает всю информацию.Я попытался создать из вашего кода работоспособный пример: я скопировал всю опубликованную вами модель и установил размер пакета 500, а общий #example - 60M.Я использовал поддельные данные.В вашей модели произошла ошибка (l7 не подключен ни к чему), и я сохранил ошибку.

#!/usr/bin/env python

import keras
from keras.models import Model
from keras.utils import np_utils
from keras.layers import *
import numpy as np

batch_size = 500
nb_classes = 1000
nb_epoch = 200

X_train = np.random.random((batch_size, 77, 2))
Y_train = np.random.random((batch_size,)).astype('int32')
Y_train = np_utils.to_categorical(Y_train, 28)

def gen():
    while True:
        yield (X_train, Y_train)


def relubn(b):
  return BatchNormalization()(  ReLU()( b ) )


def resnext_1d( layer_in, n_in, n_paths, n_bottleneck, kernel_size ):
  paths = []
  b = Conv1D(n_bottleneck * n_paths,1)( layer_in )
  b = relubn(b)
  for i in range(0,n_paths):
    group = Lambda(lambda z: z[:, :, i * n_bottleneck:(i + 1) * n_bottleneck])( b )
    c = Conv1D(n_bottleneck,kernel_size, padding='same')( group )
    paths.append( c )

  con  = concatenate(paths)
  comb = Conv1D(n_in,1)( con )
  comb = relubn( comb )

  return relubn( add( [layer_in, comb] ) )

in1 = Input(shape=(77,2))
l1 = Conv1D(64, (9,), padding='same')( in1 )
l2 = resnext_1d( l1, 64, 8, 4, 9 )
l3 = resnext_1d( l2, 64, 8, 4, 9 )
l4 = resnext_1d( l3, 64, 8, 4, 9 )
l5 = resnext_1d( l4, 64, 8, 4, 9 )
l6 = resnext_1d( l5, 64, 8, 4, 9 )
#l7 = resnext_1d( l6, 64, 8, 4, 9 )
l8 = resnext_1d( l6, 64, 8, 4, 9 )
ap = GlobalAveragePooling1D()( relubn(l8) ) # 64x1
out_class = Dense(28, activation='softmax')( ap )
model = Model(in1, out_class)
model.summary()
model.compile(loss='categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])
model.fit_generator(gen(), epochs=nb_epoch, steps_per_epoch=60000000 // batch_size)
#model.fit_generator(gen(), epochs=nb_epoch, steps_per_epoch=200)

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

Как я уже упоминал в комментарии, сам Keras работает медленно, поэтому я перевожу приведенный выше код в его эквивалент в tenorpack.Затем код выполняется со скоростью 1,5 ч / эпоха.

from tensorpack import *
import tensorflow as tf
import numpy as np

batch_size = 500

X_train = np.random.random((batch_size, 77, 2))
Y_train = np.random.random((batch_size,)).astype('int32')
Y_train = np_utils.to_categorical(Y_train, 28)

def gen():
    while True:
        yield (X_train, Y_train)


def relubn(b):
  ret = tf.layers.batch_normalization(
          tf.nn.relu(b), training=get_current_tower_context().is_training
          )
  return ret


def resnext_1d( layer_in, n_in, n_paths, n_bottleneck, kernel_size ):
  paths = []
  b = tf.layers.conv1d(layer_in, n_bottleneck * n_paths,1)
  b = relubn(b)
  #splits = tf.split(b, n_paths, axis=2)
  for i in range(0,n_paths):
    group = b[:, :, i * n_bottleneck:(i + 1) * n_bottleneck]
    #group = splits[i]
    c = tf.layers.conv1d(group, n_bottleneck,kernel_size, padding='same')
    paths.append( c )

  con  = tf.concat(paths, axis=-1)
  comb = tf.layers.conv1d(con,n_in,1)
  comb = relubn( comb )

  return relubn( layer_in+ comb)

def tower_func(input, labels):
    l1 = tf.layers.conv1d(input, 64, (9,), padding='same')
    l2 = resnext_1d( l1, 64, 8, 4, 9 )
    l3 = resnext_1d( l2, 64, 8, 4, 9 )
    l4 = resnext_1d( l3, 64, 8, 4, 9 )
    l5 = resnext_1d( l4, 64, 8, 4, 9 )
    l6 = resnext_1d( l5, 64, 8, 4, 9 )
    #l7 = resnext_1d( l6, 64, 8, 4, 9 )
    l8 = resnext_1d( l6, 64, 8, 4, 9 )
    ap = tf.reduce_mean(relubn(l8) , axis=1) # 64x1
    out_class = tf.layers.dense(ap, 28)
    loss = tf.nn.softmax_cross_entropy_with_logits_v2(labels=labels,
            logits=out_class)
    return tf.reduce_mean(loss)

trainer = SimpleTrainer()
trainer.setup_graph(
        inputs_desc=[InputDesc(tf.float32, [None, 77, 2], 'images'),
                     InputDesc(tf.float32, [None, 28], 'labels')],
        input=QueueInput(DataFromGenerator(gen)),
        get_cost_fn=tower_func,
        get_opt_fn=lambda: tf.train.GradientDescentOptimizer(1e-3)
        )
trainer.train_with_defaults(
        steps_per_epoch=60000000//batch_size
        )

Упомянутая выше операция разбиения, похоже, не влияет на скорость.

Мое окружение: GTX1080Ti;питон 3.6;куда 10;cudnn 7.4.1;тензор потока ночных сборок вчера;Керас 2.2.4;тензорпак мастер по состоянию на 19 декабря;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...