Научитесь кодировать алгоритм логистической регрессии на Python для выполнения двоичной классификации

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

Понятия и формулы

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

Здесь z - произведение входной переменной X и случайно инициализированного коэффициента theta.

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

Здесь y - исходная выходная переменная, а h - прогнозируемая выходная переменная. Наша цель - максимально снизить стоимость. Теперь нам нужно обновить значения тета, чтобы наш прогноз был как можно ближе к исходной выходной переменной. Если мы возьмем частичное дифференцирование функции стоимости по тета, мы найдем градиент для значений тета. Я не собираюсь здесь заниматься расчетом. Наш градиентный спуск, который будет использоваться для обновления теты, будет выглядеть следующим образом:

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

Реализация логистической регрессии в Python

  1. Импортируйте необходимые пакеты и набор данных. Я нашел этот набор данных из курса машинного обучения Эндрю Нг на Coursera.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv('ex2data1.txt', header=None)
df.head()

2. Разделите входные и выходные переменные. В этом наборе данных столбцы 0 и 1 являются входными переменными, а столбец 2 - выходной переменной. Итак, нам нужно будет предсказать столбец 2.

X = df.iloc[:, :-1]
y = df.iloc[:, -1]

3. Добавьте столбец смещения к X. Значение столбца смещения обычно равно единице.

X = np.c_[np.ones((X.shape[0], 1)), X]
X[:10]

4. Здесь наш X - двумерный массив, а y - одномерный массив. Давайте сделаем "y" двухмерным, чтобы оно соответствовало размерам.

y = y[:, np.newaxis]
y[:10]

5. Определите сигмовидную функцию.

def sigmoid(x, theta):
    z= np.dot(x, theta)
    return 1/(1+np.exp(-z))

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

def hypothesis(theta, x):
    return sigmoid(x, theta)

7. Напишите определение функции стоимости, используя приведенную выше формулу.

def cost_function(theta, x, y):
    m = X.shape[0]
    h = hypothesis(theta, x)
    return -(1/m)*np.sum(y*np.log(h) + (1-y)*np.log(1-h))

8. Напишите функцию градиентного спуска в соответствии с приведенным выше уравнением:

def gradient(theta, x, y):
    m = X.shape[0]
    h = hypothesis(theta, x)
    return (1/m) * np.dot(X.T, (h-y))

9. Импортируйте функцию оптимизации, которая оптимизирует для нас тэту. Эта оптимизация примет функцию для оптимизации, функцию градиента и аргумент, который необходимо передать функции в качестве входных данных. В этой задаче оптимизируемой функцией является функция стоимости. Поскольку мы хотим минимизировать стоимость, функция градиента будет gradient_descent, а аргументы - X и y. Эта функция также будет принимать «x0» - параметры, которые необходимо оптимизировать. В нашем случае нам нужно оптимизировать тета. Итак, мы должны инициализировать тэту. Я инициализировал значения тета нулями. Как я упоминал ранее, нам нужно инициализировать одно значение тета для каждой входной функции. У нас есть три функции ввода. Если вы посмотрите на X, у нас есть столбцы 0 и 1, а затем мы добавили столбец смещения. Итак, нам нужно инициализировать три значения тета.

theta = np.zeros((X.shape[1], 1))
from scipy.optimize import minimize,fmin_tnc
def fit(x, y, theta):
    opt_weights = fmin_tnc(func=cost_function, x0=theta, fprime=gradient, args=(x, y.flatten()))
    return opt_weights[0]
parameters = fit(X, y, theta)

Параметры оказались [-25.16131854, 0.20623159, 0.20147149].

10. Используйте эти параметры в качестве значений тета и функции гипотезы для расчета окончательной гипотезы.

h = hypothesis(parameters, X)

11. Используйте гипотезу для прогнозирования выходной переменной:

def predict(h):
    h1 = []
    for i in h:
        if i>=0.5:
            h1.append(1)
        else:
            h1.append(0)
    return h1
y_pred = predict(h)

12. Рассчитайте точность.

accuracy = 0
for i in range(0, len(y_pred)):
    if y_pred[i] == y[i]:
        accuracy += 1
accuracy/len(y)

Окончательная точность 89%.

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

  1. Логистическая регрессия с оптимизацией градиентного спуска.
  2. Мультиклассовая классификация с подходом градиентного спуска.
  3. Полиномиальная регрессия в Python с нуля.

Перейдите на эту страницу для набора данных:



Вот полный рабочий код: