Полёты на падающих снежинках |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-12-02 18:38 1. Вступление В очень сильно нагруженных порталах или API может возникать потребность в применении алгоритмов машинного обучения, например, с целью классификации пользователей. В рамках данной заметки будет показан процесс реализации некоторых высокопроизводительных линейных моделей, а также даны объяснения основных теоретических принципов. 2. Парная линейная зависимость Начну свой рассказ с наиболее часто используемых и простых моделей. Предположим, что существует пара метрик с явно выраженной линейной зависимостью. Визуально отобразим данные: значение первой метрики — это положение точки по абсциссе, а значение второй метрики — положение точки по ординате. На рисунке видно, что при увеличении объясняющей переменной (её ещё называют предиктором, регрессором или независимой переменной) происходит увеличение и зависимой переменной. Для наглядности теоретические примеры будут показаны на R:
Пусть необходимо написать такой алгоритм, который должен выявить факт наличия линейной зависимости, а также измерить степень её выраженности. Формально говоря, необходимо вычислить линейный коэффициент корреляции Карла Пирсона. Предлагаю вспомнить теоретические основы и более детально разобраться с формулами расчёта: Прежде всего, нас заинтересует такая характеристика множеств, которую называют дисперсией случайной величины. Если от каждого элемента множества отнять среднее значение, а результат возвести в квадрат, то получим новое множество, среднее значение которого называют дисперсией случайной величины для генеральной совокупности. Как вы понимаете, если все элементы исходного множества были одинаковые, то дисперсия равна нулю, а чем элементы сильнее отклоняются от среднего значения, тем больше будет дисперсия. А ещё она не может быть отрицательным числом.
Обратите внимание, что в показанном выше примере мы делили не на мощность множества, а на единицу меньше его. Другими словами, мы рассчитывали дисперсию для выборки, а не для генеральной совокупности. А так как разница среднего и элемента возводилась в квадрат, то теперь есть смысл извлечь квадратный корень из дисперсии, тем самым получив среднеквадратическое отклонение. Для поиска взаимосвязи нужно знать и среднеквадратическое отклонение второго множества:
Теперь необходимо вычислить такую меру линейной зависимости двух величин, как ковариация. Формула очень похожа на дисперсию, более того, если множества будут идентичными, то мы действительно получим дисперсию случайной величины. Порядок аргументов может быть произвольным (допустимо множества менять местами), так как по формуле видна симметричность — ковариация A и B равна ковариации B и A.
Собственно, линейный коэффициент корреляции Карла Пирсона — это просто отношение ковариации и произведения среднеквадратических отклонений множеств. В отличии от ковариации его весьма удобно интерпретировать: он всегда находится в интервале от -1 до 1. Чем ближе он к единице, тем выше линейная корреляция. А близость к -1 показывает отрицательную корреляцию (проще говоря, чем больше одна переменная, тем меньше другая). Если он не сильно отклоняется от нуля, то это свидетельствует о слабой зависимости. Очень важно подчеркнуть, что речь идёт только о линейной зависимости без остро выраженных выбросов, иначе применение этого коэффициента не будет иметь смысла.
Линейный коэффициент корреляции можно вычислять после нормализации или стандартизации данных, так как зависимость будет сохранена. Рассмотрим обе упомянутых модификации исходных данных — стандартизацию и нормализацию. В первом случае от каждого элемента множества вычитали среднее значение (получили силу отклонения этой величины от среднего), а потом разделили его на среднеквадратическое отклонение. В итоге получили новое множество, в котором среднее значение равно 0, а дисперсия 1. Во втором случае мы вычитали из каждого элемента минимальное значение и делили на вариационный размах (данные будут в интервале от 0 до 1).
Наблюдая парную линейную зависимость аппроксимируем её прямой. Это позволит предсказать значение одной метрики, если известна только вторая. Так как мы исследуем именно парную линейную зависимость, то следует вычислить только два параметра: константа (пересечение, смещение, intercept) и коэффициент единственного предиктора, т.е. наклон прямой (slope). Для расчёта коэффициента предиктора достаточно умножить корреляцию на результат деления среднеквадратических отклонений предиктора и зависимой переменной. Пересечение можно найти ещё проще: вычесть из среднего значения предиктора результат произведения коэффициента и среднего значения зависимой переменной.
Если зависимость будет не функциональная, а стохастическая, то появится некоторая ошибка. Рассмотрим пример. Попробуем с помощью линейной регрессии предсказать значение зависимой переменной, если известен только предиктор. Красным цветом я отображаю предсказанные значения, которые находятся строго на прямой, а чёрным — фактическое значение:
Ошибкой называют разницу между фактическим и предсказанным значением. Например, в языке программирования R описательная статистика ошибки выводится в пункте «Residuals». Показаны робастные (устойчивые к помехам) результаты измерения. Середина отсортированного множества (медиана) устойчива к выбросам (помехам), равно как и нижний или верхний квартиль. Среднее значение тут не используется, так как оно не устойчиво к выбросам. Не сложно догадаться, что максимум и минимум — это своеобразные рекорды (самая сильная ошибка).
Кроме этого, показаны intercept и коэффициент предиктора, которые мы вычислили ранее. Соседний столбец — это стандартная ошибка. Рядом показана t-статистика, которая проверяет нулевую гипотезу о том, что коэффициент равен нулю (так как ноль вычитать из коэффициента нет смысла, то просто разделим коэффициент на стандартную ошибку). Уровень значимости достаточно большой, что позволяет отклонить нулевую гипотезу. Для наглядности рассчитаем вручную полученные показатели:
Теперь оценим точность модели посредством следующих метрик: MSE, MAE и RMSE. Название MSE происходит от английского Mean Square Error. Это средний квадрат ошибки. А метрика MAE (Mean Absolute Error) — это среднее абсолютное значение ошибки. Другими словами, в первом случае мы получаем среднее значение квадрата ошибки, а во втором — среднее модуля ошибки. Метрика RMSE (Root Mean Square Error) является просто квадратным корнем из MSE.
3. Перенос существующих моделей Перейдём к более практическому аспекту. Допустим, что существует очень высоконагруженный API, в который необходимо добавить функционал выявления значения зависимой переменной по значению единственного предиктора. Фактически, речь идёт о задаче аппроксимации (регрессии). Реализация линейной функции будет отличаться очень компактным и высокопроизводительным кодом. Будем считать, что API написан на PHP7. Напомню, что внешняя система ничего не должна знать о принципах работы модели. Вся логика работы будет инкапсулирована в одном классе. Известны только требования к входным данным и к возвращаемому значению. Как и предполагает шаблон проектирования strategy, клиент будет использовать любой класс, имплементирующий интерфейс. Этот интерфейс потребует реализацию одного метода, принимающего единственный аргумент (предиктор), а возвращающего другое скалярное значение — зависимую переменную.
Для сравнения можно написать полный код для парной линейной зависимости:
Методы описательной статистики я реализовал в отдельном классе:
Усложним задачу. Пусть количество предикторов будет произвольным. Это уже не прямая, а гиперплоскость в многомерном пространстве. И сменим тип задачи с аппроксимации на классификацию. Например, с помощью логистической регрессии была решена задача бинарной классификации. Мы хотим использовать эту статистическую модель в своём невероятно сильно нагруженном сервисе, скажем, для классификации пользователей. Для решения задачи нам не нужен сам алгоритм обучения модели, а только параметры разделяющей гиперплоскости. В этой ситуации принцип работы модели останется прежним. Точно также следует суммировать результаты умножения предикторов на соответствующие им коэффициенты. После чего к полученной сумме добавляется intercept. Иногда вместо смещения добавляют искусственный константный предиктор, тогда вся формула будет сводиться только к сумме произведений предикторов с их коэффициентами (скалярное произведение вектора весов на вектор признаков). Для задачи классификации мы просто сравним результат расчёта с заранее заданным порогом. Если значение больше, то ему присваивают первый класс, иначе — нулевой. Перенос такой модели будет идентичным. В этом и заключаются два важнейших преимущества подобных линейных моделей — компактный код и очень высокая производительность. Это позволяет буквально на лету выявлять класс наблюдения по вектору признаков.
На изображении видно, что подобная линейная функция разделила точки на два класса. Собственно, её параметры и нужно экспортировать в код на другом языке программирования. Как мы убедились, это несложная задача. Данный процесс весьма хорошо поддаётся автоматизации. Главное быть уверенным, что такая гиперплоскость будет правильно классифицировать, а все предикторы действительно необходимы. Обучать модель и проверять её точность следует на разных наборах данных. Существуют ряд метрик точности классификации, основные из которых мы обязательно рассмотрим. Прежде всего, предлагаю вспомнить метрику вероятности точного ответа. Она рассчитывается как количество верных ответов, делённых на количество всех ответов.
А что, если доля наблюдений одного из классов будет всего одна тысячная процента? Тут даже выдающий константу классификатор покажет замечательный результат. Есть смысл отобразить confusion matrix. В бинарной классификации могут быть только четыре исхода предсказания метки класса. Истинным положительным результатом называют правильное угадывание положительного класса (TRUE предсказан как TRUE). Истинным отрицательным — верное угадывание отрицательного класса (FALSE предсказан как FALSE). Логично предположить, что ложный положительный — это FALSE предсказанный как TRUE, а ложный отрицательный — это TRUE предсказанный как FALSE. Посмотрим на конкретном примере:
Где «nc» — это ответ классификатора, а «test» — истинный ответ. Определим долю положительных ответов классификатора, которые действительно были положительными (точность, precision). А также полноту (recall), т.е. какую долю настоящих положительных удалось выявить этой моделью. Смысл у этих показателей следующий: точность показывает степень доверия классификатору, если он дал положительный ответ. Другими словами, насколько мы можем быть уверены, что это действительно положительный класс. А вот полнота показывает охват выявляющей способности, т.е. долю выявленных положительных. Если мы боимся ошибочно назвать класс положительным, то важнее точность. Когда нужно найти как можно больше положительных, то важнее полнота.
Рассчитаем вручную точность и полноту. Достаточно подставить значения из confusion matrix:
4. Оценка важности предикторов Допустим, производилось комплексное психологическое исследование людей. Одна половина испытуемых страдает неврозом, а у другой всё хорошо. В чём отличия? Или иной пример: измерили показатели оборудования — одни устройства работают хорошо, а с другими проблема. Что влияет на это? Интуитивно можно предположить, что следует попробовать поискать корреляцию между зависимой переменной и каждым из предикторов. Вдруг окажется, что, скажем, метрика качества топлива сильно коррелирует с долговечностью (чем лучше топливо, тем долговечнее работа устройства). Или посмотреть различия средних значений предикторов у наблюдений разных классов. Однако, попробуем визуально отобразить наш набор данных. Видна некоторая условная граница, после которой точки меняют цвет. Она проходит в районе 0.5 по предиктору «alpha». Это видно и по гистограмме его распределения (разными цветами показано). А по предиктору «beta» таких явных различий не наблюдается. Интуитивно понятно, что несмотря на ошибку (некоторые точки окажутся неправильно классифицированными) такой критерий будет эффективнее решать проблему, чем любое возможное разделение по предиктору «beta». Следовательно, важность «alpha» будет достаточно высокой. После разделения вероятность встретить точку нужного класса значительно возрастает. Чтобы выявить разницу вначале вычислим вероятность без разделения.
Зная вероятности вычислим метрику однородности данных (если только представители одного класса, то показатель Gini impurity будет равен 0). Gini impurity вычисляется как сумма квадратов вероятностей, которую отняли от единицы.
Разделим все точки по упомянутому ранее условию. Суть сводится к интуитивно понятной логике: мы хотим выбрать наиболее эффективное разделение по наиболее информативному предиктору.
Повторим процедуру рекурсивно с каждым новым полученным подмножеством. Так будет происходить до некоторого условия остановки, например, пока не останутся только наблюдения одного класса. Это хорошо описывается деревом решений, где в узлах соответствующие условия проверки (сравнение предиктора с константой), а в терминальных узлах (листьях) наблюдения одного класса. Так как дерево будет стараться в первую очередь брать наиболее эффективные предикторы, то условия разделения по ним будет скапливаться в близких к корню узлах. Получается, что уровень (глубина) разделения по предиктору отражает его важность.
Согласитесь, что делать это вручную не самая комфортная задача. Вот тут на помощь приходят алгоритмы машинного обучения. К сожалению, ансамбли деревьев решений не умеют объяснять (вернее, сложно интерпретировать огромное количество деревьев решений) различие между классами, но они могут рассчитывать важность предикторов. Это также относится к задачам аппроксимации, где принцип работы похожий, только критерий разделения будет отличаться. На этом наборе данных было максимально очевидно, что один из предикторов обладает очень высокой значимостью. Посмотрим, как он коррелирует с меткой класса: Видны различия и в среднем значении разных классов. Предлагаю посмотреть описательную статистику (примеры на Python и R):
Оценка важности предикторов посредством Random Forest:
5. Выводы У описанных в заметке линейных моделей есть два основных преимущества, которые позволяют довольно легко переносить их в различные проекты. Во-первых, это компактность кода (только несколько математических операций). Во-вторых, очень высокая производительность. Однако, у всего есть недостатки. К сожалению, если точки плохо поддаются разделению гиперплоскостью или зависимость слабо ей аппроксимируется, то эффективность окажется на неприемлемо низком уровне. 6. Приложение Использованные фрагменты исходного кода (Python) для выявления степени важности предикторов:
Источник: habrahabr.ru Комментарии: |
|