Введение в нейронные сети с помощью Scikit-Learn в Python
Искусственные нейронные сети – это вычислительные системы, которые призваны имитировать способности человека к обучению с помощью сложной архитектуры, напоминающей нервную систему человека.
В этой статье мы кратко рассмотрим, что такое нейронные сети, какие вычислительные этапы выполняет нейронная сеть (не углубляясь в сложную математику, стоящую за ней), и как их можно реализовать с помощью Scikit-Learn в Python.
Нервная система человека
Нервная система человека состоит из миллиардов нейронов. Эти нейроны коллективно обрабатывают ввод, полученный от органов чувств, обрабатывают информацию и решают, что делать в ответ на ввод. Типичный нейрон нервной системы человека состоит из трех основных частей: дендритов, ядра и аксонов.
Информация, передаваемая нейрону, принимается дендритами. Ядро отвечает за обработку этой информации. Выходной сигнал нейрона передается другим нейронам через аксон, который связан с дендритами других нейронов, расположенных дальше по сети.
Искусственные нейронные сети вдохновлены архитектурой нейронных сетей человека. Простейшая нейронная сеть состоит только из одного нейрона и называется перцептроном, как показано на рисунке ниже:
Перцептрон имеет один входной слой и один нейрон. Входной слой действует как дендриты и отвечает за получение входных данных. Количество узлов во входном слое равно количеству объектов во входном наборе данных. Каждый вход умножается на вес (который обычно инициализируется некоторым случайным значением), и результаты суммируются. Затем сумма передается через функцию активации. Функция активации перцептрона напоминает ядро нейрона нервной системы человека. Он обрабатывает информацию и выдает результат. В случае перцептрона этот результат является окончательным. Однако в случае многослойных персептронов выход нейронов предыдущего слоя служит входом для нейронов следующего слоя.
Искусственная нейронная сеть (многослойный персептрон)
Теперь, когда мы знаем, что такое однослойный персептрон, мы можем расширить это обсуждение на многослойные персептроны, более известные как искусственные нейронные сети. Однослойный перцептрон может решать простые задачи, в которых данные линейно разделяются по размерам n, где n – количество объектов в наборе данных. Однако в случае нелинейно разделяемых данных точность однослойного персептрона значительно снижается. С другой стороны, многослойные персептроны могут эффективно работать с нелинейно разделяемыми данными.
Многослойные перцептроны, или более часто называемые искусственными нейронными сетями, представляют собой комбинацию нескольких нейронов, соединенных в виде сети. Искусственная нейронная сеть имеет входной слой, один или несколько скрытых слоев и выходной слой. Это показано на изображении ниже:
Нейронная сеть выполняется в два этапа: прямое и обратное распространение.
Feed-Forward
Ниже приведены шаги, выполняемые на этапе прямой связи:
- Значения, полученные во входном слое, умножаются на веса. Смещение добавляется к суммированию входных данных и весов, чтобы избежать нулевых значений.
- Каждый нейрон в первом скрытом слое получает разные значения от входного слоя в зависимости от весов и смещения. У нейронов есть функция активации, которая работает со значением, полученным от входного слоя. Функция активации может быть многих типов, например, ступенчатая и сигмовидная функции, relu или tanh-функция. Как правило, функция relu используется в нейронах скрытого слоя, а сигмовидная функция используется для нейрона выходного слоя.
- Выходные данные нейронов первого скрытого слоя умножаются на веса второго скрытого слоя. Результаты суммируются и передаются нейронам последующих слоев. Этот процесс продолжается до тех пор, пока не будет достигнут внешний слой. Значения, вычисленные на внешнем уровне, являются фактическими выходными данными алгоритма.
Фаза прямой связи состоит из этих трех этапов. Однако прогнозируемый результат не обязательно сразу оказывается правильным. Это может быть неправильно, и нам нужно это исправить. Цель алгоритма обучения – делать максимально точные прогнозы. Чтобы улучшить эти прогнозируемые результаты, нейронная сеть затем пройдет фазу обратного распространения. Во время обратного распространения веса различных нейронов обновляются таким образом, чтобы разница между желаемым и прогнозируемым выходными данными была как можно меньше.
Обратное распространение
Фаза обратного распространения состоит из следующих этапов:
- Ошибка рассчитывается путем количественной оценки разницы между прогнозируемым и желаемым выходными данными. Эта разница называется «потерями», а функция, используемая для вычисления разницы, называется «функцией потерь». Функции потерь могут быть разных типов, например, среднеквадратичная ошибка или функции кросс-энтропии. Помните, что нейронные сети – это контролируемые алгоритмы обучения, которым требуются желаемые выходные данные для заданного набора входных данных, что позволяет ему учиться на данных.
- Следующим шагом после вычисления ошибки является минимизация этой ошибки. Для этого вычисляется частная производная функции ошибок по всем весам и смещениям. Это называется градиентным приличием. Производные можно использовать для определения наклона функции ошибок. Если наклон положительный, значение весов может быть уменьшено, а если наклон отрицательное, значение веса может быть увеличено. Это снижает общую ошибку. Функция, которая используется для уменьшения этой ошибки, называется функцией оптимизации.
Этот один цикл прямого и обратного распространения называется одной «эпохой». Этот процесс продолжается до тех пор, пока не будет достигнута разумная точность. Не существует стандарта разумной точности, в идеале вы должны стремиться к 100% точности, но этого чрезвычайно сложно достичь для любого нетривиального набора данных. Во многих случаях точность 90% + считается приемлемой, но это действительно зависит от вашего варианта использования.
Реализация нейронной сети
Теперь мы знаем, что такое нейронные сети и какие шаги необходимо выполнить, чтобы построить простую нейронную сеть с плотными связями. В этом разделе мы попытаемся построить простую нейронную сеть, которая предсказывает класс, к которому принадлежит данное растение ириса. Мы будем использовать библиотеку Python Scikit-Learn для создания нашей нейронной сети, которая выполняет эту задачу классификации.
Примечание. Сценарии, представленные в этом руководстве, были выполнены и протестированы в записной книжке Python Jupyter.
Набор данных
Первый шаг – импортировать этот набор данных в нашу программу. Для этого мы будем использовать библиотеку pandas в Python.
Выполните следующую команду, чтобы загрузить набор данных радужной оболочки в Data Frame Python:
import pandas as pd # Location of dataset url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data" # Assign colum names to the dataset names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'Class'] # Read dataset to pandas dataframe irisdata = pd.read_csv(url, names=names)
Вышеупомянутый скрипт просто загружает данные радужной оболочки, присваивает имена, например, «длина чашелистика», «ширина чашелистика», «длина лепестка», «ширина лепестка» и «класс» столбцам набора данных, а затем загружает его в dataframe irisdata.
Чтобы увидеть, как на самом деле выглядит этот набор данных, выполните следующую команду:
irisdata.head()
Выполнение вышеуказанного скрипта отобразит первые пять строк нашего набора данных, как показано ниже:
| длина чашелистика | ширина чашелистика | длина лепестка | ширина лепестка | Класс | |
|---|---|---|---|---|---|
| 0 | 5.1 | 3.5 | 1.4 | 0,2 | Ирис-шелковистый |
| 1 | 4.9 | 3.0 | 1.4 | 0,2 | Ирис-шелковистый |
| 2 | 4,7 | 3,2 | 1.3 | 0,2 | Ирис-шелковистый |
| 3 | 4.6 | 3.1 | 1.5 | 0,2 | Ирис-шелковистый |
| 4 | 5.0 | 3,6 | 1.4 | 0,2 | Ирис-шелковистый |
Предварительная обработка
Как видите, в нашем наборе данных пять столбцов. Задача состоит в том, чтобы предсказать класс (значения в пятом столбце), к которому принадлежит ирис, на основе длины чашелистика, ширины чашелистика, длины лепестка и ширины лепестка (первые четыре столбца). Следующим шагом является разделение нашего набора данных на атрибуты и метки. Для этого выполните следующий сценарий:
# Assign data from first four columns to X variable X = irisdata.iloc[:, 0:4] # Assign data from first fifth columns to y variable y = irisdata.select_dtypes(include=[object])
Чтобы увидеть, как выглядит y, выполните следующий код:
y.head()
| Класс | |
|---|---|
| 0 | Ирис-шелковистый |
| 1 | Ирис-шелковистый |
| 2 | Ирис-шелковистый |
| 3 | Ирис-шелковистый |
| 4 | Ирис-шелковистый |
Вы можете видеть, что значения в серии y являются категориальными. Однако нейронные сети лучше работают с числовыми данными. Наша следующая задача – преобразовать эти категориальные значения в числовые значения. Но сначала давайте посмотрим, сколько уникальных значений у нас в серии y. Выполните следующий скрипт:
y.Class.unique()
Выход:
array(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'], dtype=object)
У нас есть три уникальных сорта: «Ирис сетоса», «Ирис разноцветный» и «Ирис вирджиника». Преобразуем эти категориальные значения в числовые значения. Для этого мы будем использовать класс Scikit-Learn LabelEncoder.
Выполните следующий скрипт:
from sklearn import preprocessing le = preprocessing.LabelEncoder() y = y.apply(le.fit_transform)
Теперь, если вы снова проверите уникальные значения в серии y, вы увидите следующие результаты:
array([0, 1, 2], dtype=int64)
Вы можете видеть, что категориальные значения были закодированы в числовые значения, то есть 0, 1 и 2.
Тестовый сплит
Чтобы избежать чрезмерной подгонки, мы разделим наш набор данных на обучающие и тестовые части. Обучающие данные будут использоваться для обучения нейронной сети, а тестовые данные будут использоваться для оценки производительности нейронной сети. Это помогает решить проблему чрезмерной подгонки, потому что мы оцениваем нашу нейронную сеть на данных, которые она не видела раньше.
Чтобы создать тренировочные и тестовые сплиты, выполните следующий скрипт:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
Приведенный выше скрипт разделяет 80% набора данных на наш обучающий набор, а остальные 20% – на тестовые данные.
Масштабирование функций
Перед тем, как делать реальные прогнозы, всегда рекомендуется масштабировать функции, чтобы все они могли быть оценены единообразно. Масштабирование функций выполняется только на обучающих данных, а не на тестовых. Это связано с тем, что в реальном мире данные не масштабируются, и конечная цель нейронной сети – делать прогнозы на основе данных реального мира. Поэтому мы стараемся, чтобы наши тестовые данные были максимально реалистичными.
Следующий скрипт выполняет масштабирование функций:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaler.fit(X_train) X_train = scaler.transform(X_train) X_test = scaler.transform(X_test)
Обучение и прогнозы
И теперь, наконец, пришло время сделать то, чего вы ждали, – обучить нейронную сеть, которая действительно может делать прогнозы. Для этого выполните следующий скрипт:
from sklearn.neural_network import MLPClassifier mlp = MLPClassifier(hidden_layer_sizes=(10, 10, 10), max_iter=1000) mlp.fit(X_train, y_train.values.ravel())
Да, с помощью Scikit-Learn вы можете создать нейронную сеть с этими тремя строками кода, каждая из которых выполняет большую часть работы за вас. Посмотрим, что происходит в приведенном выше скрипте. Первый шаг – импортировать класс MLPClassifier из библиотеки sklearn.neural_network. Во второй строке этот класс инициализируется двумя параметрами.
Первый параметр hidden_layer_sizes используется для установки размера скрытых слоев. В нашем скрипте мы создадим три слоя по 10 узлов в каждом. Не существует стандартной формулы для выбора количества слоев и узлов нейронной сети, и она довольно сильно варьируется в зависимости от решаемой задачи. Лучше всего попробовать разные комбинации и посмотреть, что работает лучше всего.
Второй параметр MLPClassifier указывает количество итераций или эпох, которые вы хотите, чтобы ваша нейронная сеть выполнялась. Помните, что одна эпоха – это комбинация одного цикла фазы прямого и обратного распространения.
По умолчанию функция активации relu используется с оптимизатором затрат adam. Однако вы можете изменить эти функции, используя параметры активации и решателя соответственно.
В третьей строке функция соответствия используется для обучения алгоритма на наших обучающих данных, то есть X_train и y_train.
Последний шаг – сделать прогнозы на основе наших тестовых данных. Для этого выполните следующий скрипт:
predictions = mlp.predict(X_test)
Оценка алгоритма
Мы создали наш алгоритм и сделали некоторые прогнозы на тестовом наборе данных. Пришло время оценить, насколько хорошо работает наш алгоритм. Для оценки алгоритма наиболее часто используемыми показателями являются матрица неточностей, точность, отзыв и оценка f1. Методы confusion_matrix и classification_report библиотеки sklearn.metrics могут помочь нам найти эти оценки. Следующий скрипт генерирует оценочный отчет для нашего алгоритма:
from sklearn.metrics import classification_report, confusion_matrix print(confusion_matrix(y_test,predictions)) print(classification_report(y_test,predictions))
Этот код выше генерирует следующий результат:
[[11 0 0]
0 8 0]
0 1 10]]
precision recall f1-score support
0 1.00 1.00 1.00 11
1 0.89 1.00 0.94 8
2 1.00 0.91 0.95 11
avg / total 0.97 0.97 0.97 30
Из матрицы неточностей видно, что наша нейронная сеть неверно классифицировала только одно растение из 30, на которых мы тестировали сеть. Кроме того, оценка f1 0,97 – это очень хорошо, учитывая тот факт, что у нас было всего 150 тренировок.
Ваши результаты могут немного отличаться от этих, потому что train_test_split случайным образом разделяет данные на обучающие и тестовые наборы, поэтому наши сети могли не быть обучены или протестированы на одних и тех же данных. Но в целом точность ваших наборов данных также должна быть выше 90%.
Заключение
В этой статье мы дали краткий обзор того, что такое нейронные сети, и объяснили, как создать очень простую нейронную сеть, которая была обучена на наборе данных радужной оболочки глаза. Я бы порекомендовал вам попробовать поиграть с количеством скрытых слоев, функциями активации и размером разделения на обучение и тестирование, чтобы увидеть, сможете ли вы достичь лучших результатов.
Автор