Нейронный сети. Эволюция
Шрифт:
Вспоминаем старое выражение при нахождении сглаженного значения дельты линейного классификатора: А = L*(Е/х). Где (L) – скорость обучения, необходимая для того, чтобы мы делали спуск, постепенно, небольшими шашками.
Ну и наконец, давайте запишем окончательный вариант выражения при обновлении весовых коэффициентов:
новый wij = старый wij – L*(dE/dwij)
Еще
Ложный минимум
Если еще раз взглянуть на трехмерную поверхность, можно увидеть, что метод градиентного спуска может привести в другую долину, которая расположена правее, где минимум значения будет меньше относительно той долины, куда попали мы сейчас, т.е. эта долина не является самой глубокой.
На следующей иллюстрации показано несколько вариантов градиентного спуска, один из которых приводит к ложному минимуму.
Поздравляю! Мы прошли самую основу в теории нейронных сетей – метод градиентного спуска. Освоив этот материал, в дальнейшем, изучение теории искусственных нейронных сетей, не будет представлять для вас значимого труда.
Как работает эволюционировавший нейрон
Ну вот и настало время проверить практически, все наши умозаключения, касающиеся работы нашего искусственного нейрона, после первой эволюции. Для этого прибегнем к помощи Python, но сначала покажем наш список с данными, с которого мы это всё затеяли:
Если по координатам построить точки на плоскости, то мы заметим, что их значения лежат возле значений графика функции – y = 2x + 2,5.
Программа
import random
# Инициализируем любым числом крутизны наклона прямой w1 = A
w1 = 0.4
w1_vis = w1 # Запоминаем начальное значение крутизны наклона
# Инициализируем параметр w2 = b – отвечающий за точку прохождения прямой через ос Y
w2 = random.uniform(-4, 4)
w2_vis = w2 # Запоминаем начальное значение параметра
# Вывод данных начальной прямой
print('Начальная прямая: ', w1, '* X + ', w2)
# Скорость обучения
lr = 0.001
# Зададим количество эпох
epochs = 3000
# Создадим массив (выборку входных данных) входных данных x1
arr_x1 = [1, 2, 3, 3.5, 4, 6, 7.5, 8.5, 9]
# Значение входных данных второго входа всегда равно 1
x2 = 1
# Создадим массив значений (целевых значений)
arr_y = [4.3, 7, 8.0, 10.1, 11.3, 14.2, 18.5, 19.3, 21.4]
# Прогон по выборке
for e in range(epochs):
for i in range(len(arr_x1)): # len(arr) – функция возвращает длину массива
# Получить x координату точки
x1 = arr_x1[i]
# Получить расчетную y, координату точки
y = w1 * x1 + w2
# Получить целевую Y, координату точки
target_Y = arr_y[i]
# Ошибка E = -(целевое значение – выход нейрона)
E = – (target_Y – y)
# Меняем вес при x, в соответствии с правилом обновления веса
w1 -= lr * E * x1
# Меняем вес при x2 = 1
#w2 -= rate * E * x2 # Т.к. x2 = 1, то этот множитель можно не писать
w2 -= lr * E
# Вывод данных готовой прямой
print('Готовая прямая: ', w1, '* X + ', w2)
Данный код, как и все другие, вы можете скачать по ссылке: https://github.com/CaniaCan/neuralmaster
Опишем код программы:
В самом начале программы импортируем модуль для работы со случайными числами:
import random
При помощи которого, случайным числом, создаем весовой коэффициент параметра (w2 = b) – отвечающий за точку прохождения прямой через ос Y:
w2 = random.uniform(-4, 4)
Метод модуля random – uniform(from, to), генерирует случайное вещественное число от from до to включительно.
В нашей программе, как видно, не так много изменений, по сравнению с той что мы написали до этого. Мы добавили второй вход (х2 = 1), со своим весовым коэффициентом (w2). Коэффициент (А) – переименовали в весовой коэффициент (w1), параметр (b) – в весовой коэффициент (w2). Ну и конечно же, реализовали новую улучшенную функцию ошибки, и обновление весовых коэффициентов по методу градиентного спуска.
В результате чего, наш эволюционировавший нейрон, теперь гораздо лучше справляется с задачей классификации. Теперь он может классифицировать данные по двум входам, тем самым получая линейный классификатор с пересечением прямой по всей оси Y, а не только строго в точке нуля.
Давайте взглянем на результат чтобы убедиться в этом:
Начальная прямая: 0.4 * X + 0.3652477754014445
Готовая прямая: 2.058410130422831 * X + 2.5013583972057263
<