Машинное обучение — от линейной регрессии до логистической регрессии [с подробным выводом и кодом]

машинное обучение

Эта статья возникла из личного публичного аккаунта:TechFlow, оригинальность это не просто, прошу внимания


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

Новые заинтересованные и забытые студенты могут щелкнуть ссылку ниже, чтобы просмотреть предыдущее содержание линейной регрессии и градиентного спуска.

Статья о градиентном спуске

Подробный вывод моделей линейной регрессии


Регрессия и классификация


В машинном обучении модели делятся на две категории в соответствии с разными результатами прогнозирования.Если мы хотим, чтобы модель предсказывала одно или несколько непрерывных значений, такие проблемы называются проблемами регрессии. Такие, как оценка общей будущей цены акций, оценка будущей температуры и т. д., — все это проблемы регрессии. Существует еще одна категория проблем классификации.Результат предсказания модели является дискретным значением, то есть существуют только фиксированные типы результатов. Общие из них включают идентификацию спама, идентификацию изображения веб-страницы и так далее.

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


логистическая регрессия


Модель логистической регрессии удивительна.Хотя суть ее в регрессии, это классификационная модель, и в ее названии содержится слово «регрессия», которое заставляет людей чувствовать себя необъяснимо.

Если вы новичок, это нормально чувствовать головокружение, ничего страшного, давайте немного проясним это.

Давайте сначала вернемся к линейной регрессии, мы все знаем, что в линейной регрессииy=WX+b. Мы можем найти y, соответствующий X, через W и b, где y — непрерывное значение, что является регрессионной моделью, верно? Но что, если мы хотим, чтобы эта модель выполняла классификацию? Легко подумать, что мы можем установить порог искусственно, например, мы оговариваем, что окончательная классификация y > 0 равна 1, а финальная классификация y

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

Вскоре информатики нашли такую ​​функцию, которая является сигмовидной функцией, и ее выражение:

\sigma(x)= \frac{1}{1+e^{-x}}

Его функциональное изображение выглядит следующим образом:

Можно видеть, что сигмовидная функция принимает значение 0,5 при x = 0, предел равен 1 при положительной бесконечности и предел равен 0 при отрицательной бесконечности, а функция непрерывна и может быть получена везде. Диапазон значений функции значения сигмоида составляет 0-1, что очень подходит для отражения вероятности того, что что-то произойдет. Мы верим\sigma(x)представляет вероятность того, что x произойдет, то вероятность того, что x не произойдет, равна1-\sigma(x). Мы рассматриваем возникновение и невозникновение как две категории, тогда сигмовидная функция преобразуется в классификационную функцию, если\sigma(x)>0.5представляет класс 1, иначе класс 0.

Здесь очень просто, с помощью линейной регрессии мы можем получитьy = WX + b, P(1)=\sigma(y), P(0)=1-\sigma(y). Другими словами, мы помещаем слой сигмовидной функции вне модели линейной регрессии, Вычисляя разные y, мы получаем разные вероятности и, наконец, получаем разные результаты классификации.


функция потерь


Следующий процесс вывода очень энергичный, я думаю, вы увидите его три раза после прочтения (поставьте лайк, ретвитните и подпишитесь).

Приступим, сначала определимся с обозначениями, для различения назовем истинный класс в обучающей выборке какy,yМатрица записывается какY. Аналогично, один образец записывается какx,xМатрица записывается какX. Результат одного предсказания записывается как\hat{y}, все результаты предсказания записываются как\hat{Y}.

Для одной выборки y имеет два значения, которые могут быть 1 или 0. 1 и 0 представляют две разные категории. мы надеемсяy = 1когда,\hat{y}как можно больше,y = 0час,1 - \hat{y}как можно больше\hat{y}Старайтесь быть как можно меньше, потому что он принимает значения от 0 до 1. Мы используем одну формулу, чтобы объединить эти два случая:

P(y|x)=\hat{y}^y(1-\hat{y})^{1-y}

Давайте вставим это,y=0Когда первый член равен 1, выражение оставляет только последний член.y=1, последний элемент равен 1, остается только первый элемент. Следовательно, эта формула может выражать вероятность точного предсказания, и мы надеемся, что эта вероятность максимально велика. Очевидно,P(y|x)>0, поэтому мы можем зарегистрировать его, потому что функция журнала монотонна. такP(y|x)Значение при принятии наибольшего значения равноlogP(y|x)Возьмите наибольшее значение.

\log P(y|x)=y\log \hat{y} + (1-y)\log (1-\hat{y})

Мы ожидаем, что это значение будет наибольшим, то есть ожидаем, что его противоположность будет наименьшей, мы делаемJ=-\log P(y|x), что дает его функцию потерь:

J(\theta)=-\frac{1}{m}Y\log \hat{Y} + (1-Y)\log (1-\hat{Y})

Если вы знаете концепцию перекрестной энтропии, вы обнаружите, что выражение этой функции потерь на самом деле является перекрестной энтропией. Перекрестная энтропия используется для измерения «расстояния» между двумя распределениями вероятностей.Чем меньше перекрестная энтропия, тем ближе два распределения вероятностей, поэтому ее часто используют в качестве функции потерь модели классификации. Мы не будем здесь вдаваться в подробности концепции кросс-энтропии и подробно представим ее в последующих статьях. Функция потерь, которую мы вывели случайно, является перекрестной энтропией. Это не совпадение. На самом деле нижний слой поддерживается набором математической логики теории информации. Мы не будем делать много расширений, и заинтересованные студенты могут узнать о Это.


хардкорный вывод


Следующим шагом с функцией потерь является нахождение градиента для достижения градиентного спуска.

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

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

\begin{aligned} (\frac{1}{1+e^{-x}})'&=\frac{e^{-x}}{(1+e^{-x})^2} \\ &=\frac{1+e^{-x}-1}{(1+e^{-x})^2} \\ &=\frac{1}{1+e^{-x}}\cdot (1-\frac{1}{1+e^{-x}}) \\ &=\sigma(x) (1-\sigma(x)) \end{aligned}

так как\hat{y}=\sigma(\theta X), вносим в функцию потерь, можем получить, где\sigma(\theta)=\sigma(\theta X):

J(\theta)=-\frac{1}{m}Y\log \sigma(\theta) + (1 - Y)\log( 1- \sigma(\theta))

Затем мы спрашиваемJ(\theta)правильно\thetaЧастная производная от , здесь нам нужно заменить вышеуказанную грань\sigma(x)Вывод вывода:

\begin{aligned} \frac{\partial}{\partial \theta}J(\theta)&=-\frac{1}{m}(Y\cdot \frac{1}{\sigma(\theta)}\cdot \sigma'(\theta)+(1-Y)\cdot \frac{1}{1-\sigma(\theta)}\cdot \sigma'(\theta)\cdot(-1)) \\ &=-\frac{1}{m}(Y\cdot \frac{1}{\sigma(\theta)}\cdot \sigma(\theta)(1-\sigma(\theta))\cdot X-(1-Y)\cdot \frac{1}{1-\sigma(\theta)}\cdot \sigma(\theta)(1-\sigma(\theta))\cdot X) \\ &=-\frac{1}{m}(Y(1-\sigma(\theta)) - \sigma(\theta)+Y\cdot \sigma(\theta))\cdot X\\ &=-\frac{1}{m}(\sigma(\theta) - Y)\cdot X\\ &=-\frac{1}{m}(\hat{Y} - Y)\cdot X \end{aligned}

Кодовый бой


Формулы градиента закончились, до написания кода еще далеко?

Однако без риса трудно готовить.Прежде чем мы построим модель, давайте попробуем создать пакет данных.

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

Чтобы предотвратить смещение сигмовидной функции, мы масштабируем оценки каждого курса до интервала (0, 1). Суммарный балл более 140 баллов по обоим предметам считается удовлетворительным.

import numpy as np
def load_data():
    X1 = np.random.rand(50, 1)/2 + 0.5
    X2 = np.random.rand(50, 1)/2 + 0.5
    y = X1 + X2
    Y = y > 1.4
    Y = Y + 0
    x = np.c_[np.ones(len(Y)), X1, X2]
    return x, Y

Данные обучения, полученные таким образом, имеют две характеристики, а именно оценки студентов по двум курсам и смещение 1, которое используется для записи постоянного смещения.

Тогда по формуле выше не сложно (действительно не сложно) реализовать функции сигмовидного и градиентного спуска.

def sigmoid(x):
    return 1.0/(1+np.exp(-x))
    
def gradAscent(data, classLabels):
    X = np.mat(data)
    Y = np.mat(classLabels)
    m, n = np.shape(dataMat)
    # 学习率
    alpha = 0.01
    iterations = 10000
    wei = np.ones((n, 1))
    for i in range(iterations):
        y_hat = sigmoid(X * wei)
        error = Y - y_hat
        wei = wei + alpha * X.transpose()*error
    return wei

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

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

import matplotlib.pyplot as plt
def plotPic():
    dataMat, labelMat = load_data()
    #获取梯度
    weis = gradAscent(dataMat, labelMat).getA()
    n = np.shape(dataMat)[0]
    xc1 = []
    yc1 = []
    xc2 = []
    yc2 = []
    #数据按照正负类别划分
    for i in range(n):
        if int(labelMat[i]) == 1:
            xc1.append(dataMat[i][1])
            yc1.append(dataMat[i][2])
        else:
            xc2.append(dataMat[i][1])
            yc2.append(dataMat[i][2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xc1, yc1, s=30, c='red', marker='s')
    ax.scatter(xc2, yc2, s=30, c='green')
    #绘制分割线
    x = np.arange(0.5, 1, 0.1)
    y = (-weis[0]- weis[1]*x)/weis[2]
    ax.plot(x, y)
    plt.xlabel('X1')
    plt.ylabel('X2')
    plt.show()

Окончательный результат выглядит следующим образом:


Версия стохастического градиентного спуска


Можно обнаружить, что после 10 000 итераций полученная нами модель может правильно идентифицировать все выборки.

То, что мы только что реализовали, — это алгоритм полного градиентного спуска, и мы также можем использовать стохастический градиентный спуск для оптимизации. Оптимизация тоже очень простая, когда мы вычисляем градиент, мы уже не ориентируемся на весь объем данных, а выбираем один из набора данных для расчета градиента.

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

def stocGradAscent(data, classLab, iter_cnt):
    X = np.mat(data)
    Y = np.mat(classLab)
    m, n = np.shape(dataMat)
    weis = np.ones((n, 1))
    for j in range(iter_cnt):
        for i in range(m):
            # 使用反比例函数优化学习率
            alpha = 4 / (1.0 + j + i) + 0.01
            randIdx = int(np.random.uniform(0, m))
            y_hat = sigmoid(np.sum(X[randIdx] * weis))
            error = Y[randIdx] - y_hat
            weis = weis + alpha * X[randIdx].transpose()*error
    return weis

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

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

На сегодняшней статье все, если вы чувствуете, что что-то приобрели, пожалуйста, следуйте ей.Отсканируйте код и обратите вниманиеЧто ж, твое маленькое усилие много значит для меня.