Введение в применение логистической регрессии для двоичной классификации с использованием PyTorch.
Бинарная логистическая регрессия используется для классификации двух линейно разделимых групп. Это предположение о линейной разделимости делает логистическую регрессию чрезвычайно быстрой и мощной для простых задач машинного обучения. Пример линейно разделяемых данных, для которых мы будем выполнять логистическую регрессию, показан ниже:
Вот линейно разделимые группы:
- Красный = 0
- Синий = 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 (на самом деле это просто перцептрон) визуальное представление и соответствующие уравнения показаны ниже:
Где:
Сигмовидная функция чрезвычайно полезна по двум основным причинам:
- Он преобразует наши выходные данные линейной регрессии в вероятность от 0 до 1. Затем мы можем принять любую вероятность больше 0,5 за 1 и ниже за 0.
- В отличие от пошаговой функции (которая также преобразует данные в двоичный случай), сигмоид является дифференцируемым, что необходимо для оптимизации параметров с помощью градиентного спуска (мы покажем позже).
Шаг 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
Полный код:
Дополнительные ресурсы:
- Https://pytorch.org/docs/stable/nn.html
- Https://deeplearning.cs.cmu.edu/F21/index.html
- Https://www.youtube.com/watch?v=MswxJw-8PvE&t=304s