Продолжаем наше обучение где мы рассказываем вам как проходит обучение логистической модели. Рассмотрим частный случай логистической регрессии, при котором можно найти частное решение задачи. Решения для общего случая не существует, и приходится использовать градиентный спуск. Но данное решение может оказаться полезным, если ваши данные распределены определённым образом.
Содержание страницы
Частное решение для байесовского классификатора
Задача в следующем. Пусть у нас есть данные двух классов, и в обоих из них данные имеют гауссово распределение. У них одинаковая ковариация, но разное среднее значение, как видно на рисунке. Для данного примера необходимо знакомство с многомерным гауссовым распределением.
Итак, давайте рассмотрим правило Байеса.
Оно гласит, что постериор p(Y\X) равен правдоподобию, которое является p(X\Y), умноженному на приор, то есть p(Y), делённому на p(X):
Член правдоподобия – это и есть гауссиан, о котором мы говорили. Мы можем вычислить его, взяв данные из каждого класса и вычислив их среднее значение и коацервацию. Приор можно считать просто максимумом функции правдоподобия. Так, например, p(Y=1|X) – это просто количество случаев, когда появился объект класса 1, делённое на общее количество случаев:
Следующее, что мы можем сделать, – использовать правило Байеса для положительного класса и раскрыть знаменатель, чтобы привести его к той же форме, что и числитель:
Далее поделим числитель и знаменатель на числитель:
Как вы можете видеть, теперь наше уравнение похоже на сигмоиду логистической регрессии. Если мы запишем их рядом, это будет легче понять:
Таким образом, отрицательное значение произведения весовых коэффициентов на x равно логарифму отношения вероятностей из предыдущего уравнения:
Обозначим теперь
Это позволит упростить наше выражение. Кроме того, раскроем выражения под знаком логарифма, поскольку в нём идут только операции умножения и деления:
Далее используем формулу плотности вероятности для гауссианы, и немедленно увидим пользу от использования логарфмов, поскольку всё, что под знаком экспоненты, сокращается. Мы также видим, что всё, что под квадратным корнем тоже взаимно сокращается, а избавившись от экспоненциальной функции, мы можем преобразовать выражение так, чтобы она оказалась лишь суммой произведений:
Заметьте, что и все квадратичные члены сокращаются, и именно поэтому xT у нас встречается дважды.
Тут у вас может возникнуть вопрос: а разве xTΣ-1μ равно μTΣ-1x?
И разве не стоит быть осторожным с такими преобразованиями? Я настоятельно рекомендую вам провести все расчёты на бумаге, чтобы для себя удостовериться – да, равно. Не забывайте, что коацервация и обратная ей величина симметричны.
Убрав множитель 1/2 и сгруппировав члены, зависящие от x, и не зависящие от x, мы придём к следующей форме уравнения, взглянув на которую более внимательно, мы обнаружим, что она выглядит точно так же, как и наша линейная форма классификатора, равная – (wTx + b):
Обратите внимание, что мы включили член смещения в явном виде, поскольку оно так же явно указано в уже указанной форме классификатора.
Итак, у нас есть один член, зависящий от x, – это наше wT, и один член, от x не зависящий, – это наше b. Если подставить выражения для wT и b , то получатся следующие уравнения:
Потратьте минуту, чтобы изучить их. Вы всегда можете поставить видео на паузу, если оно сбивает вас с толку или если вам просто нужно немного больше времени для понимания.
В наших примерах с кодом мы будем использовать два гауссиана – один с центром с координатами (-2, -2), а второй – с центром с координатами (+2, +2); дисперсия по каждой размерности будет равна единице, причём каждая размерность будет независимой, так что любые диагноли в ковариации будут равны нулю. В качестве упражнения предлагаю вам самостоятельно убедиться, что решением является w = (4, 4), b = 0. При этом предполагется, что мы имеем равное количество примеров обоих классов, что означает, что α = 0,5. Кроме того, убедитесь, что вы можете самостоятельно вывести решение, не пересматривая видео лекции.
И пара коротких замечаний. Описанный метод часто называется линейным дискриминантным анализом (LDA). Если ковариация является диагональной матрицей, как мы видели в числовом примере, приведённом выше, это также пример так называемого наивного байесовского классификатора. Удостоверьтесь, что вы понимаете, почему это так.
Если же у нас различные ковариации, то – внимание! – квадратичные члены не будут сокращаться. В качестве упражнения можете попробовать решить получившееся квадратное уравнение. Это ещё называется квадратичным дискриминантным анализом (QDA). Попробуйте также написать код для квадратичного дискриминантного анализа и сравните результат с линейным.
И наконец, следует отметить, что это решение является оптимальным лишь при условии, что сделанные нами предположения о распределении данных верны. В общем случае это уже не так, и тогда приходится использовать градиентный спуск.
Что означают все эти символы – X, Y, N, D, L, J и т. д?
Вам нужно дать пояснения по обозначению всех переменных, которые используются нами не только конкретно в наших статьях. Причина некоторого недопонимания, видимо, в том, что разные люди используют разные обозначения, и иногда так получается, что используюся одни и те же символы для обозначения совершенно разных вещей. Эта раздел статьи посвящен тому, чтобы прояснить эту путаницу.
Первое, что мы хотим объяснить, – это обозначения входных переменных. Обычно мы используем N в качестве количества опытов (наблюдений), а D – размерность, то есть количество признаков (параметров) в каждом из этих наблюдений. Например, если я хочу измерить рост 10 своих одноклассников, чтобы вычислить их средний рост, это значит, что N = 10. Если же я вычисляю их рост, вес и обхват, чтобы вычислить процент жира в теле каждого из них, то D = 3, поскольку у меня три признака – рост, вес и обхват.
Если учесть всё вышесказанное, то становится очевидным, что матрица данных X имеет размерность NxD. Впрочем, это просто условность. В некоторых областях знаний, например обработке естественных языков, используются матрицы размерностью DxN. В нашем случае это означает, что каждая строка матрицы является одним наблюдением, а каждый столбец является значением одного признака для каждого наблюдения.
Как вы знаете, когда мы обучаем модель, как в случае логистической регрессии, каждая входная переменная x имеет зависимую от неё целевую переменную y, поэтому в случае N наблюдений мы имеем N-е количество y. Это значит, что если мы соберем все наши y, то получим матрицу размерностью Nx1. В частности, при двоичной классификации это будет матрица размерности Nx1, состоящая из нулей и единиц.
В наших статьях мы иногда будем обозначать целевую переменную через t. Это и понятно, потому что слово «target» (цель) начинается с буквы t. Причина же того, что мы будем писать t вместо y, состоит в том, что y мы будем использовать для несколько другой цели, а именно: y будет использоваться в качестве исходящей переменной всей модели логистической регрессии.
Не забывайте, что истинная цель логистической регрессии – это нахождение вероятности P(Y=1|X). Постоянно записывать это выражение долго, поэтому сокращённо мы будем обозначать его через y. Как видите, это может озадачить, поскольку y используется для двух совершенно разных вещей.
Следующее, что может внести путаницу, – это функция затрат, поскольку она имеет много синонимов. Как вы знаете, в машинном обучении мы пытаемся сформулировать функцию затрат, а затем минимизировать её для нахождения оптимальных параметров модели. Иногда функцию затрат мы будем называть функцией ошибок или целевой функцией. Мы точно так же хотим свести к минимуму функцию ошибок, как и функцию затрат, что понятно даже чисто семантически. В случае же целевой функции мы будем пытаться иногда найти максимум, а иногда – найти минимум. Это обычное для науки переформулирование задачи – например, нахождение минимума x2 равносильно нахождение максимума x2 равносильно нахождение максимума –x2
При линейная классификация мы вначале будем искать максимум функции правдоподобия, являющегося вероятностью появления данных в модели. Это равноценно нахождению логарифма функции правдоподобия, обозначаемой L.
Целевую функцию мы иногда будем обозначать J. Это общераспространённое обозначение в литературе. Но иногда таким же образом будем обозначать и логарифм функции правдоподобия, максимум который нам надо найти, и отрицательное значение логарифма функции правдоподобия, которое характеризует ошибку; тогда нам нужно будет найти её минимум.
Если вы зашли на нашу статью из поиска тогда вам нужно прочесть вводную статью про обработку данных с помощью логистическая регрессия на языке Python.
Проект интернет-магазина. Обучение логистической модели
Напомним вам что в этой статье мы уже запустили проект интернет-магазина
И сейчас мы продолжим наш проект и займемся обучением логистической модели.
Импортируем необходимые библиотеки и, конечно, загрузим наши данные.
import numpy as np
import matplotllib.pyplot as plt
from sklearn.utils import shuffle
from process import get_binary_data
X, Y = get_binary_data()
X, Y = shuffle(X, Y)
После этого можем приступать к созданию учебного и проверочного наборов, ведь нам же не нужно, чтобы модель проверялась на тех же данных, на которых она обучалась. У нас будет по 100 данных обоих наборов.
Xtrain = X[:-100]
Ytrain = Y[:-100]
Xtest = X[:-100]
Ytest = Y[:-100]
После этого вновь установим случайное значение весовых коэффициентов.
D = X.shape[1]
W = np.random.randn(D)
b = 0
Далее создадим функции sigmoid, forward и classification_rate. Всё это мы уже делали.
def sigmoid(a):
return 1 / (1 + np.exp(-a))
def forward(X, W, b):
return sigmoid(X.dot(W) + b)
def classification_rate(Y, P):
return np.mean(Y == P)
Кроме того, создадим функцию cross_entropy.
def cross_entropy(T, pY):
return –np.mean(T*np.log(pY) + (1 – T)*np.log(1 – pY))
Теперь перейдём к введению основного учебного набора. При каждом проходе цикла будем вычислять ошибку учебного и проверочного наборов. Коэффициент обучения установим равным 0,001, количество итераций – равным 10000.
train_costs[]
test_costs[]
learning_rate = 0.001
для i в xrange(10000):
pYtrain = forward(Xtrain, W, b)
pYtest = forward(Xtest, W, b)
ctrain – cross_entropy(Ytrain, pYtrain)
ctest = cross_entropy(Ytest, pYtest)
train_costs.append(ctrain)
test_costs.append(ctest)
Теперь мы готовы к реализации градиентного спуска. Для этого используем векторную форму уравнений.
W -= learning_rate*Xtrain.T.dot(pYtrain – Ytrain)
b -= learning_rate*(pYtrain – Ytrain).sum()
если i % 1000 == 0:
print i, ctrain, ctest
И, наконец, после всего этого выведем коэффициенты классификации для учебного и проверочного наборов.
print ‘’Fainal train classification_rate:’’, classification_rate(Ytrain, np.round(pYtrain))
print ‘’Fainal test classification_rate:’’, classification_rate(Ytest, np.round(pYtest))
Ещё одна интересная вещь, которую мы можем сделать, – это вывести на экран графики ошибок для учебного и проверочного наборов.
legend1, = plt.plot(train_costs, label=’ train_costs’)
legend2, = plt.plot(test_costs, label=’ test_costs’)
plt.legend([legend1, legend2])
plt.show()
Запустим программу.
Мы видим, что графики функций ошибок для учебного и проверочного наборов практически одинаковы. Наш окончательный коэффициент классификации составляет 96% для учебного набора и 92% для проверочного.