Логистическая регрессия серии базовых алгоритмов машинного обучения

машинное обучение искусственный интеллект Python алгоритм NumPy
Логистическая регрессия серии базовых алгоритмов машинного обучения

Впереди написано: я объясню часто используемые алгоритмы машинного обучения с точки зрения новичка (уровень). Мой собственный уровень действительно ограничен, и если есть какие-то ошибки, я надеюсь, что вы укажете на них и не будете вводить вас в заблуждение. Тогда это вторая статья из этой серии.Для новичков, если вы не читали первую статью, рекомендуется ее прочитать.Линейная регрессия базовых алгоритмов машинного обучения, в котором упоминается много базовых математических знаний и некоторое мышление машинного обучения, что очень полезно для понимания этой статьи Многие вещи процесса машинного обучения здесь специально не представлены, но прямо объясняют, почему логика Регрессия должна быть реализована таким образом , уделяя больше внимания реализации самой логистической регрессии, а не пониманию процессов машинного обучения.

экспериментальный код-Справочная литература-[Подробности см. в блоге в конце]

Сначала рендеры ^_^

0 готов

0.1 Окружающая среда

Python: 3.5

TensorFlow: Anaconda3 envs

IDE: PyCharm 2017.3.3

0.2 Базовое понимание

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

1 Бинарная классификация

1.1 Предложите подходящую функциюSigmoid

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

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

y=\begin{cases} 1,\quad x > 5 \\\\ 0,\quad x \leq 5 \end{cases}

Тогда он идеально вписывается в текущее распределение данных, и интуиция подсказывает нам, что весьма вероятно, что он обладает сильной способностью предсказывать данные. Далее найдитеSфункция формы как функция подгонки. Здесь видно, что наша функция нелинейна. Вот звонокSigmoidФункция:

y = \frac{1}{1 + e^{-x}}

Как видно из изображения, совершенство этой функции — это то, что мы имели в виду.

# coding: utf-8

import numpy as np
import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 6, 7, 8, 9, 10]
y = [0, 0, 0, 0, 1, 1, 1, 1, 1]

train_X = np.asarray(x)
train_Y = np.asarray(y)

fig = plt.figure()
plt.xlim(-1, 12)
plt.ylim(-0.5, 1.5)
plt.scatter(train_X, train_Y)

s_X = np.linspace(-2, 12, 100)
s_Y = 1/(1 + np.power(np.e, -6*(s_X - 5)))
plt.plot(s_X, s_Y)
plt.savefig("linear2LogisticreGressionGraphAddSigmoid.png")
# plt.savefig("linear2LogisticreGressionGraph.png")
plt.show()

1.2 Расширенная классификация

Как упоминалось ранее, чтобы лучше понять логистическую регрессию, данные немного особенные и единичные.Давайте посмотрим на другой набор данных:

Точечная диаграмма с таким очевидным эффектом кластеризации может рассматриваться как проблема классификации, так как же мы можем использовать вышеупомянутую логистическую регрессию для решения таких проблем классификации?

Здесь нужно немного изменить мышление.Ранее мы использовалиyЗначение , как выход, здесь больше нет, здесь дан результат, который нужно предсказать(x, y)Выясните, является ли точка красным кругом или синим треугольником? Так что найдиg(x, y)функция для обработки, предыдущаяSigmoidФункции могут помочь нам классифицировать, если мы предполагаем1и0Каждый представляет ситуацию, тогда мы получаем1/0можно предположить, когда(x, y)Является ли текущая ситуация красным кругом или синим треугольником, текущая ситуация такова, какg(x, y)Результат предварительной обработкиSigmoidфункция подключения. Возможно, вы уже подумали оg(x, y)диапазон значений какSigmoidобласть определения. затем дали(x,y)Мы можем получить интервал в[0, 1]значение внутри. Теперь функция может удовлетворить наши требования.

Чтобы имитировать мышление предыдущего машинного обучения, мы единообразно используем входную матрицу для заданного ввода.Xвыражать(x, y)затем добавьте весаW, то функцияg(W, X), то нам нужно определить модель, чтобы различать это распределение? Если вы видели код, то знаете, что по умолчанию используетсяx + y > 7Класс, на который нужно разделить, поэтому линейная модель, естественно, выбирается в качестве первого выбора. Что касается того, как выбрать модель, я думаю, что самое краткое представление часто является лучшим.Давайте рассмотрим пример г-на Ву Энда, чтобы испытать этот процесс.

Поскольку он линейный, то непосредственно получаетсяg(W, X) = W^TXНапоминание здесь{}^TЭто связано с тем, что все наши векторы по умолчанию являются векторами-столбцами. Если вы это понимаете, с этим будет легко справиться.SigmoidФункцию подгонки можно получить:

h_W(X) = \frac{1}{1 + e^{-W^TX}}

1.3 Интуитивное получение функции потерь

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

Ниже мы анализируем только1как пройтиh_W(x_1) < h_W(x_2) < h_W(x_3)найти функцию, выражающую потери. Во-первых, несомненно, чтоh_W(x_1)наказание самое большое. Поскольку из рисунка видно, что его предсказание является самым возмутительным, функция потерь должна быть убывающей функцией, а затем продолжить анализ, подходит ли функция потерь дляh_W(x_i)Изменение является равномерным изменением, т. е. каков диапазон убывания этой убывающей функции? Это понятно,h_W(x_i)чем ближе0, его наказание должно быть чем-то похоже на экспоненциальный рост. Чем меньше значение, тем сильнее немедленно увеличивается штраф, так что результаты подбора параметров, когда окончательная функция потерь сходится, больше соответствуют большинству данных, и ее экстремальная классификация не произойдет, потому что штраф за экстремальные данные слишком велик. . . . Ну, эта функция отвечает трем характеристикам,递减,导数绝对值递减(величина декремента должна быть уменьшена) и область определения[0, 1]Размах должен быть большим, предпочтительно от положительной бесконечности до0потому что если значение функции0Мы не собираемся штрафовать этот момент, так что должно быть0значение этой функции. В этот момент вы, возможно, подумали, что логарифмическая функция — это именно тот случай. Итак, есть следующие результаты:

loss(h_W(x_i), y_i) = -log(h_W(x_i))\quad if\ y_i = 1

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

Окончательный результат приведен непосредственно ниже:

loss(h_W(x_i), y_i) = -y_i * log(h_W(x_i)) - (1 - y_i)*log(1 - h_W(x_i))

1.4 Анализ функции потерь с точки зрения теории вероятностей

Помните, что логистическую регрессию можно рассматривать как проблему классификации? Для прогнозирования проблем классификации мы можем рассчитать его как вероятность. так что функцияh_W(x_i)можно увидеть, как вWвниз, войтиx_iценность1Вероятность. И все, что нам нужно сделать, это найтиWда для данногоx_iвероятность как можно больше иy_iвстречает. Тогда вы обнаружите, что результатy_iследуйте распределению Бернулли, которое является случайной величинойYЗначение может быть только0/1,существуетh_W(x_i)считается взятием1случай вероятности, когда это значение больше, чем0.5Мы рассматриваем классификацию как1.

Что ж, «забудьте» все вышеперечисленное, а затем войдите в режим мышления, основанный на теории вероятностей. Предположим, что на этой плоскости бесконечное количество точек, а данные, которые мы даем, — это просто выборка данных. Но мы не можем перечислить все случаи, поэтому все, что нам нужно сделать, это оценить общее распределение по предоставленным выборкам. На самом деле это связано еще и с тем, что машинное обучение требует большого количества выборок для обучения, очевидно, что чем больше объем данных, тем меньше случайная ошибка и тем ближе распределение выборки к общему распределению. Возвращаясь к теории вероятностей, я обнаружил, что легко сбиться с пути, когда я это пишу ???. Сейчас ситуация с нашей статистикой такая: по распределению Бернулли. И этот метод знания параметров распределения, чтобы найти параметры, которые могут соответствовать распределению. В теории вероятностей есть метод оценки параметров, который называется:极大似然估计. Если вы не понимаете, прочитайте краткое введение:

Оценка максимального правдоподобия в общепринятом понимании заключается в использовании известной информации о результатах выборки для вывода значений параметров модели, которые с наибольшей вероятностью (максимальная вероятность) вызовут появление этих результатов выборки! Другими словами, оценка максимального правдоподобия обеспечивает способ оценки параметров модели с учетом данных наблюдений, то есть: «Модель задана, параметры неизвестны».

Ссылка из@愛陈: понять оценку максимального правдоподобия в одной статье

Согласно приведенному выше смыслу, очевидно, что мы кладемh_W(x_i) = P(y = 1|x_i;W)Тогда конечно:

P(y_i|x_i;W) = {h_W(x_i)}^{y_i} * {(1 - h_W(x_i))}^{1 - y_i}

это сингл(x_i, y_i)Вероятность. Если всю выборку рассматривать какnА как насчет независимых реплик? Вероятность того, что это произойдет, является продуктом этого. использовать здесьX, YВектор представляет все данные. который:

P(Y|X;W) = \prod_{i = 1}^{n}P(y_i|x_i; W) = \prod_{i = 1}^{n}{h_W(x_i)}^{y_i} * {(1 - h_W(x_i))}^{1 - y_i}

Видно, что этоWТеперь перейдем к метафизической части функции . Мы считаем, что, поскольку это событие произошло, вероятность его возникновения должна быть наибольшей среди всех событий. Если нет, то почему оно происходит? Ха-ха, это способ проповедовать (сюань) и рассуждать (сюэ). Максимум? Это легко сделать, попросить совета напрямую? Нет, нет, это слишком сложно. . . Самый распространенный трюк в старшей школе: умножай, чтобы сложить, используй логарифмы. затем умножить на-\frac{1}{n}Просто программирование, чтобы найти минимальное значение.

loss(W) = -\frac{1}{n}log(P(Y|X;W)) = -\frac{1}{n}\sum_{i = 1}^{n}y_i * log(h_W(x_i)) + (1 - y_i)*log(1 - h_W(x_i))

1.5 Градиентный спуск для поиска экстремальных значений

Задав функцию потерь ранее, мы снова используем алгоритм градиентного спуска для обновления весов. Если мы делаем это рукописным кодом, мы все равно запрашиваем частную производную ???

Для вещей с большими номерами я тут ленивый.Если слова немного сложно набирать, я просто делаю скриншот.Ведь это не сложно:

Тогда функция обновления:

w_j := w_j - \frac{\alpha}{n}\sum_{i=1}^{n}(h_W(x_i) - y_i)x_{i_j}

Обратите внимание здесьi, j,x_iпредставляет вектор-столбец,x_{i_j}представительiклассифицироватьjчисла. На самом деле, если хорошенько подумать, можно обнаружить, что обновленныйw_jЭто число, когда получена частная производная от него, остаток равен тому, что на него умножается.x_{i_j}. Поскольку предыдущее исследование начиналось с одной точки, для лучшего понимания индекс используется напрямую, но при использовании линейной граничной функции должно быть представление о матрице. Я не буду здесь вдаваться в подробности, а более поздняя многомерность должна использовать векторную форму.

1.6 Рукописный код

Что ж, с базовой логикой разобрались, она похожа на линейную регрессию, но здесь возникает задача линейной бинарной классификации, исходные данные нужно преобразовать в линейные значения, а затем линейные значения сопоставить сsigmoidНа области определения функции согласноsigmoidПо функциональным признакам можно сделать вывод, что данные классифицируются как положительные.(1)вероятность, а затем оценить ее.

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

Требуемые библиотеки и данные лучше всего использовать здесь для получения большей точностиfloat64:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

x = [1, 2, 3, 4, 6, 7, 8, 9, 10]
y = [0, 0, 0, 0, 1, 1, 1, 1, 1]

train_X = np.asarray(np.row_stack((np.ones(shape=(1, len(x))), x)), dtype=np.float64)
train_Y = np.asarray(y, dtype=np.float64)
train_W = np.asarray([-1, -1], dtype=np.float64).reshape(1, 2)

определениеsigmoidиlossфункция

def sigmoid(X):
    return 1 / (1 + np.power(np.e, -(X)))


def lossfunc(X, Y, W):
    n = len(Y)
    return (-1 / n) * np.sum(Y * np.log(sigmoid(np.matmul(W, X))) + (1 - Y) * np.log((1 - sigmoid(np.matmul(W, X)))))

Реализовать обновление параметров (алгоритм градиентного спуска)

def gradientDescent(X, Y, W, learningrate=0.001, trainingtimes=500):
    n = len(Y)
    for i in range(trainingtimes):
        W = W - (learningrate / n) * np.sum((sigmoid(np.matmul(W, X)) - Y) * X, axis=1)

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

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

# coding: utf-8

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

x = [1, 2, 3, 4, 6, 7, 8, 9, 10]
y = [0, 0, 0, 0, 1, 1, 1, 1, 1]

train_X = np.asarray(np.row_stack((np.ones(shape=(1, len(x))), x)), dtype=np.float64)
train_Y = np.asarray(y, dtype=np.float64)
train_W = np.asarray([-1, -1], dtype=np.float64).reshape(1, 2)


def sigmoid(X):
    return 1 / (1 + np.power(np.e, -(X)))


def lossfunc(X, Y, W):
    n = len(Y)
    return (-1 / n) * np.sum(Y * np.log(sigmoid(np.matmul(W, X))) + (1 - Y) * np.log((1 - sigmoid(np.matmul(W, X)))))


Training_Times = 100000
Learning_Rate = 0.3

loss_Trace = []
w_Trace = []
b_Trace = []


def gradientDescent(X, Y, W, learningrate=0.001, trainingtimes=500):
    n = len(Y)
    for i in range(trainingtimes):
        W = W - (learningrate / n) * np.sum((sigmoid(np.matmul(W, X)) - Y) * X, axis=1)
        # for GIF
        if 0 == i % 1000 or (100 > i and 0 == i % 2):
            b_Trace.append(W[0, 0])
            w_Trace.append(W[0, 1])
            loss_Trace.append(lossfunc(X, Y, W))
    return W


final_W = gradientDescent(train_X, train_Y, train_W, learningrate=Learning_Rate, trainingtimes=Training_Times)

print("Final Weight:", final_W)
print("Weight details trace: ", np.asarray([b_Trace, w_Trace]))
print("Loss details trace: ", loss_Trace)

fig, ax = plt.subplots()
ax.scatter(np.asarray(x), np.asarray(y))
ax.set_title(r'$Fitting\ line$')


def update(i):
    try:
        ax.lines.pop(0)
    except Exception:
        pass
    plot_X = np.linspace(-1, 12, 100)
    W = np.asarray([b_Trace[i], w_Trace[i]]).reshape(1, 2)
    X = np.row_stack((np.ones(shape=(1, len(plot_X))), plot_X))
    plot_Y = sigmoid(np.matmul(W, X))
    line = ax.plot(plot_X, plot_Y[0], 'r-', lw=1)
    ax.set_xlabel(r"$Cost\ %.6s$" % loss_Trace[i])
    return line


ani = animation.FuncAnimation(fig, update, frames=len(w_Trace), interval=100)
ani.save('logisticregression.gif', writer='imagemagick')

plt.show()

2 Многомерная классификация

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

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

Здесь мы решаем проблему еще одной переменной, выбирая основную переменную в качестве1, остальные значения0, а затем можно разделить на два. Другой вопрос, как подобрать параметры? Поскольку мы можем преобразовать ее в задачу о делении пополам, то для каждого деления пополам нам нужно выбрать только(W, X).XОчевидно, есть два основных(X1, X2)Однако для выбора более подходящей границы недостаточно иметь только эти два признака, поэтому другиеX1^2,X1*X2 \ldotsПодождите, в зависимости от того, какую границу вы хотите установить, выберите тип элемента и, аналогично для 3D, выберите количество элементов, которое может выражать криволинейную плоскость. Выберите вес ниже, то есть коэффициент перед признаком.Если признак выбран, то просто добавьтеbiasДостаточно.

Вот небольшой пример того, как это сделать:

Ясно, что здесь присутствует тенденция к окружности, поэтому круги, естественно, рассматриваются. То есть выбралX: X1,\ X2,\ X1^2,\ X2^2ТакsigmoidТогда функция может быть определена как:

h_{(bias, w_1, w_2, w_3, w_4)}({x_1, x_2, x_1^2, x_2^2}) = \frac{1}{1 + e^{-{bias + w_1 * x_1 + w_2 * x_2 + w_3 * x_1^2 + w_4 * x_2^2}}}

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

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

3 Оптимизация модели

3.1 Направление алгоритма

Существуют не только алгоритмы градиентного спуска для решения задач оптимизации, но и другие способы более быстрой сходимости. Например: метод сопряженных градиентовBFGS(метод переменного масштабирования) иL-BFGS(метод ограниченной переменной шкалы) и т. д., но конкретной реализации этих алгоритмов я еще не видел, так что вот ФЛАГ. Однако мы обычно используем эти алгоритмы для вызова готовых библиотек, ведь алгоритмы, написанные нами, более или менее ущербны.

3.2 Направление степени посадки

В предыдущем примере вы обнаружите, что после выбора количества функций очень важно, как выбрать количество итераций. В качестве небольшого примера: мы подбираем график рассеяния, который соответствует распределению квадратичной функции, если выбранная вами модельb + w*xТогда как ни беги, а нужного результата не получишь.x^2Этот термин функции добавлен, чтобы не было недообучения. Точно так же, если вы выберете квадратичную модель, но количества итераций недостаточно, это также приведет к недообучению.Разумно сказать, что если прогноз и распределение модели согласуются, чем больше итераций, тем лучше. Но, если вы не уверены, добавьте ещеx^3Включено количество характеристик данных, изначально данные соответствуют характеристикам квадратичной функции, если количество тренировок хорошо контролируется, хорошую модель также можно обучить, это не что иное, как положитьx^3Если количество тренировок плохо контролируется, это неизбежно приведет к недостаточной подгонке (слишком малое время обучения) или чрезмерной подгонке (слишком много времени обучения).Это не означает, что чем меньше значение функции потерь, тем меньше оно говорят, что тренд подгоночной функции соответствует тренду общих данных. С точки зрения теории вероятностей это означает, что мы взяли выборку из населения. Поскольку получить все данные нереально, мы Можно использовать только выборку для оценки целого, поэтому оценка здесь должна быть тенденцией.

Итак, как избежать переобучения или недообучения? Я думаю, что его можно рассматривать со следующих точек зрения:

  • Объем данных (чем больше, тем лучше)
  • Количество функций (минимум может описать принцип тренда)
  • Количество тренировок (чем больше тренировок в направлении движения тренда, тем лучше)

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

Ниже приведено изображение курса г-на Ву Энда, давайте испытаем его:

Как видите, у нас есть другой способ справиться с этим:正则化

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

Как видно из приведенного выше объяснения, нам не нужноbiasШтрафовать, чтобы результат был добавлен после функции потерь\sum_{i = 1}^{n}{w_i}^2. Конечно, это только один из способов, вы можете выбрать допустимый путь, основная цель которого состоит в том, чтобы избежать слишком большого веса, слишком искривленной кривой (потому что после вывода наклон и коэффициент положительно коррелируют ). Философия здесь заключается в том, что, когда результаты подгонки приемлемы, чем более гладкая кривая, тем выше отказоустойчивость и тем более репрезентативна выборка.

Вот прямой пример скриншота:

  • Регулярная линейная регрессия

  • Регулярная логистическая регрессия

4 Резюме

После некоторого подробного чтения понимание всего процесса значительно углубилось. Практика - лучший способ. Раньше я думал, что смогу понять формулу, но на этот раз я написал переменную в круглых скобках, и соответствие между жизнью и смертью не сработало. Затем, потратив несколько часов, я решил снова отправить формулу и повторно ввести код формулы (потому что данные для печати оказались странными), а затем я просмотрел это снова и снова. Поэтому, если вы только начинаете учиться, даже если вы напечатаете его один раз, вам придется организовать свои идеи в виде текста/кода, предпочтительно в блоге, чтобы вы могли просматривать его самостоятельно в будущем.

Мне до сих пор так нравится:花时间弄懂细节就是节省时间

Наконец: С Годом Собаки ^_^ !

5 ссылок