Нейронные сети. Эволюция

Текст
Читать фрагмент
Отметить прочитанной
Как читать книгу после покупки
Шрифт:Меньше АаБольше Аа

ГЛАВА 4

Добавляем входной параметр

Теперь представим, что нам приходит новое задание. Где, проанализировав самостоятельно данные, мы видим, что их координаты значительно отличаются от прежних. Теперь провести классифицирующую прямую, обладая в своем арсенале лишь коэффициентом крутизны – не выйдет!


Очевидно, что без параметра b, которого мы до этого избегали (b=0), тут не обойтись.

Вспомним, что параметр b, в уравнении прямой y = Ax + b, как раз отвечает за точку её пересечения с осью Y. На графике выше, такая точка очевидно находится возле координаты – (x =0; y =11).

Для того, чтобы выполнить новое задание, придется добавить в наш нейрон, второй вход – отвечающий за параметр b.

Моделирование нейрона как линейного классификатора со всеми параметрами линейной функции

Определимся с параметром (b). Как будет выглядеть второй вход? Какие данные подавать в ходе обучения?

Параметр (b) – величина постоянная, поэтому мы добавим его на второй вход нейрона, с постоянным значением входного сигнала, равным единице (x2 = 1). Таким образом, произведение этого входа на значение величины (b), всегда будет равно значению самой величины (b).

Пришло время для первого эволюционного изменения структуры нашего нейрона!

Рассмотрим следующую графическую модель искусственного нейрона:



Где, как говорилось выше, на вход нейрона поступают два входных сигнала x (из нашего набора данных) и x2 = 1. После чего, эти значения умножаются со своими изменяемыми параметрами, а далее они суммируются: A*x+b*x2. Значение этой суммы, а по совместительству – значение функции y = A*x+b*x2 = A*x+b, поступает на выход.

Ну и давайте всё представим согласно тем принятым условным обозначениям, которые используются при моделировании искусственных нейронов и нейронных сетей. А именно – коэффициент А и параметр b, обозначим как w1 и w2 соответственно. И теперь будем их называть – весовыми коэффициентами.

Ну и конечно же, визуализируем структуру нашего нейрона, с новыми обозначениями:



Переименуем в нашей первой программе коэффициент (А) и параметр (b), на обозначения весовых коэффициентов, как показано на слайде. Инициализируем их в ней. Дополним небольшую её часть в области с обучением, формулой изменения веса (w2), как мы это делали ранее с коэффициентом (А).

После чего, область с обучением в программе, будет выглядеть следующим образом:

# Прогон по выборке

for e in range(epochs):

for i in range(len(arr)): # len(arr) – функция возвращает длину массива

# Получить x координату точки

x = arr[i]


# Получить расчетную y, координату точки

y = w1 * x + w2


# Получить целевую Y, координату точки

target_Y = arr_y[i]


# Ошибка E = целевое значение – выход нейрона

E = target_Y – y


# Меняем вес при входе x

w1 += lr*(E/x)


# Меняем вес при входе x2 = 1, w2 += lr*(E/x2) = lr*E

w2 += lr*E


И забегая вперед, скажу, что тут нас постигнет разочарование – ничего не выйдет…

Дело в том, что вес (w2) (бывший параметр (b)), вносит искажение в поправку веса (w1) (бывшего коэффициента (А)) и наоборот. Они действуют независимо друг от друга, что сказывается на увеличении ошибки с каждым проходом цикла программы.

Нужен фактор, который заставит наша веса действовать согласованно, учитывать интересы друг друга, идти на компромиссы, ради нужного результата. И такой фактор у нас уже есть – ошибка.

Если мы придумаем как согласованно со всеми входами уменьшать ошибку с каждым проходом цикла в программе, подгоняя под неё весовые коэффициенты таким образом, что в конечном счете привело к самому минимальному её значению для всех входов. Такое решение, являлось бы общим для всех входов нашего нейрона. То есть, согласованно обновляя веса в сторону уменьшения их общей ошибки, мы будем приближаться к оптимальному результату на выходе.

Поэтому, при числе входов нейрона, больше одного, наши выработанные до этого правила линейной классификации, необходимо дополнить. Нужно использовать ошибку, чтобы математически связать все входы таким образом, при котором они начнут учитывать общие интересы. И как следствие, на выходе получить нужный классификатор.

Итак, мы постепенно подходим к ключевому понятию в обучении нейрона и нейронных сетей – обучение методом градиентного спуска.

Обновление весовых коэффициентов

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

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

У такого абстрактного подхода, есть математическая версия, которая называется – градиентным спуском. Где подножье холма – минимум ошибки, а шагами в его направлении – обновления весовых коэффициентов.

Градиентный спуск – метод нахождения локального  минимума или максимума функции с помощью движения вдоль градиентакоторый, своим направлением указывает направление наибольшего возрастания некоторой величины, значение которой меняется от одной точки пространства к другой, а по величине (модулю) равный скорости роста этой величины в этом направлении.





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

Для наглядности, рассмотрим использование метода градиентного спуска на простейшем примере.

Возьмём график функции, которая своими значениями иллюстрирует склон. Если бы это была функция ошибки, то нам нужно найти такое значение (х), которое минимизирует эту функцию:



Значение шага (скорости обучения), как мы говорили ранее, играет тоже не малую роль, при слишком большом значении, мы быстро спускаемся, но можем переступить минимум функции – страдает точность. При очень маленьком значении величины скорости обучения, нахождение минимума потребует гораздо больше времени. Нужно подобрать величину шага такой, чтоб он удовлетворяла нас и по скорости, и по точности. При нахождении минимума, наша точка будет коррелировать, возле значения минимум, в чуть большую и меньшую сторону на величину шага. Это все равно что – когда спустившись вплотную к подножью, мы сделали шаг и оказались чуть выше подножья, повернувшись сделали такой же шаг назад, и поняв, что опять находимся чуть выше, повторяли эти действия до бесконечности. Но при этом, мы все равно находились бы очень близко к подножью, потому как величина шага, в общем объеме, ничтожна, поэтому мы можем говорить – что находимся в самом низу.



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

Функция выходного сигнала не является функцией ошибки. Но мы знаем, что есть связь между этими функциями, поскольку ошибка – это разность между целевыми тренировочными значениями и фактическими выходными значениями (Е=Y-y).

Однако и здесь не все так гладко. Давайте взглянем на таблицу с тренировочными данными и выходными значениями для трех выходных узлов вместе с разными функциями ошибок:





Функция ошибки, которой мы пользовались ранее (целевоевыход), не совсем нам подходит, так как можно видеть, что если мы решим использовать сумму ошибок по всем узлам в качестве общего показателя того, насколько хорошо обучена сеть, то эта сумма равна нулю! Нулевая сумма означает отсутствие ошибки. Отсюда следует, что простая разность значений (целевоевыход), не годится для использования в качестве меры величины ошибки.

 

Во втором варианте, в качестве меры ошибки используется квадрат разности: ((целевоевыход)²). Этот вариант предпочтительней первого, поскольку, как видно из таблицы, сумма ошибок на выходе не дает нулевой вариант. Кроме того, такая функция имеет еще ряд преимуществ над первой, делает функцию ошибки непрерывно гладкой, исключая провалы и скачки, тем самым улучшая работу метода градиентного спуска. Еще одно преимущество заключается в том, что при приближении к минимуму градиент уменьшается, что уменьшает корреляцию через точку минимума.

Чтобы воспользоваться методом градиентного спуска, нам нужно применить метод дифференциального исчисления. Не пугайтесь, всё не так сложно, как может показаться.

Дифференциальное исчисление – это просто математически строгий подход к определению величины изменения одних величин при изменении других. Например, мы можем говорить о скорости изменения чего угодно, ускорения или любой другой физической величины, или математической функции.


Не изменяющиеся величина

Если мы представим автомобиль, движущийся с постоянной скоростью в 1,5 км/мин, то отвечая на вопрос, как меняется скорость автомобиля с течением времени, ответ утвердительный никак, ноль, так как его скорость постоянна:


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

Сказанное, можно записать в следующей математической форме:





Линейное изменение


А теперь представим тот же автомобиль, с начальной скоростью 1,5 км/мин, но в определенный момент, водитель жмет на газ, и автомобиль начинает набирать скорость (равномерно ускоряться). И по истечении трех минут, от момента, когда мы нажали педаль газа, его скорость станет равной 2,1 км/мин.


Из графика видно, что увеличение скорости автомобиля, происходит с постоянной скоростью изменения (равномерным ускорением), откуда функция зависимости скорости от времени, выглядит как прямая линия.

Изначально, в нулевой момент времени, скорость равна 1,5 км/мин. Далее мы добавляем по 0,2 км в минуту. Таким образом, искомое выражение приобретает следующий вид:

Скорость = 1,5 + (0,2 * время)

S = 1,5 + 0,2t


В итоговом выражении, вы легко увидите уравнение прямой. Где коэффициент = 0,2 – величина крутизны наклона прямой, а постоянный член = 1,5 – точка через которую проходит линия на оси координат y.

Так будет выглядеть выражение, которое скажет нам о том, что между скоростью движения автомобиля и временем существует зависимость:





Каждую минуту, скорость изменяется на значение 0,2.


Не равномерное изменение


Возьмём всё тот же автомобиль, который стоит на месте. Сидя в нем, вы начинаете жать в “пол” педаль газа, удерживая её в этом положении. Скорость движения автомобиля, за счет инерции, будет возрастать не равномерно. Ежеминутное приращение скорости будет с каждой минутой увеличиваться.


Приведем в таблице, значения скорости в каждую минуту:





Эти данные представляют собой выражение:


s = t²


Какова скорость изменения скорости автомобиля в каждый момент времени?

Если посмотреть на два предыдущих примера, то в них скорость изменения скорости определялась наклоном графика, коэффициентом крутизны прямой линии А. Когда автомобиль двигался с постоянной скоростью, его скорость не изменялась, и скорость изменения скорости равна 0. Когда автомобиль равномерно набирал скорость, скорость его изменения составляла 0,2 км/мин, на протяжении всего времени движения автомобиля в этом режиме.

А как тогда поступить в этом случае? Как узнать изменение скорости по кривой?

Применение дифференциального исчисления, понятие производной


После трех минут с момента начала движения (t=3), скорость составит 9 км/мин. Сравним со скоростью в конце пятой минуты. После пяти минут с момента начала движения (t=5), скорость составляет 25 км/мин. Не важно, что скорость 25 км/мин – сопоставима со скоростью пули, ведь это воображаемая машина, и едет она с той скоростью, с какой мы захотим. Если провести касательную линию в этих точках, то окажется, что угол наклона у них совершенно разный:


Вы видите, что чем больше скорость в точке касательной, тем её наклон круче. Оба наклона представляют искомую скорость изменения скорости движения. Можно сравнить с вторым примером – линейное изменение.

Но как измерить наклон этих линий? Для этого давайте представим, что наша касательная (t = 3, s = 9), пересекает функцию в двух точках, расстояние между которыми очень мало:



Зная координаты этих точек и проведя проекции по осям, можно вычислить расстояние между этими точками.

Если представить прямоугольный треугольник где гипотенуза – это прямая между двумя точками, а его катеты равны разности проекциям точек по осям (∆t и ∆s), то поделив противолежащий катет на прилежащий получим тангенс угла, который и будет являться коэффициентом крутизны. Зная который, как во втором примере, мы легко определим изменение скорости в момент ∆t.




Как мы знаем, скорость изменения – это наклон прямой, которую из второго примера мы уже умеем находить. Значит, около точки (t=3), наш коэффициент крутизны будет равен:




Значит, скорость изменения скорости в момент времени три минуты составляет 6,06 км/мин.

Производная функции


Мы можем говорить о скорости изменения чего угодно – физической величины, экономического показателя и так далее.

Рассмотрим функцию y = f(x). Отметим на оси X, некоторое значение аргумента x, а на оси Y – соответствующее значение функции y = f(x).




Дадим аргументу x, некоторое приращение, обозначенное как ∆х. Попадаем в точку х+∆х. А соответствующие этим значениям аргументов, значение функции обозначим соответственно f(x), f и f(x+∆х). Приращение аргумента ∆х, есть аналог промежутка времени t, а соответствующее приращение функции – это аналог пути s, пройденного за время t.

Если представить, что ∆х – бесконечно мала, т.е. стремиться к нулю (∆х-›0), то выражение нахождения изменения скорости можно записать как:




Или исходя из геометрического представления, описанного ранее:



Отсюда вывод, что производная функции f(x) в точке х – это предел отношения приращения функции к приращению её аргумента, когда приращение аргумента стремиться к нулю.

Нахождение некоторых табличных производных


Решим найденным способом, наш первый пример, когда скорость автомобиля была постоянной, на всем промежутке времени. В этом примере, приращение функции равно нулю (s = 0), и соответственно тангенса угла не существует:

∆s = s(t+∆t) – s(t) = s(t) – s(t) = 0



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



Откуда можно сформулировать правило, что производная константы, равна нулю.

s(t) = с, где с – константа

с′ = 0

Запись с′ – означает что берется производная по функции.


Во второй примере, когда изменение скорости автомобиля проходило линейно, с постоянным изменением, найти производную функции (s = 0,2t + 1,5), не зная правил дифференцирования сложных функций, мы пока не сможем, поэтому отложим этот пример на потом.


Продолжим с решения третьего примера, когда изменение скорости автомобиля проходило не линейно:

s = t²

Приращение функции и производная:

s(t) = t²

∆s = s(t+∆t) – s(t) = (t+∆t) ² – t² = t² + 2t∆t + ∆t² – t² = ∆t(2t+∆t)




Вот мы и решили наш третий пример! Нашли формулу точного изменения скорость от времени. Вычислим производную, в всё той же точки t = 3.

s(t) = t²

s′(t) = 2*3 = 6

Точный ответ, в пределах небольшой погрешности, почти сошелся с вычисленном до этого приближенным ответом.


Попробуем усложнить пример. Предположим, что скорость движения автомобиля описывается кубической функцией времени:

s(t) = t³

Приращение и производная:

s(t) = t³

∆s = s(t+∆t) – s(t) = t³ + 3 t²∆t+ 3t∆ t² + ∆ t³ – t³ = ∆t(3 t² + 3t∆t + ∆t²)




Из двух последних примеров (с производными функций s(t) = t² и s(t) = t³) следует, что показатель степени числа, становится его произведением, а степень уменьшается на единицу:

s(t) = tⁿ




А чему равна производная от аргумента функции? Давайте узнаем…


s(t) = t

Приращение:


s = s(t+∆t) – s(t) = t + ∆tt = ∆t


Производная:




Получается, что производная от переменной:


t′ = 0

Правила дифференцирования и дифференцирование сложных функций

Дифференцирование суммы

(u+v)′ = u′ + v, где u и v – функции.

Пусть f(x) = u(x) + v(x). Тогда:

f = f(x+∆x) – f(x) = u(x+∆x) + v(x+∆x) – u(x) – v(x) = u(x) + ∆u + v(x) + ∆vu(x) – v(x) = ∆u + ∆v

Тогда имеем:



Дроби u/∆х и v/∆х при ∆х->0 стремятся соответственно к u′(x) и v′ (x). Сумма этих дробей стремится к сумме u′(x) + v′ (x).

f′(x) = u′ (x) + v′ (x)

 

Дифференцирование произведения

(u*v)′ = uv + vu, где u и v – функции

Разберем, почему это так. Обозначим f(x) = u(x) * v(x). Тогда:

f = f(x+∆x) – f(x) = u(x+∆x) * v(x+∆x) – u(x) * v(x) = (u(x) + ∆u) * (v(x) + ∆v) – u(x) * v(x) = u(x)v(x) + v(x)∆u + u(x)∆v + ∆uvu(x)v(x) = v(x)∆u + u(x)∆v + ∆uv

Далее имеем:



Первое слагаемое стремиться к u′(x) v(x). Второе слагаемое стремиться к v′(x)* u(x). А третье, в дроби u/∆x, в пределе даст число u′(x), а поскольку множитель ∆v стремиться к нулю, то и вся эта дробь обратится в ноль. А следовательно, в результате получаем:

f′(x) = u′ (x) v(x) + v′ (x) u(x)

Из этого правила, легко убедиться, что:

(c*u)′ = cu + c u′ = c u

Поскольку, с – константа, поэтому ее производная равна нулю (c′ = 0).

Зная это правило мы без труда, найдем изменение скорости второго примера.

Применим к выражению правило дифференцирование суммы:

s′ (t) = (0,2t) ′ + (1,5) ′

Теперь по порядку, возьмём выражение – (0,2t) ′. Как брать производную произведения константы и переменной мы знаем:

(0,2t) ′ = 0,2

А производная самой константы равна нулю – (1,5) ′ = 0.

Следовательно, скорость изменения скорости, второго примера:

s′ (t) = 0,2

Что совпадает с нашим ответом, полученном ранее во втором примере.


Дифференцирование сложной функции

Допустим, что в некоторой функции, y сама является функцией:

f = y²

y = x²+x

Представим дифференцирование этой функции в виде:



Нахождение производной в этом случае, осуществляется в два этапа.



Мы знаем, как решить производную типа: dy²/dy = 2y

А также знаем, как решать производную суммы: х² + х = (х²)′ + х′ = 2х+1

Тогда:

2(x²+x) * (2х+1) = (2х²+2х) * (2х+1) = 4х³+6х²+2х

Я надеюсь, вам удалось понять, в чем состоит суть дифференциального исчисления.

Используя описанные, методы дифференцирования выражений, вы сможете понять механизм работы метода градиентного спуска.

В качестве небольшого дополнения, приведу список наиболее распространённых табличных производных:




Зачем нам дифференцировать функции

Еще раз вспомним как мы спускаемся по склону. Что в кромешной тьме, мы хотим попасть к его подножью, имея в своем арсенале слабенький фонарик.



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



К слову, отобразить визуально такую функцию, с более чем двумя параметрами, как видите, будет довольно проблематично, но идея нахождения минимума методом градиентного спуска останется ровно такой же.

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

Представим ось значение, как ось ошибка. Очень хорошо видно, что функция ошибки общая для всех значений весов. Соответственно – координаты точки значения ошибки, при определенных значениях весовых коэффициентов, тоже общие.

При нахождении производной функции ошибки (угол наклона спуска в точке), по каждому из весовых коэффициентов, находим новую точку функции ошибки, которая обязательно стремиться двигаться в направлении её уменьшения. Тем самым, находим вектор направления.

А обновляя веса в соответствии со своим входом, на величину угла наклона, находим новые координаты этих коэффициентов. Проекции этих новых координат на ось ошибки (значение низ лежащей точки на графике), приводят в ту самую новую точку функции ошибки.

Как происходит обновление весовых коэффициентов?

Для ответа на этот вопрос, изобразим наш гипотетический рельеф в двумерной плоскости (гипотетический – потому что функция ошибки, зависящая от аргумента весовых коэффициентов, нам не известна). Где значение высоты будет ошибка, а за координаты по горизонтали нахождения точки в данный момент, будет отвечать весовой коэффициент.



Тьму, через которую невозможно разглядеть даже то, что находится под ногами, можно сравнить с тем, что нам не известна функция ошибки. Так как, даже при двух, постоянно изменяющихся, параметрах неизвестных в функции ошибки, провести её точную кривую на координатной плоскости не представляется возможным. Мы можем лишь вычислить её значение в точке, по весовому коэффициенту.

Свет от фонаря, можно сравнить с производной – которая показывает скорость изменения ошибки (где в пределах видимости фонаря, круче склон, чтоб сделать шаг в его направлении). Следуя из основного понятия производной – измерения изменения одной величины, когда изменяется вторая, применительно к нашей ситуации, можно сказать что мы измеряем изменение величины ошибки, когда изменяются величины весовых коэффициентов.

А шаг, в свою очередь, отлично подходит на роль обновления нашего весового коэффициента, в сторону уменьшения ошибки.

Вычислив производную в точке, мы вычислим наклон функции ошибки, который нам нужно знать, чтобы начать градиентный спуск к минимуму:





Ij – определитель веса, в соответствии со своим входом. Если это вход x1 – то его весовой коэффициент обозначается как – w11, а у входа х2 – обозначается как -w21. Чем круче наклон касательной, тем больше скорость изменения ошибки, тем больше шаг.


Запишем в явном виде функцию ошибки, которая представляет собой сумму возведенных в квадрат разностей между целевым и фактическим значениями:



Разобьем пример на более простые части, как мы это делали при дифференцировании сложных функций:



Продифференцируем обе части поочередно:



Так как выход нейрона – f(x) = y, а взвешенная сумма – у = ∑I wij*xi, где xi – известная величина (константа), а весовые коэффициенты wij – переменная, производная по которой, дает как мы знаем единицу, то взвешенную сумму можно разбить на сумму простых множителей:



Откуда нетрудно найти:



Значит, для того чтобы обновить весовой коэффициент по своей связи:



Прежде чем записать окончательный ответ, избавимся от множителя 2 в начале выражения. Мы спокойно можем это сделать, поскольку нас интересует только направление градиента функции ошибки. Не столь важно, какой множитель будет стоять в начале этого выражения, 1, 2 или любой другой (лишь немного потеряем в масштабировании, направление останется прежним). Поэтому для простоты избавимся от неё, и запишем окончательный вид производной ошибки:



Всё получилось! Это и есть то выражение, которое мы искали. Это ключ к тренировке эволюционировавшего нейрона.

Бесплатный фрагмент закончился. Хотите читать дальше?
Купите 3 книги одновременно и выберите четвёртую в подарок!

Чтобы воспользоваться акцией, добавьте нужные книги в корзину. Сделать это можно на странице каждой книги, либо в общем списке:

  1. Нажмите на многоточие
    рядом с книгой
  2. Выберите пункт
    «Добавить в корзину»