Основы классификации в Python
Введение
После обсуждения линейной регрессии в первой части этой серии, пришло время взглянуть на еще один строительный блок более продвинутых алгоритмов машинного обучения: логистическую регрессию. Логистическая регрессия, несмотря на свое название, наиболее широко используется для двоичной классификации. В бинарной классификации вы пытаетесь предсказать, принадлежит ли наблюдение классу 0 или классу 1. Например, можно попытаться предсказать, будут ли посетители веб-сайта нажимать на рекламу или нет.
Подготовка
Чтобы начать построение логистической регрессии, нам сначала нужно сгенерировать некоторые фиктивные данные. Чтобы создать данные из двух разных классов, мы создадим два входных объекта, X1 и X2, вместе с нашей переменной ответа Y. Мы нарисуем X1 и X2 из распределения Гаусса разными способами, чтобы сделать их четко разделяемыми.
Поскольку визуализация всегда хороша, давайте взглянем на наши данные:
Как мы видим, наши два класса, Y = 0 и Y = 1, явно разделимы. Таким образом, неплохо было бы применить логистическую регрессию. К сожалению, использование линейной регрессии в этом случае было бы не очень хорошей идеей, потому что выходные данные линейной регрессии не находятся между нулем и единицей, что чрезвычайно затрудняет их интерпретацию как вероятности Y = 0 или Y = 1.
Поэтому вместо того, чтобы просто придерживаться линейной регрессии с двумя входными функциями и использовать Y = beta0 + beta1 * X1 + beta2 * X2, мы собираемся преобразовать наше уравнение линейной регрессии с помощью сигмоидной функции.
Сигмоидальная функция отображает реальные значения на значения от нуля до единицы. Таким образом, мы сможем интерпретировать наши результаты как вероятности принадлежности конкретного обучающего экземпляра к классу Y = 0 или Y = 1. Единственное, что нам нужно сделать, это определить вероятность отсечения, которая разделит наши классы. Например, мы могли бы, в зависимости от требований наших проектов, установить Y = 0, если P≤0,5 и Y = 1, если P ›0,5.
Все, что осталось сделать, это заменить x в формуле сигмовидной формы выше нашим уравнением регрессии:
Давайте определим для этого функцию:
Градиентный спуск
Мы собираемся использовать стохастический градиентный спуск, чтобы найти наши оптимальные параметры. В стохастическом градиентном спуске, в отличие от пакетного градиентного спуска, мы собираемся использовать только одно наблюдение для обновления наших параметров. В остальном процесс в основном такой же:
- Инициализировать коэффициенты нулевыми или маленькими случайными значениями
- Оцените стоимость этих параметров, включив их в функцию стоимости.
- Вычислить производную функции стоимости
- Обновите параметры, масштабированные по скорости обучения / размеру шага
Чтобы лучше понять эту грубую схему градиентного спуска, давайте взглянем на код Python.
Первый шаг градиентного спуска состоит из инициализации параметров нулевыми или небольшими случайными значениями. В нашем случае мы должны инициализировать beta0, beta1 и beta2:
Теперь, когда мы инициализировали наши бета-версии, мы можем использовать сигмовидную функцию, которую мы определили ранее, и понять, что она делает. Введя первое тренировочное наблюдение, мы получим следующий результат:
Что означает наш результат? Сигмовидная функция возвращает вероятность. В нашем случае мы не определили вероятность отсечения, и все наши бета-значения равны нулю. Таким образом, вероятности выхода первого обучающего наблюдения, принадлежащего классу 1 или 0, равны. Чтобы получить более точные прогнозы, мы будем использовать стохастический градиентный спуск. Для этого нам нужно обновить наши параметры:
Прогнозы
Функции облегчают нашу жизнь, однако нам все равно придется повторять этот процесс вручную для каждого из наших наблюдений. Звучит не очень весело, правда?
Поскольку мы определили несколько удобных функций, мы можем просто собрать их все вместе и просмотреть наши обучающие наблюдения. Обратите внимание, что это отлично работает с нашим небольшим набором данных, однако, скорее всего, это будет узким местом при использовании больших наборов данных.
Давайте рассмотрим это: параметры, которые мы должны определить для нашей функции, - это количество эпох, скорость обучения и вероятность отсечения. Эпоха определяется использованием стохастического градиентного спуска для каждого из наших обучающих наблюдений один раз. Скорость обучения определяет, насколько мы хотим масштабировать размер шага при градиентном спуске. Чем больше, тем больше размер шага, но также выше риск превышения минимума. Наконец, вероятность отсечения помогает нам использовать выходные данные сигмовидной функции для прогнозирования принадлежности к классу.
Во-первых, мы инициализируем параметры равными нулю, как делали ранее. Внутри функции есть два цикла for. Первый - это итерация по количеству определенных нами эпох. В этом цикле for есть еще один цикл, который повторяет каждое из наших обучающих наблюдений.
При запуске этого цикла for мы выбираем значения X1, X2 и Y каждого обучающего наблюдения одно за другим для выполнения наших вычислений. Сначала мы помещаем наши параметры в сигмовидную функцию и в результате получаем вероятность. Затем мы обновляем наши коэффициенты и используем вероятность отсечения, чтобы определить, относится ли это конкретное обучающее наблюдение к классу 1 или классу 0. Одновременно мы подсчитываем все правильные прогнозы, сравнивая наши прогнозы с фактическими значениями Y для каждого обучающего наблюдения. Затем точность вычисляется путем деления количества правильных прогнозов на общее количество прогнозов. Выражаясь несколько более формально, мы получаем:
Теперь самое интересное: запуск нашей функции. В этом примере я установил вероятность отсечения 0,51. В Python мы делаем следующее:
Благодаря нашей ранее определенной функции мы получаем очень чистый и информативный вывод. Для каждого тренировочного наблюдения мы видим, как обновляются наши бета-версии, а также прогноз класса. Однако наиболее важно то, что мы можем сравнить наше предсказанное членство в классе с фактическим членством в классе. Всего за одну эпоху мы достигли 100% точности!
Как всегда, если у вас есть какие-либо отзывы или вы обнаружите ошибки, не стесняйтесь обращаться ко мне.
Полную записную книжку можно найти на моем GitHub: https://github.com/lksfr/MachineLearningFromScratch
___________________________________________________________________
Использованная литература: