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

Каниа Алексеевич Кан, 2018

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

Оглавление

* * *

Приведённый ознакомительный фрагмент книги Нейронные сети. Эволюция предоставлен нашим книжным партнёром — компанией ЛитРес.

Купить и скачать полную версию книги в форматах FB2, ePub, MOBI, TXT, HTML, RTF и других

ГЛАВА 3

Рождение искусственного нейрона

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

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

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

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

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

Видно, что наши данные напоминают прямую линию, уравнение которой Y = = 2*x. Данные находятся около значений этой функции, но не повторяют их. Задача нашего нейрон суметь с большой точностью провести эту прямую, несмотря на то, что данные по остальным точкам отсутствуют (например, нет данных о Y координате с точкой с x = 5).

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

Визуализируем структуру нейрона, которую будем моделировать:

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

Программа

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

Создадим переменную А, являющейся коэффициентом крутизны наклона прямой, и зададим ей любое значение, пусть это будет всё те же А=0.4.

A = 0.4

Запомним начальное значение коэффициента А:

A_vis = A

Покажем функцию начальной прямой:

print('Начальная прямая: ', A, '* X')

Укажем значение скорости обучения:

lr = 0.001

Зададим количество эпох:

epochs = 3000

Эпоха — значение количества проходов по обучающей выборке. Если в нашей выборке девять наборов, то одна эпоха — это один проход в цикле всех девяти наборов данных.

Зададим наш набор данных, используя массивы. Создадим два массива. В один массив поместим все входные данные — x, а в другой целевые значения (ответы) — Y.

Создадим массив входных данных х:

arr_x = [1, 2, 3, 3.5, 4, 6, 7.5, 8.5, 9]

Создадим массив целевых значений (ответы Y):

arr_y = [2.4, 4.5, 5.5, 6.4, 8.5, 11.7, 16.1, 16.5, 18.3]

Задаем в цикле эпох, вложенный цикл — for i in range(len(arr)), который будет последовательно пробегать по входным данным, от начала до конца. А циклом — for e in range(epochs), мы как раз указываем количество таких пробегов (итераций):

for e in range(epochs):

for i in range(len(arr)):

Функция len(arr) возвращает длину массива, в нашем случае возвращает девять.

Получаем x координату точки из массива входных значений x:

x = arr_x[i]

А затем действуем как в случае с линейным классификатором:

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

y = A * x

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

target_Y = arr_y[i]

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

E = target_Y — y

# Меняем коэффициент при x, в соответствии с правилом A+дельтаA = A

A += lr*(E/x)

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

Выведем результат после обучения:

print('Готовая прямая: y = ', A, '* X')

Полный текст программы:

# Инициализируем любым числом коэффициент крутизны наклона прямой

A = 0.4

A_vis = A # Запоминаем начальное значение крутизны наклона

# Вывод данных начальной прямой

print('Начальная прямая: ', A, '* X')

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

lr = 0.001

# Зададим количество эпох

epochs = 3000

# Создадим массив входных данных x

arr_x = [1, 2, 3, 3.5, 4, 6, 7.5, 8.5, 9]

# Создадим массив целевых значений (ответы Y)

arr_y = [2.4, 4.5, 5.5, 6.4, 8.5, 11.7, 16.1, 16.5, 18.3]

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

for e in range(epochs):

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

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

x = arr_x[i]

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

y = A * x

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

target_Y = arr_y[i]

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

E = target_Y — y

# Меняем коэффициент при x, в соответствии с правилом A+дельтаA = A

A += lr*(E/x)

# Вывод данных готовой прямой

print('Готовая прямая: y = ', A, '* X')

Результатом ее работы будет функция готовой прямой:

y = 2.0562708725692196 * X

Для большей наглядности, что я специально указал данные в обучающей выборке, так чтобы они лежали около значений функции y = 2x. И после обучения нейрона, мы получили ответ очень близкий к этому значению.

Было бы неплохо визуализировать все происходящие на графике прямо в Python.

Визуализация позволяет быстро получить общее представление о том, что мы делаем и чего добились.

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

Ниже приведена инструкция, с помощью которой мы импортируем нужный нам пакет для работы с графикой:

import matplotlib.pyplot as plt

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

%matplotlib inline

Если не получается загрузить данный пакет в программу, то скорей всего его надо скачать из сети. Делать это удобно через Anaconda Prompt, который устанавливается вместе с пакетом Anaconda.

Для системы Windows, в Anaconda Prompt вводим команду:

conda install matplotlib

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

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

Выполним код:

import matplotlib.pyplot as plt

%matplotlib inline

# Функция для отображения входных данных

def func_data(x_data):

return [arr_y[i] for i in range(len(arr_y))]

# Функция для отображения начальной прямой

def func_begin(x_begin):

return [A_vis*i for i in x_begin]

# Функция для отображения готовой прямой

def func(x):

return [A*i for i in x]

# Значения по X входных данных

x_data = arr_x

# Значения по X начальной прямой (диапазон значений)

x_begin = [i for i in range(0, 11)]

# Значения по X готовой прямой (диапазон значений)

x = [i for i in range(0, 11)]

#x = np.arange(0,11,1)

# Значения по Y входных данных

y_data = func_data(x_data)

# Значения по Y начальной прямой

y_begin = func_begin(x_begin)

# Значения по Y готовой прямой

y = func(x)

# Зададим имена графику и числовым координатам

plt.title("Neuron")

plt.xlabel("X")

plt.ylabel("Y")

# Зададим имена входным данным и прямым

plt.plot(x,y, label='Входные данные', color = 'g')

plt.plot(x,y, label='Готовая прямая', color = 'r')

plt.plot(x,y, label='Начальная прямая', color = 'b')

plt.legend(loc=2) #loc — локация имени, 2 — справа в углу

# представляем точки данных (х,у) кружочками диаметра 10

plt.scatter(x_data, y_data, color ='g', s=10)

# Начальная прямая

plt.plot(x_begin, y_begin, 'b')

# Готовая прямая

plt.plot(x, y, 'r')

# Сетка на фоне для улучшения восприятия

plt.grid(True, linestyle='-', color='0.75')

# Показать график

plt.show()

При выполнении кода, результат визуализации окажется следующим:

Исходники с программами вы можете найти по ссылке: https://github.com/CaniaCan/neuralmaster

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

В функциях отображения входных данных — def func_data(x_data), def func_data(x_begin), def func_data(x), возвращаем координаты y, в соответствии со своими значениями по х.

Зададим имена графику — plt.title(), и числовым координатам — plt.xlabel():

plt.title("Neuron")

plt.xlabel("X")

plt.ylabel("Y")

Зададим имена входным данным и прямым — plt.plot(), в скобках укажем имя и цвет, plt.legend(loc=2) — определяет нахождение данных имен на плоскости:

plt.plot(x,y, label='Входные данные', color = 'g')

plt.plot(x,y, label='Готовая прямая', color = 'r')

plt.plot(x,y, label='Начальная прямая', color = 'b')

plt.legend(loc=2) #loc — локация имени, 2 — справа в углу

Метод scatter выводит на плоскость точки с заданными координатами:

plt.scatter(x_data, y_data, color ='g', s=10)

Метод plot выводит на плоскость прямую по заданным точкам:

plt.plot(x, y, 'r')

Ну и наконец отображаем все что натворили, командой plt.show().

Теперь разберем получившийся график. Синим — отмечена начальная прямая, которая изначально не выполняла никакой классификации. После обучения, значение коэффициента A, стабилизируется возле числа = 2.05. Если провести прямую функции y = Ax = 2.05*x, отмеченной красным на графике, то получим значения близкие к нашим входным данным (на графике — зеленые точки).

А что если, наш обученный нейрон смог бы правильно отвечать на вводимые пользователем данные? Если задать условие, что всё что выше красной линии относится к виду — жирафов, а ниже к виду — крокодилов:

x = input("Введите значение ширины Х:")

x = int(x)

T = input("Введите значение высоты Y:")

T = int(T)

y = A * x

# Условие

if T > y:

print('Это жираф!')

else:

print('Это крокодил!')

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

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

Введите значение ширины Х: 4

Введите значение высоты Y: 15

Это жираф!

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

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

Оглавление

* * *

Приведённый ознакомительный фрагмент книги Нейронные сети. Эволюция предоставлен нашим книжным партнёром — компанией ЛитРес.

Купить и скачать полную версию книги в форматах FB2, ePub, MOBI, TXT, HTML, RTF и других

Смотрите также

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