Введение в применение логистической регрессии для двоичной классификации с использованием PyTorch.

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

Вот линейно разделимые группы:

  1. Красный = 0
  2. Синий = 1

Мы хотим использовать логистическую регрессию для сопоставления любой пары [x1, x2] с соответствующим классом (красным или синим).

Шаг 1. Разделение нашего набора данных на разделение поездов и тестов.

Мы делаем это, чтобы оценить производительность наших моделей на данных, которые они не увидели во время обучения. Обычно, если вы говорите кому-то, что ваша модель точна на 97%, предполагается, что вы говорите о точности проверки / тестирования.

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

X_train, X_test, y_train, y_test = train_test_split(
 inputs, labels, test_size=0.33, random_state=42)

Шаг 2: построение класса модели PyTorch

Мы можем создать модель логистической регрессии с помощью следующего кода:

import torch
class LogisticRegression(torch.nn.Module):
     def __init__(self, input_dim, output_dim):
         super(LogisticRegression, self).__init__()
         self.linear = torch.nn.Linear(input_dim, output_dim)
     def forward(self, x):
         outputs = torch.sigmoid(self.linear(x))
         return outputs

В нашем «прямом» проходе нейронной сети PyTorch (на самом деле это просто перцептрон) визуальное представление и соответствующие уравнения показаны ниже:

Где:

Сигмовидная функция чрезвычайно полезна по двум основным причинам:

  1. Он преобразует наши выходные данные линейной регрессии в вероятность от 0 до 1. Затем мы можем принять любую вероятность больше 0,5 за 1 и ниже за 0.
  2. В отличие от пошаговой функции (которая также преобразует данные в двоичный случай), сигмоид является дифференцируемым, что необходимо для оптимизации параметров с помощью градиентного спуска (мы покажем позже).

Шаг 3: Инициализация модели

Также нам нужно назначить некоторые гиперпараметры:

epochs = 200000
input_dim = 2 # Two inputs x1 and x2 
output_dim = 1 # Single binary output 
learning_rate = 0.01

Определения параметров:

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

Приведенный ниже код инициализирует созданный нами ранее класс модели:

model = LogisticRegression(input_dim,output_dim)

Шаг 4. Инициализация функции потерь и оптимизатора

criterion = torch.nn.BCELoss()

  • m = Количество обучающих примеров
  • y = истинное значение y
  • y ^ = прогнозируемое значение y
  • y = действительное значение y
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

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

Примечание. Чтобы точно и быстро достичь минимума функции потерь, полезно постепенно снижать скорость обучения, а оптимизаторы, такие как алгоритм оценки адаптивного движения (ADAM), который есть в PyTorch также реализовано, сделайте это за нас. Вы можете узнать больше о реализации этих оптимизаторов в PyTorch по адресу https://pytorch.org/docs/stable/optim.html.

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

  • Альфа - скорость обучения

Вам может быть интересно, откуда мы берем dL / dw и dL / dbeta,, и это был бы отличный вопрос! В нейронных сетях мы используем обратное распространение для получения частных производных. К счастью для нас, в логистической регрессии уравнения упрощаются, и я покажу это (вместе с обратным распространением для сети) ниже.

Используя цепное правило, мы можем вывести, что:

Частные производные показаны ниже:

Просто уравнения, и вы получите:

Так что на самом деле вы бы сделали:

Аналогичным образом мы можем получить dL / dbeta. К счастью, Autograd помогает сделать все это за нас!

Шаг 5: Обучите модель

Сначала мы конвертируем наши входные данные и метки из массивов numpy в тензоры.

X_train, X_test = torch.Tensor(X_train),torch.Tensor(X_test)
y_train, y_test = torch.Tensor(y_train),torch.Tensor(y_test)

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

Убытки за 10 000 эпох:

Шаг 6: нанесение результатов

Поскольку мы знаем, что граница решения будет w * x + b = 0,5, мы можем построить границу решения. Результаты представлены ниже:

Поезд:

Тест:

Шаг 7: Как делать прогнозы на основе новых данных!

Если у вас появилась новая точка в x1 = 1, x2 = 1 визуально (в 2-мерном пространстве), легко сказать, что мы должны классифицировать точку как «красный ». Итак, давайте проверим, правильно ли работает наша модель, и покажем, как получить прогноз от модели на новых данных:

x1 = 1
x2 = 1
new_data = torch.tensor([x1,x2]).type(torch.FloatTensor)
with torch.no_grad():
    prediction = model(new_data).round()
    if prediction == 1.0:
        print(f'The model classifies this point as RED')
    else:
        print(f'The model classifies this point as BLUE')

Новая точка отображается на графике с данными обучения ниже:

ВЫХОД:

>>> The model classifies this point as RED

Полный код:

Дополнительные ресурсы:

Давайте подключимся!

  1. Твиттер
  2. LinkedIn
  3. GitHub