Вес модели Keras для некоторых слоев становится все "NaN"

Я тренирую триплетную модель, похожую на -Все параметры модели Keras - NaN после перезагрузки.; за исключением того, что эта модель построена на модели inception_v3.

(Я использую Keras с бэкэндом Tensorflow)

Но уже через 2 эпохи веса модели оказываются NaN. И когда я пытаюсь извлечь изученные функции, передав входное изображение, все функции равны 0.

Модель Архитектура

def triplet_loss (x, АЛЬФА = 0,2):

anchor, positive, negative = x                                      

pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), 1)
neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), 1)

basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), ALPHA)         
loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0), 0)               

return loss                                                         

класс StyleNet ():

def __init__(self, input_shape_x, input_shape_y, input_shape_z, n_classes, reg_lambda):

    self.input_shape_x = input_shape_x                              
    self.input_shape_y = input_shape_y                              
    self.input_shape_z = input_shape_z                              
    self.n_classes = n_classes                                      
    self.reg_lambda = reg_lambda                                    


def create_model(self):                                             

    anchor_example = Input(shape=(self.input_shape_x, self.input_shape_y, self.input_shape_z), name='input_1')
    positive_example = Input(shape=(self.input_shape_x, self.input_shape_y, self.input_shape_z), name='input_2')
    negative_example = Input(shape=(self.input_shape_x, self.input_shape_y, self.input_shape_z), name='input_3')

    input_image = Input(shape=(self.input_shape_x, self.input_shape_y, self.input_shape_z))

    base_inception = InceptionV3(input_tensor = input_image, input_shape=(self.input_shape_x, self.input_shape_y, self.input_shape_z), weights=None, include_top=False, pooling='avg')
    base_pool5 = base_inception.output                              

    ##############Adding the Bottleneck layer Here#######################################################
    bottleneck_layer = Dense(256, kernel_regularizer=l2(self.reg_lambda), name='bottleneck_layer')(base_pool5)
    bottleneck_norm = BatchNormalization(name='bottleneck_norm')(bottleneck_layer)
    bottleneck_relu = Activation('relu', name='bottleneck_relu')(bottleneck_norm)
    bottleneck_drop = Dropout(0.5)(bottleneck_relu)                 

    fin = Dense(self.n_classes)(bottleneck_drop)                    
    fin_norm = BatchNormalization(name='fin_norm')(fin)             
    fin_softmax = Activation('softmax')(fin_norm)                   
    ######################################################################################################

    ###########Triplet Model Which learns the embedding layer relu6####################
    self.triplet_model = Model(input_image, bottleneck_drop)        
    positive_embedding = self.triplet_model(positive_example)       
    negative_embedding = self.triplet_model(negative_example)       
    anchor_embedding = self.triplet_model(anchor_example)           
    ###########Triplet Model Which learns the embedding layer relu6####################

    adam_opt = optimizers.Adam(lr=0.00001, clipnorm = 1.0, amsgrad=False)

    #The Triplet Model which optimizes over the triplet loss.       
    loss = Lambda(triplet_loss, output_shape=(1,))([anchor_embedding, positive_embedding, negative_embedding])
    self.triplet_model_worker = Model(inputs=[anchor_example, positive_example, negative_example], outputs = loss)
    self.triplet_model_worker.compile(loss='mean_absolute_error', optimizer=adam_opt)

def fit_model(self, pathname='./models/'):                          
    if not os.path.exists(pathname):                                
        os.makedirs(pathname)                                       
    if not os.path.exists(pathname+'/weights'):                     
        os.makedirs(pathname+'/weights')                            
    if not os.path.exists(pathname+'/tb'):                          
        os.makedirs(pathname+'/tb')                                 
    filepath=pathname+"weights/{epoch:02d}.hdf5"                    
    checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=False, mode='auto')
    tensorboard = TensorBoard(log_dir=pathname+'/tb', write_graph=True, write_images=True)
    callbacks_list = [checkpoint, tensorboard]                      

    #Parameter                                                              
    params = {'dim': (224, 224), 'batch_size':32, 'n_classes':11, 'n_channels':3, 'shuffle':True}

    #Datasets                                                               
    partition = pickle.load(open('../../../data/bam_2_partition_triplet.pkl', 'rb'))
    labels = pickle.load(open('../../../data/bam_2_labels_triplet.pkl', 'rb'))

    #Generators                                                             
    training_generator = DataGenerator(partition['train'], labels, **params)
    self.triplet_model_worker.fit_generator(generator = training_generator,  epochs = 60, use_multiprocessing=True, workers = 10, callbacks = callbacks_list, verbose = 1)

То, что вызывает беспокойство, описано в приведенной выше ссылке. Даже после использования *** clipnorm = 1.0 **** градиенты взрываются, а веса выдают значения "nan".

Сохранение и загрузка модели, затем печать весов. NaN хорошо видны. Код загрузки:

m = load_model('/scratch/models_inception_stage2/yo/weights/02.hdf5', custom_objects = {"tf":tf})

for layer in m.layers:                                                  
    weights = layer.get_weights()                                       
    print (weights)

Фрагмент распечатанных гирь

Here
[array([ 3.4517611e-04,  1.3431008e-03, -1.1081886e-03,  2.6104850e-04,
   -2.1620051e-04,  1.6816283e-03,  8.8927911e-05, -3.8964470e-04,
    1.7968584e-03,  1.0259283e-03,  5.0400384e-04, -3.6578919e-04,
   -1.1292399e-03,  1.1509922e-03,  3.2478449e-04, -3.6580343e-05,
   -4.4458261e-04,  4.8210021e-04, -9.5213606e-04, -6.4406055e-04,
    5.0959276e-04, -3.4098624e-04, -7.0486858e-05,  2.8134760e-04,
   -8.0100907e-04,  8.2962180e-04, -6.4140803e-04,  9.4872032e-04,
   -3.3409546e-05, -3.0277384e-04,  5.2237371e-04, -8.3427120e-04,
   -2.5856070e-04, -1.0346439e-03,  4.3354488e-05, -8.8099617e-04,
   -6.8233605e-04, -1.2386916e-04,  8.2019303e-04, -1.9070004e-03,
    1.5571159e-03, -3.4599879e-04,  6.2088901e-04, -8.4720332e-06,
    1.6024955e-04, -1.2059419e-03, -1.4946899e-04, -6.7080715e-04,
   -2.8154058e-05,  5.1517348e-04,  5.9993083e-05,  2.8555689e-04,
    3.9626448e-04, -5.1538437e-04,  1.9132573e-04,  1.1226863e-03,
    1.1591403e-03, -6.3404470e-04,  2.8910063e-04, -7.9366821e-04,
   -1.7228167e-04,  6.2899920e-04,  1.7438219e-04,  1.1385380e-04],
  dtype=float32), array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
   nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
   nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
   nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
   nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan],
  dtype=float32), array([0.50248814, 0.48732147, 0.64627343, 0.49432775, 0.45906776,
   0.5168214 , 0.8561428 , 0.7308014 , 0.5067555 , 0.516555  ,
   1.3287057 , 0.5746422 , 0.55597156, 1.0038179 , 0.9859771 ,
   0.6110601 , 0.7357226 , 0.6123694 , 0.90676117, 0.5439505 ,
   0.48629472, 0.5434108 , 0.4934845 , 0.5407317 , 0.6443982 ,
   1.0403991 , 0.48624724, 0.83786434, 0.72478205, 0.7294607 ,
   0.536994  , 0.38235992, 1.0484552 , 0.45833316, 0.48205158,
   0.48236838, 0.71035874, 0.9472658 , 0.78085536, 1.0207686 ,
   0.5089741 , 0.97984046, 0.86524594, 0.9828817 , 0.49027866,
   0.7367909 , 0.57438385, 0.5011991 , 0.47189236, 0.52376693,
   0.45648402, 0.40523565, 0.8375675 , 0.57908285, 0.6055632 ,
   1.0325785 , 0.5377976 , 0.47033092, 0.83586556, 1.2780553 ,
   0.503384  , 0.54509026, 0.5375585 , 0.6091993 ], dtype=float32)]

Буду признателен за любую помощь.

Вы пробовали повысить скорость обучения?

kvish 20.11.2018 21:37

Нет, я этого не пробовал. Хотя я не уверен, возможно, я пробовал с 0,0001. Может ли повышение скорости обучения решить эту проблему? Я не понимаю, как бы это было?

Sid Gairola 20.11.2018 21:56

Кажется, где-то есть какая-то числовая нестабильность. Ваша скорость обучения в сочетании с низким градиентом также может способствовать этому, если ваша скорость довольно низкая. Вот почему мне было интересно, пробовали ли вы более высокие темпы обучения!

kvish 20.11.2018 22:10

Я пробовал со скоростью обучения 0,001. Тот же результат.

Sid Gairola 21.11.2018 09:19

на высоком уровне я не вижу проблем с вашей разводкой сети. Но я не очень разбираюсь в этих деталях, чтобы это комментировать. Это происходит и с другими оптимизаторами? Например SGD?

kvish 22.11.2018 04:37

Я только что пробовал с адамом. Вы бы порекомендовали здесь использовать SGD или какой-нибудь другой оптимизатор?

Sid Gairola 22.11.2018 04:54

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

kvish 22.11.2018 04:59

Еще одна интересная вещь, которую я заметил при печати весов / параметров для каждого слоя, что NaN возникают только на уровнях batch_norm. На что это могло указывать? См. - stackoverflow.com/questions/53830547/…

Sid Gairola 18.12.2018 12:32

это интересно! Если слои батчнорма получают NaN, я бы проверил ваш ввод. BatchNorm делит на дисперсию, так может ли быть, что ваша дисперсия равна нулю для этих мини-батчей? Это может случиться, если все будет одним числом!

kvish 18.12.2018 15:10

Спасибо за ответ. Я вручную проверил ввод и распечатал мини-серию (размер 32). У мини-партий были разные векторы. Для дальнейшего изучения я запускал процесс обучения каждую итерацию за раз. Общий обучающий размер составляет ~ 0,12 млн изображений. Параметры слоя batch_norm становятся NaN где-то до завершения 1-й эпохи. Есть ли другие причины, по которым это могло произойти?

Sid Gairola 20.12.2018 09:44

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

kvish 21.12.2018 05:09

Я использую один графический процессор. (Каждый мини-пакет обучается на одном графическом процессоре.)

Sid Gairola 21.12.2018 07:21

Есть ли шанс, что существует проблема числовой нестабильности, связанная с BN в Keras или Tensorflow, как это было ранее в Caffe? Ссылка: BVLC / caffe # 5136

Sid Gairola 21.12.2018 10:12

Еще одно открытие здесь заключается в том, что сеть изучает NaN для слоев batch_norm, даже когда batch_size = 1. Разве это не странно? Значит ли это, что есть проблема с triplet_loss или разделением весов?

Sid Gairola 21.12.2018 18:37

Batchnorm не имеет смысла, когда размер партии равен 1, потому что как таковая разница отсутствует, верно? Таким образом, размер пакета должен быть больше 1. Если вы используете только один графический процессор, это может не быть связано с проблемой неравномерного разделения данных между графическими процессорами, вызывающих NaN. Я заметил кое-что еще, чего я не заметил сначала. Вес вашего первого слоя кажется очень низким. Это может быть причиной того, что ваша дисперсия действительно очень мала. Вы замораживаете параметры своей сети Inception? А еще можно проверить удаление регуляризатора ядра?

kvish 21.12.2018 19:02

Так что моя текущая работа - это двухэтапный конвейер. Этап 1: Обучение через перекрестную энтропийную потерю 11 меток. Этап 2: Загрузите веса из этапа 1, а затем тренируйте модель триплета. P.S. - 1. Первый этап не имеет разделения весов. Обычная классификационная сеть.

Sid Gairola 22.12.2018 07:02

m.create_model (); m.triplet_model_worker.load_weights (./ models_inception_stage‌ 1 / yo / weights / 20.hdf5‌ ', by_name = True); m.fit_model ('./ models_inception_stage2 /');

Sid Gairola 22.12.2018 07:04

Извините за поздний ответ! Ездили на каникулы. Можете ли вы попробовать тренировку, заморозив веса начальных слоев? Таким образом, вы можете тренировать только те слои, которые вы добавляете поверх, и увеличивать скорость обучения для этого. Может быть, это поможет вам понять, является ли это причиной, по которой ваша сеть переходит к Нан?

kvish 26.12.2018 16:31

Привет! Спасибо за ответ. Попробую и вернусь. Я понимаю, сейчас курортный сезон. Спасибо. Я благодарен за вашу помощь. Также есть вероятность, что что-то не так с самим Керасом. github.com/keras-team/keras/issues/11927

Sid Gairola 31.12.2018 10:27

спасибо, что поделились этой ссылкой. Похоже, команда Keras добавила это как ошибку! В этом случае, надеюсь, они смогут пролить свет на то, что на самом деле происходит за пределами наших предположений :)

kvish 31.12.2018 14:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
20
1 448
0

Другие вопросы по теме