Хороше питання.
Я кілька разів стикався з цим явищем. Ось мої спостереження:
Градієнтний підрив
Причина: великі градієнти відхиляють процес навчання.
Що слід очікувати: Переглядаючи журнал виконання, слід дивитись на значення втрат за ітерацію. Ви помітите, що втрати починають значно зростати від ітерації до ітерації, врешті-решт втрата буде занадто великою, щоб бути представленою змінною з плаваючою комою, і вона стане nan.
Що ви можете зробити: Зменшіть base_lr(у розв'язувальному протоколі) на порядок (принаймні). Якщо у вас є кілька шарів втрат, слід перевірити журнал, щоб побачити, який шар відповідає за loss_weightвибух градієнта, і зменшити (у train_val.prototxt) для цього конкретного шару, замість загальногоbase_lr .
Погана політика та параметри навчання
Причина: caffe не може обчислити дійсну швидкість навчання і отримує'inf' або 'nan'замість цього, ця недійсна швидкість примножує всі оновлення і таким чином анулює всі параметри.
Що слід очікувати: Переглядаючи журнал виконання, ви побачите, що сам рівень навчання стає 'nan', наприклад:
... sgd_solver.cpp:106] Iteration 0, lr = -nan
Що ви можете зробити: виправити всі параметри, що впливають на швидкість навчання у вашому 'solver.prototxt'файлі.
Наприклад, якщо ви використовуєте, lr_policy: "poly"а ви забули визначити max_iterпараметр, у підсумку ви отримаєте lr = nan...
Більше інформації про швидкість навчання в caffe див. У цій темі .
Несправна функція втрати
Причина: Іноді обчислення збитків у шарах збитків призводить nanдо появи s. Наприклад, ГодуванняInfogainLoss шару з ненормованими значеннями , використання спеціального шару втрат з помилками тощо.
Що слід очікувати: Переглядаючи журнал виконання, ви, мабуть, не помітите нічого незвичного: втрати поступово зменшуються, і раптом nanз’являється a .
Що ви можете зробити: подивіться, чи можете ви відтворити помилку, додати роздруківку до шару втрат і налагодити помилку.
Наприклад: Одного разу я використав програш, який нормалізував покарання за частотою появи етикетки в партії. Так трапилося, що якщо одна з навчальних міток взагалі не відображалася в партії - обчислена втрата давала nans. У цьому випадку роботи з достатньо великими партіями (щодо кількості міток у наборі) було достатньо, щоб уникнути цієї помилки.
Помилка введення
Причина: вас є вхідні дані nan!
Що слід очікувати: як тільки процес навчання "потрапляє" на цей несправний вхід - вихід стаєnan . Переглядаючи журнал виконання, ви, мабуть, не помітите нічого незвичного: втрати поступово зменшуються, і раптом nanз'являється a .
Що ви можете зробити: заново побудуйте набори вхідних даних (lmdb / leveldn / hdf5 ...), переконайтесь, що у вас немає поганих файлів зображень у вашому навчальному / перевірочному наборі. Для налагодження ви можете створити просту мережу, яка зчитує вхідний рівень, має фіктивну втрату поверх нього і проходить через усі входи: якщо один з них несправний, ця фіктивна мережа також повинна створити nan.
крок більше "Pooling"шару, ніж розмір ядра
З якоїсь причини вибір stride> kernel_sizeдля об'єднання може призвести до nans. Наприклад:
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
результати з nans вy .
Нестабільність у "BatchNorm"
Повідомлялося, що за деяких параметрів "BatchNorm"рівень може виводити nans через числові нестабільності.
Цю проблему порушено у bvlc / caffe, і PR # 5136 намагається її виправити.
Нещодавно я дізнався про debug_infoпрапорі: установка debug_info: trueв 'solver.prototxt'змусить Caffe друк увійти більше налагоджувальної інформації ( в тому числі градієнтні величин і значень активації) під час тренування: Ця інформація може допомогти в плямистість градієнтні роздуття та інші проблеми в процесі навчання .