Паралич сети – это явление, при котором глубокие слои не обучаются. Это происходит из-за затухания градиента при обратном распространении ошибки. Затухание градиента может возникнуть из-за большой глубины сети или больших выходных значений.
Почему большая глубина сети приводит к затуханию градиента?
Для разъяснения приведем пример, где пять полносвязных слоёв соединены сигмоидой.
У выбранной функции активации производная не превышает 1/4, значит градиент каждый раз, проходя через нее, будет умножаться на число не большее 1/4. Если в сети 5 функций активаций, то к самому глубокому слою градиент будет умножен на (1/4)^5, что равно 1/1024. Было бы в сети 10 слоев, градиент уменьшился бы в миллионы раз.
Почему большие выходные значения приводят к затуханию градиента?
Попробуем взять другую функцию активации, у которой производная достигает единицы, например, гиперболический тангенс. В этом случае, как и в предыдущем, у функции есть плато, на котором значение почти не меняется. Если выходные значения слоя будут достаточно большими, градиент будет умножаться на очень маленькие значения, потому что производная в точках, удаленных от центра оси, почти нулевая.
Как избежать паралича сети?
Сменить функцию активации
Можно попробовать сменить функцию активации на ReLU. У нее в положительной части оси производная всегда равна единице. Казалось бы, что градиент будет проходить по сети без потерь, но в части случаев он не будет походить дальше. Если выходы слоя центрированы, то в половине случаев значения градиента не пройдут дальше и станут равными нулю. Теперь градиенту пройти через пять слоев уже проще, но проблема с затуханием осталась.
Leaky ReLU и ELU немного помогают ситуации, но глобально ее не меняют.
Нормализовать данные
Например, можно использовать batch normalization. В этом случае выходные значения будут реже выходить на плато функции активации. Это позволит реже умножать градиент на нулевые значения.
Модифицировать архитектуру сети
В GoogLeNet использовали дополнительные функции потерь у глубоких слоев, тем самым обучая их той же самой задаче. Это подпитывало обновление весов на глубоких слоях сети. В нашей статье важны части в красных эллипсах на изображении, через них и проходят дополнительные функции потерь.
В ResNet использовались Residual блоки. В этих блоках к результату работы слоев добавляют входные данные. Таким образом, градиент не затухает и приводит к обновлению весов слоя на любой глубине.
В LSTM выходные значения складываются с новыми данными, чтобы избежать затухания градиента на старых данных. В Vanilla RNN использовалась функция активации при переходе от старого состояния к новому, из-за чего обратное распространение ошибки затухало.
Заключение
Паралич сети или затухание градиента – очень сложная проблема, решение которой может привести к необычным архитектурным решениям.