Модель персептрона составляет основу современной нейронной сети и заложила основу для ландшафта машинного обучения, который мы видим сегодня.
В конце 1950-х годов авиационный инженер по имени Фрэнк Розенблатт впервые реализовал алгоритм, который откроет двери машинного обучения для человечества и станет поворотным камнем для современного мира. Он назывался персептрон. Первая в мире модель нейронной сети.
Алгоритм обучения перцептрона был первым компьютерным алгоритмом, способным классифицировать точки данных за конечное время, изучая в них закономерности, а затем используя это для прогнозирования будущих точек данных. Это было воспринято как большой скачок в информатике и обещает футуристический мир, в котором машины могут учиться без вмешательства человека. В этом посте мы узнаем, как и почему работает алгоритм персептрона.
Модель персептрона на бумаге
Модель персептрона состоит из двух основных слоев: входного слоя и выходного слоя. Самая первая модель персептрона использовалась для предсказания классификации, т. е. того, принадлежит ли конкретное наблюдение с некоторыми признаками к определенному классу или нет. Это бинарный входной классификатор, который классифицировал наблюдения по двум классам, представленным 0 и 1.
Мы поймем модель персептрона с помощью простой схемы, которая состоит из двух входных узлов, они подключены к одному выходному узлу. Входные узлы представляют количество функций, которые имеют наши данные, а выходной узел представляет, к какому классу принадлежит конкретная точка данных.
Связь между входным и выходным слоями представляет собой параметры модели персептрона, также называемые весами наблюдений. Вес — это число, на которое умножается значение наблюдения. В выходном узле все наблюдения, умноженные на соответствующие веса, суммируются, и к конечному результату также добавляется смещение. Существует также функция активации, связанная с выходным узлом, который не показан на изображении. Функция активации отображает вывод либо в 0, либо в 1 в зависимости от его значения.
Итак, для каждой входной функции первое вычисление, которое мы выполняем, выглядит следующим образом:
Здесь значения X представляют два признака i-го наблюдения, а w1 и w2 представляют два веса, связанные с двумя признаками. Во время инициализации количество весов соответствует количеству объектов в наборе данных и не меняется в течение времени выполнения.
Значение y может принимать любое число в зависимости от значения входных данных X. Чтобы получить результат классификации, мы ограничиваем значение y либо 0, либо 1. Формула активации может выглядеть примерно так:
Линейная регрессия в перцептроне
Как вы могли заметить, персептрон очень похож на линейную регрессию. Мы регрессируем по двум функциям, используя вес для каждой из них и коэффициент смещения. Что отличает его, так это его способность к обобщению. В то время как линейная регрессия ограничивается задачами регрессии, персептрон также может использоваться для задач классификации, а также с использованием функции активации для кодирования выходного ответа в двоичное состояние.
С помощью линейной регрессии модель пытается найти линейную границу, которая может четко разделить наблюдения на два соответствующих класса. Если такая граница существует, персептрон обязательно ее найдет за конечное время. Это называется теоремой сходимости персептрона. Это гарантирует, что алгоритму персептрона потребуется конечное время, чтобы дать нам желаемый результат. Это большое дело!! Теперь у нас есть алгоритм, который будет работать за конечное время и может учиться на реальных данных и делать новые прогнозы.
Имеющаяся у нас модель персептрона в ее нынешнем виде не подходит для обработки данных нелинейной регрессии или данных классификации, не имеющих линейной границы разделения. Другие глубокие нейронные сети, называемые нейронными сетями с прямой связью, больше подходят для сопоставления нелинейных функций с данными.
Давайте углубимся в детали того, как модель учится на данных.
обновление параметра
Модель перцептрона имеет связанную с ней функцию стоимости, и она работает путем сравнения прогнозов модели с истинными метками классов, и, если они неверны, они суммируются в общую стоимость прогноза и эту общую стоимость по всему набору данных поезда. используется для обновления весов и смещений модели. Формула описана ниже:
Обновление веса происходит одновременно для всех параметров и по всему набору данных поезда. После каждой эпохи обучения веса обновляются, а затем делаются новые прогнозы для следующей эпохи.
Таким образом, модель персептрона учится на протяжении многих последовательных проходов по набору данных поезда, в отличие от линейной регрессии, которая ищет глобальный минимум функции стоимости по всему пространству параметров модели. Он следует подходу, аналогичному градиентному спуску, за исключением того, что он гарантирует нахождение разделяющей границы, если она существует для заданных данных.
Выполнение
Файл модели выглядит следующим образом:
import numpy as np class Model(): def __init__(self, weights = None , bias = None , random_seed = None): self.weights = weights self.bias = bias self.random_seed = random_seed self.errors = [] def fit(self, X, y, learning_rate = 0.01, n_iters = 10): rgen = np.random.RandomState(self.random_seed) if self.weights == None: self.weights = rgen.normal(loc = 0.0, scale = 0.01, size = X.shape[-1]) if self.bias == None: self.bias = rgen.normal(loc = 0.0, scale = 0.01, size = 1) for i in range(n_iters): per_iteration_error = 0 for x_i, y_i in zip(X, y): prediction = self.predict(x_i) error = y_i - prediction self.weights += learning_rate * error * x_i self.bias += learning_rate * error # this will take care of negative errors. # if the error is not equal to 0, we get a boolean true # convering the boolean true to integer gives us 1. # for every non-zero error, we get a positive number to add to the total. per_iteration_error += int(error != 0) self.errors.append(per_iteration_error) return self def predict(self, x): prediction = np.dot(self.weights, x) + self.bias return self.activation(prediction) def activation(self, y): return np.where(y >= 0.5, 1, 0)
У нас есть функция инициализации, которая инициализирует модель весами и смещениями, если они заданы, в противном случае создается новый объект модели с параметрами, установленными на None.
Функция подгонки сначала инициализирует веса и смещения, если они установлены на None, используя предоставленное случайное начальное число (если есть). Затем мы обучаем модель для заданного количества итераций (n_iters) и для каждой итерации следуем следующей процедуре:
- Делайте прогнозы по заданной точке
- Получить ошибку в предсказании
- Обновите веса на основе ошибки
- Обновить смещение на основе ошибки
- Обновите общее количество ошибок за итерацию.
В конце каждой итерации мы добавляем ошибку в массив, который отслеживает ошибку для каждой итерации. Веса обновляются с использованием приведенной выше формулы обновления параметров.
Функция прогнозирования использует линейное уравнение, описанное для выходного слоя сети, и, таким образом, это результат, который дает модель.
Модель имеет простую функцию активации, которая возвращает 1, если прогноз больше или равен 0,5. Таким образом, наш порог принятия решения для предсказания классификации равен 0,5.
Давайте проверим нашу модель на наборе данных Iris. Тестовый скрипт приведен ниже:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from perceptron import Model from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error data = pd.read_csv("./datasets/Iris.csv") X = data.iloc[:100, [1, 3]].to_numpy() y = np.where(data.Species[:100] == "Iris-setosa", 0, 1) x_train, x_test, y_train, y_test = train_test_split(X, y, test_size = 0.1) ppr = Model(random_seed = 20) ppr_trained = ppr.fit(x_train, y_train) plt.plot(range(len(ppr_trained.errors)), ppr_trained.errors, marker = 'o') plt.show() test_preds = ppr_trained.predict(x_test) test_error = mean_absolute_error(y_test, test_preds) print(f"mean absolute error: {test_error}") print(f"true test data labels: {y_test}") print(f"predicted test data labels: {test_preds}")
Сценарий тестирования обучает нашу модель на 90 наблюдениях и проверяет производительность модели на 10 наблюдениях. Он сообщает о средней абсолютной ошибке модели, а также об истинных и прогнозируемых метках модели. Результат приведен ниже:
output mean absolute error: 0.0 true test data labels: [1 1 1 1 1 1 1 0 1 1] predicted test data labels: [1 1 1 1 1 1 1 0 1 1]
Из-за небольшого размера набора данных модель способна точно предсказать все тестовые случаи, но это может быть не так для больших наборов данных с большим количеством функций и большим количеством наблюдений.
Мы видим, что наш алгоритм работает и фактически сходится к оптимальному состоянию, как мы можем видеть по значениям ошибок на графике ниже:
Заключение (со ссылкой на исходный код)
В этом посте мы узнали об алгоритме персептрона и о том, как он работает внутри. Мы видели реализацию на Python и то, как она работает с набором данных iris. Модель действительно показывает сходимость с хорошей точностью теста.
Вот и все, увидимся в следующем, удачного кодирования :)
Рекомендации
Себастьян Рашка, Вахид Маржалили, «Машинное обучение Python», глава 2, третье издание, Packt Publishing, 2019.