Эта статья поможет вам понять, зачем нам нужна скорость обучения и полезно ли она для обучения искусственной нейронной сети. Используя очень простой код Python для однослойного персептрона, значение скорости обучения будет изменено, чтобы уловить его идею.

Введение

Препятствием для новичков в искусственных нейронных сетях является скорость обучения. Меня много раз спрашивали о влиянии скорости обучения на обучение искусственных нейронных сетей (ИНС). Почему мы используем скорость обучения? Какое лучшее значение для скорости обучения? В этой статье я попытаюсь упростить задачу, приведя пример, показывающий, как скорость обучения полезна для обучения ИНС. Я начну с объяснения нашего примера с кодом Python, прежде чем работать со скоростью обучения.

Пример

Используется очень-очень простой пример, чтобы вывести нас из состояния сложности и позволить нам просто сосредоточиться на скорости обучения. Один числовой ввод будет применен к персептрону одного слоя. Если вход 250 или меньше, его значение будет возвращено как выход сети. Если входной сигнал больше 250, он будет обрезан до 250. На рисунке 1 показана таблица с 6 образцами, используемыми для обучения.

Архитектура ИНС

Архитектура используемой ИНС показана на рисунке 2. Есть только уровни ввода и вывода. На входном слое есть только один нейрон для нашего единственного входа. Выходной слой имеет только один нейрон для генерации выходных данных. Нейрон выходного слоя отвечает за отображение входа на правильный выход. Также к нейрону выходного слоя применяется смещение с весом b и значением +1. Для входа также указан вес W.

Функция активации

Уравнение и график функции активации, используемые в этом примере, показаны на рисунке 3. Когда входной сигнал меньше или равен 250, выход будет таким же, как вход. В противном случае он будет обрезан до 250.

Реализация с использованием Python

Код Python, реализующий всю сеть, показан ниже. Мы обсудим все это, пока не сделаем это настолько простым, насколько это возможно, а затем сосредоточимся на изменении скорости обучения, чтобы выяснить, как это влияет на обучение сети.

1. import numpy  
2.   
3. def activation_function(inpt):  
4.     if(inpt > 250):  
5.         return 250 # clip the result to 250  
6.     else:  
7.         return inpt # just return the input  
8.   
9. def prediction_error(desired, expected):  
10.     return numpy.abs(numpy.mean(desired-expected)) # absolute error  
11.   
12. def update_weights(weights, predicted, idx):  
13.     weights = weights + .00001*(desired_output[idx] - predicted)*inputs[idx] # updating weights  
14.     return weights # new updated weights  
15.   
16. weights = numpy.array([0.05, .1]) #bias & weight of input  
17. inputs = numpy.array([60, 40, 100, 300, -50, 310]) # training inputs  
18. desired_output = numpy.array([60, 40, 150, 250, -50, 250]) # training outputs  
19.   
20. def training_loop(inpt, weights):  
21.     error = 1  
22.     idx = 0 # start by the first training sample  
23.     iteration = 0 #loop iteration variable  
24.     while(iteration < 2000 or error >= 0.01): #while(error >= 0.1):  
25.         predicted = activation_function(weights[0]*1+weights[1]*inputs[idx])  
26.         error = prediction_error(desired_output[idx], predicted)  
27.         weights = update_weights(weights, predicted, idx)  
28.         idx = idx + 1 # go to the next sample  
29.         idx = idx % inputs.shape[0] # restricts the index to the range of our samples  
30.         iteration = iteration + 1 # next iteration  
31.     return error, weights  
32.   
33. error, new_weights = training_loop(inputs, weights)  
34. print('--------------Final Results----------------')  
35. print('Learned Weights : ', new_weights)  
36. new_inputs = numpy.array([10, 240, 550, -160])  
37. new_outputs = numpy.array([10, 240, 250, -160])  
38. for i in range(new_inputs.shape[0]):  
39.     print('Sample ', i+1, '. Expected = ', new_outputs[i], ' , Predicted = ', activation_function(new_weights[0]*1+new_weights[1]*new_inputs[i]))

Строки 17 и 18 отвечают за создание двух массивов (input и required_output), содержащих обучающие входные и выходные данные, представленные в предыдущей таблице. Каждый вход будет иметь выход в соответствии с используемой функцией активации.

Строка 16 создает массив весов сети. Всего два веса: один для входа, а другой для смещения. Они были случайным образом инициализированы 0,05 для смещения и 0,1 для входа.

Сама функция активации реализуется с помощью метода activate_function (inpt) из строк с 3 по 7. Он принимает единственный аргумент, который является входом, и возвращает единственное значение, которое является ожидаемым выходом.

Поскольку в прогнозе может быть ошибка, нам нужно измерить эту ошибку, чтобы узнать, насколько мы далеки от правильного прогноза. По этой причине в строке 9–10 реализован метод prediction_error (желаемый, ожидаемый), который принимает два входа: желаемый и ожидаемый выходы. Этот метод просто вычисляет абсолютную разницу между каждым желаемым и ожидаемым результатом. Лучшее значение для любой ошибки - точно 0. Это оптимальное значение.

Что, если произошла ошибка прогноза? В этом случае мы должны внести изменения в сеть. Но что именно поменять? Это веса сети. Для обновления сетевых весов существует метод update_weights (веса, предсказанный, idx), определенный в строках с 13 по 14. Он принимает три входа: старые веса, предсказанные выходные данные и индекс входа с ложным предсказанием. Уравнение, используемое для обновления весов, показано на рисунке 4.

Уравнение использует веса текущего шага (n) для генерации весов следующего шага (n + 1). Это уравнение мы будем использовать, чтобы узнать, как скорость обучения влияет на процесс обучения.

Наконец, нам нужно объединить все это вместе, чтобы сеть обучалась. Это делается с помощью метода training_loop (inpt, weights), определенного в строках с 20 по 31. Он переходит в цикл обучения. Цикл используется для сопоставления входов и выходов с наименьшей возможной ошибкой прогнозирования.

Цикл выполняет три операции:

  1. Прогнозирование выхода.
  2. Расчет ошибок.
  3. Обновление весов.

Получив представление о примере и его коде Python, давайте начнем показывать, насколько полезна скорость обучения для получения наилучших результатов.

Скорость обучения

В ранее обсужденном примере строка 13 содержит уравнение обновления весов, в котором используется скорость обучения. Сначала предположим, что мы не использовали скорость обучения полностью. Уравнение будет следующим:

weights = weights + (desired_output[idx] — predicted)*inputs[idx]

Давайте посмотрим на эффект от удаления скорости обучения. В итерации цикла обучения сеть имеет следующие входы (b = 0,05 и W = 0,1, вход = 60 и желаемый выход = 60).

Ожидаемый результат, который является результатом функции активации, как в строке 25, будет Activ_function (0,05 (+1) + 0,1 (60)). Прогнозируемый выход будет 6.05.

В строке 26 ошибка прогнозирования будет рассчитана путем получения разницы между желаемым и прогнозируемым выходными данными. Ошибка будет абс (60–6,05) = 53,95.

Затем в строке 27 веса будут обновлены в соответствии с приведенным выше уравнением. Новые веса будут [0,05, 0,1] + (53,95) * 60 = [0,05, 0,1] + 3237 = [3237,05, 3237,1].

Кажется, что новые веса слишком отличаются от предыдущих весов. Каждый вес увеличился на 3237, что слишком много. Но продолжим делать следующий прогноз.

На следующей итерации к сети будут применены следующие входные данные: (b = 3237,05 и W = 3237,1, вход = 40 и желаемый выход = 40). Ожидаемый результат будет: activate_function ((3237.05 + 3237.1 (40)) = 250. Ошибка прогноза будет abs (40–250) = 210. Ошибка очень большая. Она больше, чем предыдущая ошибка. Таким образом, мы должны обновите веса снова.В соответствии с приведенным выше уравнением новые веса будут [3237,05, 3237,1] + (-210) * 40 = [3237,05, 3237,1] + -8400 = [-5162,95, -5162,9].

Таблица, показанная на рисунке 5, суммирует результаты первых трех итераций.

Чем больше итераций, тем хуже результаты. Величина весов быстро меняется, иногда со сменой знаков. Они переходят от очень большого положительного значения к очень большому отрицательному значению. Как мы можем остановить это резкое и резкое изменение веса? Как уменьшить значение, на которое обновляются веса?

Если мы посмотрели на значение, на которое изменяются веса из предыдущей таблицы, кажется, что значение очень большое. Это означает, что сеть меняет свои веса с большой скоростью. Это похоже на человека, который делает большие шаги за малое время. Одно время человек находится на Дальнем Востоке, а через очень короткое время этот человек будет на Дальнем Западе. Нам просто нужно сделать это медленнее.

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

Возвращаясь к той части кода, которая генерирует это значение, похоже, что уравнение обновления - это то, что его генерирует. В частности, эта часть:

(desired_output[idx] — predicted)*inputs[idx]

Мы можем масштабировать эту часть, умножив ее на небольшое значение, например 0,1. Таким образом, вместо того, чтобы генерировать 3237.0 в качестве обновленного значения в первой итерации, оно будет уменьшено до 323,7. Мы даже можем масштабировать это значение до меньшего значения, уменьшив значение шкалы до 0,001. Используя 0,001, значение будет всего 3,327.

Мы можем поймать это сейчас. Это масштабируемое значение - скорость обучения. Выбор небольших значений для скорости обучения уменьшает скорость обновления весов и позволяет избежать резких изменений. Чем больше значение, тем быстрее изменения и, как следствие, плохие результаты.

Но каково наилучшее значение скорости обучения?

Нет никакого значения, которое мы можем сказать, что это лучшее значение для скорости обучения. Скорость обучения - гиперпараметр. Значение гиперпараметра определяется экспериментально. Мы пробуем разные значения и используем то, которое дает наилучшие результаты. Есть несколько способов, которые просто помогут вам выбрать значения гиперпараметров.

Тестовая сеть

Для нашей проблемы я пришел к выводу, что значение 0,00001 работает нормально. После обучения сети с такой скоростью обучения мы можем провести тест. В таблице на рисунке 6 показаны результаты прогноза 4 новых тестовых образцов. Кажется, что результаты теперь намного лучше после использования скорости обучения.

Исходная статья доступна в LinkedIn по этой ссылке: https://www.linkedin.com/pulse/learning-rate-useful-artificial-neural-networks-ahmed-gad/

Он также доступен в KDnuggets на этой странице: https://www.kdnuggets.com/2018/01/learning-rate-useful-neural-network.html

Статья опубликована на TDS 28–6–2018.

Для связи с автором

Ахмед Фаузи Гад

LinkedIn: https://linkedin.com/in/ahmedfgad

Электронная почта: [email protected]