Хороше питання.
Я кілька разів стикався з цим явищем. Ось мої спостереження:
Градієнтний підрив
Причина: великі градієнти відхиляють процес навчання.
Що слід очікувати: Переглядаючи журнал виконання, слід дивитись на значення втрат за ітерацію. Ви помітите, що втрати починають значно зростати від ітерації до ітерації, врешті-решт втрата буде занадто великою, щоб бути представленою змінною з плаваючою комою, і вона стане 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 .
Що ви можете зробити: подивіться, чи можете ви відтворити помилку, додати роздруківку до шару втрат і налагодити помилку.
Наприклад: Одного разу я використав програш, який нормалізував покарання за частотою появи етикетки в партії. Так трапилося, що якщо одна з навчальних міток взагалі не відображалася в партії - обчислена втрата давала nan
s. У цьому випадку роботи з достатньо великими партіями (щодо кількості міток у наборі) було достатньо, щоб уникнути цієї помилки.
Помилка введення
Причина: вас є вхідні дані nan
!
Що слід очікувати: як тільки процес навчання "потрапляє" на цей несправний вхід - вихід стаєnan
. Переглядаючи журнал виконання, ви, мабуть, не помітите нічого незвичного: втрати поступово зменшуються, і раптом nan
з'являється a .
Що ви можете зробити: заново побудуйте набори вхідних даних (lmdb / leveldn / hdf5 ...), переконайтесь, що у вас немає поганих файлів зображень у вашому навчальному / перевірочному наборі. Для налагодження ви можете створити просту мережу, яка зчитує вхідний рівень, має фіктивну втрату поверх нього і проходить через усі входи: якщо один з них несправний, ця фіктивна мережа також повинна створити nan
.
крок більше "Pooling"
шару, ніж розмір ядра
З якоїсь причини вибір stride
> kernel_size
для об'єднання може призвести до nan
s. Наприклад:
layer {
name: "faulty_pooling"
type: "Pooling"
bottom: "x"
top: "y"
pooling_param {
pool: AVE
stride: 5
kernel: 3
}
}
результати з nan
s вy
.
Нестабільність у "BatchNorm"
Повідомлялося, що за деяких параметрів "BatchNorm"
рівень може виводити nan
s через числові нестабільності.
Цю проблему порушено у bvlc / caffe, і PR # 5136 намагається її виправити.
Нещодавно я дізнався про debug_info
прапорі: установка debug_info: true
в 'solver.prototxt'
змусить Caffe друк увійти більше налагоджувальної інформації ( в тому числі градієнтні величин і значень активації) під час тренування: Ця інформація може допомогти в плямистість градієнтні роздуття та інші проблеми в процесі навчання .