Перейти к содержимому

Как написать нейросеть на python

  • автор:

Как написать свою первую нейросеть на Python

Как написать свою первую нейросеть на Python

С помощью статьи доктора философии Оксфордского университета и автора книг о глубоком обучении Эндрю Траска показываем, как написать нейросеть на Python. Она умещается всего в девять строчек кода и выглядит вот так:

from numpy import exp, array, random, dot training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) training_set_outputs = array([[0, 1, 1, 0]]).T random.seed(1) synaptic_weights = 2 * random.random((3, 1)) — 1 for iteration in xrange(10000): output = 1 / (1 + exp(-(dot(training_set_inputs, synaptic_weights)))) synaptic_weights += dot(training_set_inputs.T, (training_set_outputs — output) * output * (1 — output)) print 1 / (1 + exp(-(dot(array([1, 0, 0]), synaptic_weights))))

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

Data Scientist

Дата-сайентисты решают поистине амбициозные задачи. Научитесь создавать искусственный интеллект, обучать нейронные сети, менять мир и при этом хорошо зарабатывать. Программа рассчитана на новичков и плавно введет вас в Data Science.

картинка - 2023-03-14T190938.211

Профессия / 24 месяца
Data Scientist
Решайте амбициозные задачи с помощью нейросетей
5 990 ₽/мес 9 983 ₽/мес

Group 1321314349 (2)

Что такое нейросеть

моделирование нейрона

Человеческий мозг состоит из ста миллиардов клеток, которые называются нейронами. Они соединены между собой синапсами. Если через синапсы к нейрону придет достаточное количество нервных импульсов, этот нейрон сработает и передаст нервный импульс дальше. Этот процесс лежит в основе нашего мышления. Мы можем смоделировать это явление, создав нейронную сеть с помощью компьютера. Нам не нужно воссоздавать все сложные биологические процессы, которые происходят в человеческом мозге на молекулярном уровне, нам достаточно знать, что происходит на более высоких уровнях. Для этого мы используем математический инструмент — матрицы, которые представляют собой таблицы чисел. Чтобы сделать все как можно проще, мы смоделируем только один нейрон, к которому поступает входная информация из трех источников и есть только один выход. Наша задача — научить нейронную сеть решать задачу, которая изображена в ниже. Первые четыре примера будут нашим тренировочным набором. Получилось ли у вас увидеть закономерность? Что должно быть на месте вопросительного знака — 0 или 1?

Входные данные Вывод
0 0 1 0
1 1 1 1
1 0 1 1
0 1 1 0
1 0 0 ?

Вы могли заметить, что вывод всегда равен значению левого столбца. Так что ответом будет 1. Пройдите наш тест и узнайте, какой контент подготовил искусственный интеллект, а какой — реальный человек. Ссылка в конце статьи.

Процесс тренировки

схема обучения нейронной сети

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

  1. В качестве входных данных мы возьмем примеры из тренировочного набора. Потом мы воспользуемся специальной формулой для расчета выхода нейрона, которая будет учитывать случайные веса, которые мы задали для каждого примера.
  2. Далее посчитаем размер ошибки, который вычисляется как разница между числом, которое нейрон подал на выход и желаемым числом из примера.
  3. В зависимости от того, в какую сторону нейрон ошибся, мы немного отрегулируем вес этого примера.
  4. Повторим этот процесс 10 000 раз.

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

Станьте дата-сайентистом и решайте амбициозные задачи с помощью нейросетей

Формула для расчета выхода нейрона

Разберем специальную формулу для расчета выхода нейрона. Сначала возьмем взвешенную сумму входов нейрона:

взвешенная сумма входов нейрона

Затем мы нормализуем это, поэтому результат будет между 0 и 1. Для этого мы используем математически удобную функцию, называемую функцией Sigmoid:

На графике функция Sigmoid нарисует S-образную кривую.

Sigmoid S-образная кривая

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

формула для выхода нейрона

Формула корректировки весов

Во время тренировочного цикла (он изображен на рисунке 3) мы постоянно корректируем веса. Но на сколько? Для того, чтобы вычислить это, мы воспользуемся следующей формулой:

формула для нейросети на python

Давайте поймем почему формула имеет такой вид. Сначала нам нужно учесть то, что мы хотим скорректировать вес пропорционально размеру ошибки. Далее ошибка умножается на значение, поданное на вход нейрона, что, в нашем случае, 0 или 1. Если на вход был подан 0, то вес не корректируется. И в конце выражение умножается на градиент сигмоиды. Разберемся в последнем шаге по порядку:

  1. Мы использовали сигмоиду для того, чтобы посчитать выход нейрона.
  2. Если на выходе мы получаем большое положительное или отрицательное число, то это значит, что нейрон был весьма уверен в том или ином решении.
  3. На рисунке 4 мы можем увидеть, что при больших значениях переменной градиент принимает маленькие значения.
  4. Если нейрон уверен в том, что заданный вес верен, то мы не хотим сильно корректировать его. Умножение на градиент сигмоиды позволяет добиться такого эффекта.

Градиент сигмоиды может быть найден по следующей формуле:

Градиент сигмоиды для нейросети

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

конечная формула для корректировки весов

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

Как написать это на Python

Хотя мы не будем использовать специальные библиотеки для нейронных сетей, мы импортируем следующие 4 метода из математической библиотеки numpy:

  • exp — функция экспоненты
  • array — метод создания матриц
  • dot — метод перемножения матриц
  • random — метод, подающий на выход случайное число

Теперь мы можем, например, представить наш тренировочный набор с использованием array() :

training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) training_set_outputs = array([[0, 1, 1, 0]]).T

Функция .T транспонирует матрицу из горизонтальной в вертикальную. В результате компьютер хранит эти числа таким образом:

вертикальная матрица

Теперь мы готовы к более изящной версии кода. После нее добавим несколько финальных замечаний.

Обратите внимание, что на каждой итерации мы обрабатываем весь тренировочный набор одновременно. Таким образом наши переменные все являются матрицами.

Итак, вот полноценно работающий пример нейронной сети, написанный на Python:

from numpy import exp, array, random, dot class NeuralNetwork(): def __init__(self):

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

random.seed(1)

Мы моделируем единственный нейрон с тремя входящими связями и одним выходом. Мы задаем случайные веса в матрице размера 3 x 1, где значения весов варьируются от -1 до 1, а среднее значение равно 0:

self.synaptic_weights = 2 * random.random((3, 1)) - 1

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

def __sigmoid(self, x): return 1 / (1 + exp(-x))

Производная от функции сигмоиды. Это градиент ее кривой. Его значение указывает насколько нейронная сеть уверена в правильности существующего веса:

def __sigmoid_derivative(self, x): return x * (1 - x)

Мы тренируем нейронную сеть методом проб и ошибок, каждый раз корректируя вес синапсов:

def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations): for iteration in xrange(number_of_training_iterations):

Тренировочный набор передается нейронной сети (одному нейрону в нашем случае):

output = self.think(training_set_inputs)

Вычисляем ошибку (разницу между желаемым выходом и выходом, предсказанным нейроном):

error = training_set_outputs - output

Умножаем ошибку на входной сигнал и на градиент сигмоиды. В результате этого, те веса, в которых нейрон не уверен, будут откорректированы сильнее. Входные сигналы, которые равны нулю, не приводят к изменению веса:

adjustment = dot(training_set_inputs.T, error * self.__sigmoid_derivative(output))
self.synaptic_weights += adjustment

Заставляем наш нейрон подумать:

def think(self, inputs):

Пропускаем входящие данные через нейрон:

return self.__sigmoid(dot(inputs, self.synaptic_weights)) if __name__ == "__main__":

Инициализируем нейронную сеть, состоящую из одного нейрона:

neural_network = NeuralNetwork() print "Random starting synaptic weights:" print neural_network.synaptic_weights

Тренировочный набор для обучения. У нас это 4 примера, состоящих из 3 входящих значений и 1 выходящего значения:

training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])training_set_outputs = array([[0, 1, 1, 0]]).T

Обучаем нейронную сеть на тренировочном наборе, повторяя процесс 10000 раз, каждый раз корректируя веса:

neural_network.train(training_set_inputs, training_set_outputs, 10000) print "New synaptic weights after training:" print neural_network.synaptic_weights

Тестируем нейрон на новом примере:

print "Considering new situation [1, 0, 0] -> ?:" print neural_network.think(array([1, 0, 0]))

Этот код также можно найти на GitHub. Обратите внимание, что если вы используете Python 3, то вам будет нужно заменить команду “xrange” на “range”.

Несколько финальных замечаний

Попробуйте теперь запустить нейросеть на Python, используя в терминале эту команду:

python main.py

Результат должен быть таким:

Random starting synaptic weights:
[[-0.16595599]
[ 0.44064899]
[-0.99977125]]

New synaptic weights after training:
[[ 9.67299303]
[-0.2078435 ]
[-4.62963669]]

Considering new situation
[1, 0, 0] -> ?: [ 0.99993704]

Ура, мы построили простую нейронную сеть с помощью Python!

Сначала нейронная сеть задала себе случайные веса, затем обучилась на тренировочном наборе. После этого она предсказала в качестве ответа 0.99993704 для нового примера [1, 0, 0]. Верный ответ был 1, так что это очень близко к правде!

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

Как можно улучшить нейронную сеть

Нейросеть, которую мы построили, решает очень простую задачу. Она обучилась на закономерности из таблицы и выдает правильный ответ. Но что, если усложнить задачу — например, цифр будет не две, а три, или результаты не будут иметь жесткой закономерности?

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

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

Больше нейронов. В нашей тренировочной нейросети только один нейрон. Но если нейронов будет больше — каждый из них сможет по-своему реагировать на входные данные, соответственно, на следующие нейроны будут приходить данные с разных синапсов. Значит — больше вариативность, «подумать» и передать сигнал дальше может не один нейрон, а несколько. Можно менять и формулу передачи, и связи между нейронами — так получаются разные виды нейронных сетей.

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

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

Лучше обучение. Искусственные нейронные сети обучаются примерно по тому же принципу, что живые существа. Когда человек часто повторяет одни и те же действия, он учится: ездить на велосипеде, рисовать или набирать текст. Это происходит, потому что веса между нейронами в мозгу меняются: нервные клетки наращивают новые связи, по-новому начинают воспринимать сигналы и правильнее их передают. Нейронная сеть тоже изменяет веса при обучении — чем оно объемнее, тем сильнее она «запомнит» какую-то закономерность.

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

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

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

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

Больше мощностей. Нейронные сети работают с матрицами, так что если нейронов много, вычисления получаются очень ресурсоемкие. Известные нейросети вроде Midjourney или ChatGPT — это сложные и «тяжелые» системы, для их работы нужны сервера с мощным «железом». Так что написать собственный DALL-E на домашнем компьютере не получится. Но есть сервисы для аренды мощностей: ими как раз пользуются инженеры машинного обучения, чтобы создавать, обучать и тестировать модели.

Можно ли написать нейросеть еще короче

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

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

Как создать нейросеть на Python: пошаговое руководство для начинающих

Чтобы создать нейросеть на Python, вам понадобится использовать библиотеку TensorFlow. Вот простой пример кода:

 import tensorflow as tf # Определение модели model = tf.keras.models.Sequential([ tf.keras.layers.Dense(64, activation='relu', input_shape=(784,)), tf.keras.layers.Dense(10, activation='softmax') ]) # Компиляция модели model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # Обучение модели model.fit(x_train, y_train, epochs=10, batch_size=32) # Прогнозирование с использованием модели predictions = model.predict(x_test) 

В этом примере мы создаем модель с двумя слоями: один слой с 64 нейронами с функцией активации ReLU и один выходной слой с 10 нейронами с функцией активации softmax. Затем мы компилируем модель, используя оптимизатор «adam» и функцию потерь «sparse_categorical_crossentropy». Затем мы обучаем модель, используя обучающие данные «x_train» и метки «y_train» в течение 10 эпох с размером пакета 32. Наконец, мы делаем прогнозы с использованием модели для тестовых данных «x_test».

Детальный ответ

Как создать нейросеть на Python

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

Установка основных компонентов

Прежде всего, вам необходимо установить Python на ваш компьютер. Вы можете загрузить установочный файл Python с официального веб-сайта python.org и следовать инструкциям по установке. После установки Python вы можете установить несколько дополнительных пакетов, которые понадобятся для работы с нейронными сетями. Для этого вы можете использовать менеджер пакетов pip, который обычно включается в установку Python. Вот несколько команд для установки необходимых пакетов:

 pip install numpy pip install tensorflow 

Пакет numpy используется для работы с массивами и матрицами, а tensorflow — для создания нейронных сетей.

Определение архитектуры нейросети

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

 import tensorflow as tf from tensorflow.keras.layers import Dense model = tf.keras.Sequential() model.add(Dense(64, activation='relu', input_shape=(input_size,))) model.add(Dense(64, activation='relu')) model.add(Dense(num_classes, activation='softmax')) 

Этот пример создает последовательную модель с одним скрытым слоем, включающим 64 нейрона. Функция активации ‘relu’ используется для активации нейронов. Входной размер определяется параметром input_shape, а выходной слой имеет количество нейронов, соответствующее количеству классов в задаче классификации.

Обучение нейросети

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

 from sklearn.model_selection import train_test_split # Загрузка данных X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # Нормализация данных X_train = X_train / 255.0 X_test = X_test / 255.0 

В этом примере мы используем функцию train_test_split из библиотеки scikit-learn для разделения данных на обучающий и тестовый наборы. Затем мы нормализуем данные, чтобы значения были в диапазоне от 0 до 1. После подготовки данных вы можете приступить к обучению нейросети. Вот пример кода для обучения модели:

 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test)) 

В этом примере мы компилируем модель с оптимизатором ‘adam’ и функцией потерь ‘sparse_categorical_crossentropy’. Затем мы обучаем модель на обучающем наборе данных в течение 10 эпох и проверяем точность на тестовом наборе данных.

Оценка производительности нейросети

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

 test_loss, test_accuracy = model.evaluate(X_test, y_test) print('Test Loss:', test_loss) print('Test Accuracy:', test_accuracy) 

В этом примере мы используем метод evaluate для оценки потерь и точности модели на тестовом наборе данных.

Использование нейросети для предсказаний

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

 predictions = model.predict(X_new) predicted_classes = np.argmax(predictions, axis=1) 

В этом примере мы используем метод predict для получения предсказаний модели на новом наборе данных. Функция argmax используется для получения предсказанного класса.

Заключение

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

Как создать нейронную сеть с нуля на языке Python

нейронная сеть на python

Мотивация: ориентируясь на личный опыт в изучении глубокого обучения, я решил создать нейронную сеть с нуля без сложной учебной библиотеки, такой как, например, TensorFlow. Я считаю, что для начинающего Data Scientist-а важно понимание внутренней структуры нейронной сети.

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

  • Обучение с подкреплением на Python с библиотекой Keras
  • Пример решения задачи по машинному обучению на Python

Что такое нейронная сеть?

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

Нейронные сети состоят из следующих компонентов:

  • входной слой, x
  • произвольное количество скрытых слоев
  • выходной слой, ŷ
  • набор весов и смещений между каждым слоем Wи b
  • выбор функции активации для каждого скрытого слоя σ; в этой работе мы будем использовать функцию активации Sigmoid

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

нейронная сеть на python

Создание класса Neural Network на Python выглядит просто:

Обучение нейронной сети

Выход ŷ простой двухслойной нейронной сети:

обучение нейронной сети на питон

В приведенном выше уравнении, веса W и смещения b являются единственными переменными, которые влияют на выход ŷ.

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

Каждая итерация обучающего процесса состоит из следующих шагов

  • вычисление прогнозируемого выхода ŷ, называемого прямым распространением
  • обновление весов и смещений, называемых обратным распространением

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

backpropagation

Прямое распространение

Как мы видели на графике выше, прямое распространение — это просто несложное вычисление, а для базовой 2-слойной нейронной сети вывод нейронной сети дается формулой:

обучение нейронной сети на питон

Давайте добавим функцию прямого распространения в наш код на Python-е, чтобы сделать это. Заметим, что для простоты, мы предположили, что смещения равны 0.

Однако нужен способ оценить «добротность» наших прогнозов, то есть насколько далеки наши прогнозы). Функция потери как раз позволяет нам сделать это.

Функция потери

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

функция потери

Сумма квадратов ошибок — это среднее значение разницы между каждым прогнозируемым и фактическим значением.

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

Обратное распространение

Теперь, когда мы измерили ошибку нашего прогноза (потери), нам нужно найти способ распространения ошибки обратно и обновить наши веса и смещения.

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

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

градиентный спуск

Если у нас есть производная, то мы можем просто обновить веса и смещения, увеличив/уменьшив их (см. диаграмму выше). Это называется градиентным спуском.

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

chain rule python neural network

Фух! Это было громоздко, но позволило получить то, что нам нужно — производную (наклон) функции потерь по отношению к весам. Теперь мы можем соответствующим образом регулировать веса.

Добавим функцию backpropagation (обратного распространения) в наш код на Python-е:

Проверка работы нейросети

Теперь, когда у нас есть наш полный код на Python-е для выполнения прямого и обратного распространения, давайте рассмотрим нашу нейронную сеть на примере и посмотрим, как это работает.

Идеальный набор весов нейросети

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

Давайте тренируем нейронную сеть на 1500 итераций и посмотрим, что произойдет. Рассматривая график потерь на итерации ниже, мы можем ясно видеть, что потеря монотонно уменьшается до минимума. Это согласуется с алгоритмом спуска градиента, о котором мы говорили ранее.

ошибка нейронной сети

Посмотрим на окончательное предсказание (вывод) из нейронной сети после 1500 итераций.

предсказание

Мы сделали это! Наш алгоритм прямого и обратного распространения показал успешную работу нейронной сети, а предсказания сходятся на истинных значениях.

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

Финальные размышления

Я многому научился в процессе написания с нуля своей собственной нейронной сети. Хотя библиотеки глубинного обучения, такие как TensorFlow и Keras, допускают создание глубоких сетей без полного понимания внутренней работы нейронной сети, я нахожу, что начинающим Data Scientist-ам полезно получить более глубокое их понимание.

Я инвестировал много своего личного времени в данную работу, и я надеюсь, что она будет полезной для вас!

Как создать свою собственную нейронную сеть с нуля на Python

Мотивация: в рамках моего личного пути к лучшему пониманию глубокого обучения я решил создать нейронную сеть с нуля без библиотеки глубокого обучения, такой как TensorFlow. Я считаю, что понимание внутренней работы нейронной сети важно для любого начинающего специалиста по данным. Эта статья содержит то, что я узнал, и, надеюсь, она будет полезна и вам!

Что такое нейронная сеть?

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

Нейронные сети состоят из следующих компонентов:

  • Входной слой, x
  • Произвольное количество скрытых слоев
  • Выходной слой, y
  • Набор весов и смещений между каждым слоем, W и b
  • Выбор функции активации для каждого скрытого слоя, σ. В этом уроке мы будем использовать функцию активации

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

Создать класс нейронной сети в Python очень просто.

class NeuralNetwork: def __init__(self, x, y): self.input = x self.weights1 = np.random.rand(self.input.shape[1],4) self.weights2 = np.random.rand(4,1) self.y = y self.output = np.zeros(y.shape)

Обучение нейронной сети.

Выход y простой двухслойной нейронной сети:

Вы могли заметить, что в приведенном выше уравнении веса W и смещения b являются единственными переменными, влияющими на выход y.

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

Каждая итерация процесса обучения состоит из следующих шагов:

  • Расчет прогнозируемого выхода y, известный как прямая связь.
  • Обновление весов и смещений, известное как обратное распространение.

Последовательный график ниже иллюстрирует процесс.

Прямая связь

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

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

class NeuralNetwork: def __init__(self, x, y): self.input = x self.weights1 = np.random.rand(self.input.shape[1],4) self.weights2 = np.random.rand(4,1) self.y = y self.output = np.zeros(self.y.shape) def feedforward(self): self.layer1 = sigmoid(np.dot(self.input, self.weights1)) self.output = sigmoid(np.dot(self.layer1, self.weights2))

Однако нам по-прежнему нужен способ оценить «хорошесть» наших прогнозов (т. е. насколько далеки наши прогнозы)? Функция потерь позволяет нам сделать именно это.

Функция потери

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

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

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

Обратное распространение

Теперь, когда мы измерили ошибку нашего прогноза (потери), нам нужно найти способ распространить ошибку обратно и обновить наши веса и смещения.

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

Вспомним из исчисления, что производная функции — это просто наклон функции.

Если у нас есть производная, мы можем просто обновить веса и смещения, увеличивая/уменьшая ее (см. диаграмму выше).

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

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

class NeuralNetwork: def __init__(self, x, y): self.input = x self.weights1 = np.random.rand(self.input.shape[1],4) self.weights2 = np.random.rand(4,1) self.y = y self.output = np.zeros(self.y.shape) def feedforward(self): self.layer1 = sigmoid(np.dot(self.input, self.weights1)) self.output = sigmoid(np.dot(self.layer1, self.weights2)) def backprop(self): # application of the chain rule to find derivative of the loss function with respect to weights2 and weights1 d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * sigmoid_derivative(self.output))) d_weights1 = np.dot(self.input.T, (np.dot(2*(self.y - self.output) * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1))) # update the weights with the derivative (slope) of the loss function self.weights1 += d_weights1 self.weights2 += d_weights2
Собираем все вместе

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

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

Давайте обучим нейронную сеть на 1500 итераций и посмотрим, что получится. Глядя на приведенный ниже график потерь на итерацию, мы ясно видим, что потери монотонно уменьшаются к минимуму. Это согласуется с алгоритмом градиентного спуска, который мы обсуждали ранее.

Давайте посмотрим на окончательный прогноз (выход) нейронной сети после 1500 итераций.

Мы сделали это! Наш алгоритм прямого и обратного распространения успешно обучил нейронную сеть, и прогнозы сошлись на истинных значениях.

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

Что дальше?

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

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

Последние мысли

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

Хотя библиотеки глубокого обучения, такие как TensorFlow и Keras, упрощают создание глубоких сетей без полного понимания внутренней работы нейронной сети, я считаю, что начинающим специалистам по данным полезно получить более глубокое понимание нейронных сетей. Это упражнение было отличным вложением моего времени, и я надеюсь, что оно будет полезным и для вас!

  • Ненормальное программирование
  • Python

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *