Обратное распространение ошибки нейронной сети?
-
20-09-2019 - |
Вопрос
Может ли кто-нибудь порекомендовать веб-сайт или дать мне краткое описание того, как обратное распространение ошибки реализовано в NN?Я понимаю основную концепцию, но не знаю, как писать код.
Многие источники, которые я нашел, просто показывают уравнения, не давая никаких объяснений, почему они это делают, а имена переменных затрудняют их поиск.
Пример:
void bpnn_output_error(delta, target, output, nj, err)
double *delta, *target, *output, *err;
int nj;
{
int j;
double o, t, errsum;
errsum = 0.0;
for (j = 1; j <= nj; j++) {
o = output[j];
t = target[j];
delta[j] = o * (1.0 - o) * (t - o);
errsum += ABS(delta[j]);
}
*err = errsum;
}
В этом примере может ли кто-нибудь объяснить цель
delta[j] = o * (1.0 - o) * (t - o);
Спасибо.
Решение
Цель
дельта[j] = о * (1,0 - о) * (т - о);
заключается в нахождении ошибки выходного узла в сети обратного распространения ошибки.
o представляет выход узла, t — ожидаемое значение выхода узла.
Член (o * (1,0 - o) является производной общей используемой передаточной функции - сигмовидной функции.(Другие передаточные функции не являются редкостью и потребуют переписывания кода, имеющего вместо этого первую производную сигмовидной формы.Несоответствие между функцией и производной, вероятно, будет означать, что обучение не будет сходиться.) Узел имеет значение «активации», которое передается через передаточную функцию для получения выходных данных o, например
о = f(активация)
Главное, что обратное распространение ошибки использует градиентный спуск, а ошибка распространяется обратно за счет применения правила цепочки.Проблема заключается в назначении кредита или вины, если хотите, за скрытые узлы, выходные данные которых не могут быть напрямую сопоставимы с ожидаемым значением.Начнем с того, что известно и сравнимо, — с выходных узлов.Ошибка считается пропорциональной первой производной выходных данных, умноженной на необработанное значение ошибки между ожидаемым и фактическим выходными данными.
Итак, более символично, мы бы написали эту строку как
delta[j] = f'(activation_j) * (t_j - o_j)
где f — ваша передаточная функция, а f’ — ее первая производная.
Дальше, в скрытых слоях, ошибка в узле представляет собой его предполагаемый вклад в ошибки, обнаруженные на следующем уровне.Таким образом, дельты последующего слоя умножаются на связующие веса, и эти произведения суммируются.Эта сумма умножается на первую производную активации скрытого узла, чтобы получить дельту для скрытого узла, или
delta[j] = f'(activation_j) * Sum(delta[k] * w_jk)
где j теперь ссылается на скрытый узел, а k — на узел в следующем слое.
Другие советы
(t-o)
это ошибка на выходе сети, поскольку t
целевой результат и o
это фактический результат.Он хранится в нормализованном виде в delta
множество.Метод, используемый для нормализации, зависит от реализации и o * ( 1.0 - o )
кажется, делает это (я могу ошибаться в этом предположении).
Эта нормализованная ошибка накапливается для всего обучающего набора, чтобы судить о завершении обучения:обычно, когда errsum
находится ниже некоторого целевого порога.
На самом деле, если вы знаете теорию, программы должны быть простыми для понимания.Вы можете прочитать книгу и сделать несколько простых примеров, используя карандаш чтобы выяснить точные шаги распространения.Это общий принцип реализации числовых программ, в небольших случаях надо знать самые детали.
Если вы знаете Matlab, я бы посоветовал вам прочитать исходный код Matlab (например. здесь), который легче понять, чем C.
Для кода в вашем вопросе имена говорят сами за себя, вывод может быть массивом вашего прогноза, целью может быть массив обучающих меток, дельта - это ошибка между прогнозом и истинными значениями, она также служит значением для обновиться в весовой вектор.
По сути, обратное распространение запускает сеть на обучающих данных, наблюдает за выходными данными, затем корректирует значения узлов, итеративно переходя от выходных узлов обратно к входным узлам.