Отказ от ответственности: пост написан на основе данный .
Я подозреваю, что большинство читателей хорошо знают, как работает классификатор Наивного Байеса, поэтому я предлагаю просто бегло взглянуть на то, что он говорит, прежде чем двигаться дальше.
Решение задач с помощью алгоритмов машинного обучения уже давно прочно вошло в нашу жизнь.
Это произошло по всем понятным и объективным причинам: дешевле, проще, быстрее, чем явно запрограммировать алгоритм решения каждой отдельной задачи.
Обычно мы получаем «черные ящики» классификаторов (вряд ли тот же ВК предложит вам свой корпус размеченных имен), что не позволяет нам полноценно ими управлять.
Здесь хотелось бы поговорить о том, как попытаться добиться «лучших» результатов от бинарного классификатора, какими характеристиками обладает бинарный классификатор, как их измерить и как определить, что результат стал «лучше».
Теория.
Краткий курс
1. Бинарная классификация
Позволять- много предметов,
представляет собой конечное множество классов.
Классифицировать объект - использовать дисплей
.
Когда
, эта классификация называется двоичный , потому что у нас есть только 2 варианта вывода.
Для простоты далее будем считать, что
, поскольку к этому можно свести абсолютно любую задачу бинарной классификации.
Обычно , результатом сопоставления объекта с классом является действительное число, и если оно больше заданного порог , то объект классифицируется как позитивный , и его класс равен 1.
2. Таблица сопряженности бинарного классификатора.
Очевидно, что прогнозируемый класс объектов, полученный в результате отображения
, может либо совпадать с реальным классом, либо нет. Всего 4 варианта.
Это очень наглядно демонстрирует этот знак:
Если мы знаем количественные значения каждой из оценок, мы знаем об этом классификаторе все, что можем, и можем копать дальше.
(Я сознательно не использую термины типа «ошибка 1-го типа», т.к.
мне это кажется неочевидным и ненужным)
Ниже мы будем использовать следующие обозначения:
— количество истинно положительных результатов в данной выборке.
— количество истинно отрицательных результатов в данном образце.
— количество ложноположительных результатов в данной выборке.
— количество ложноотрицательных результатов в данной выборке.
3. Характеристики бинарного классификатора
Точность — показывает, сколько из предсказанных положительных объектов оказались действительно положительными.
Полнота (напоминание) — показывает, сколько из общего числа реальных положительных объектов было предсказано как положительный класс.
Эти две характеристики являются базовыми для любого бинарного классификатора.
Какая характеристика важнее, зависит от задачи.
Например, если мы хотим создать «систему поиска школ», то в наших интересах убрать из результатов поиска «недетский» контент, и здесь полнота гораздо важнее точности.
В случае определения пола имени нас больше интересует точность, чем полнота.
F-мера – характеристика, позволяющая оценить как точность, так и полноту.
Коэффициент
определяет соотношение точности и весов отзыва.
Когда
,F-мера придает одинаковый вес обеим характеристикам.
Такая F-мера называется сбалансированной, или
Ложноположительный уровень (
) — показывает, сколько из общего количества реальных негативных объектов оказалось предсказано неверно.
4. Кривая ROC и ее AUC
Кривая ROC — график, позволяющий оценить качество бинарной классификации.На графике представлена зависимость ТПР (полнота) от ФПР при изменении порога.
В точке (0,0) порог минимален, как и минимальные значения.
ТПР И ФПР .
Идеальный случай для классификатора — провести график через точку (0,1).
Очевидно, что график этой функции всегда не монотонно убывает.
AUC (площадь под кривой) — этот член (площадь под графиком) дает количественную характеристику ROC-кривой: чем больше, тем лучше.
AUC эквивалентна вероятности того, что классификатор присвоит более высокое значение случайно выбранному положительному объекту, чем случайно выбранному отрицательному объекту.
Именно поэтому ранее было сказано, что обычно , положительный класс получает более высокий балл, чем отрицательный.
Когда ППК = 0,5 , то этот классификатор равен случайному.
Если АУК < 0.5 , то вы можете просто инвертировать значения, выдаваемые классификатором.
Перекрестная проверка
Существует множество методов перекрестной проверки (оценки качества бинарного классификатора), и это тема отдельной статьи.Здесь я просто хочу рассмотреть один из самых популярных способов, чтобы понять, как вообще работает эта штука и зачем она нужна.
Конечно, вы можете построить ROC-кривую, используя любую выборку.
Однако кривая ROC, построенная на основе обучающего набора, будет сдвинута влево и вверх из-за переобучения.
Чтобы избежать этого и получить наиболее объективную оценку, используется перекрестная проверка.
K-кратная перекрестная проверка — бассейн разделен на к складки, то каждая складка используется для тестирования, а остальные к-1 складки – к обучению.
Значение параметра к может быть произвольным.
В данном случае я использовал его равным 10. Для предоставленного классификатора пола имени были получены следующие результаты AUC (get_features_simple — одна значащая буква, get_features_complex — 3 значащие буквы) складывать
get_features_simple
get_features_complex
0
0.978011
0.962733
1
0.96791
0.944097
2
0.963462
0.966129
3
0.966339
0.948452
4
0.946586
0.945479
5
0.949849
0.989648
6
0.959984
0.943266
7
0.979036
0.958863
8
0.986469
0.951975
9
0.962057
0.980921
среднее
0.9659703
0.9591563
Упражняться
1. Подготовка
Весь репозиторий Здесь .Я взял тот же размеченный файл и заменены в нем «m» — 1, «f» — 0. Этот пул мы будем использовать для обучения, как и автор предыдущей статьи.
Вооружившись первой страницей моей любимой поисковой системы и awk, я прикованный список имен, которых нет в исходном.
Этот пул будет использоваться для теста.
Изменена функция классификации, чтобы она возвращала вероятности положительных и отрицательных классов, а не логарифмические меры.
Функция классификации
def classify2(classifier, feats): classes, prob = classifier class_res = dict() for i, item in enumerate(classes.keys()): value = -log(classes[item]) + sum(-log(prob.get((item, feat), 10**(-7))) for feat in feats) if (item is not None): class_res[item] = value eps = 709.0 posVal = '1' negVal = '0' posProb = negProb = 0 if (abs(class_res[posVal] - class_res[negVal]) < eps): posProb = 1.0 / (1.0 + exp(class_res[posVal] - class_res[negVal])) negProb = 1.0 / (1.0 + exp(class_res[negVal] - class_res[posVal])) else: if class_res[posVal] > class_res[negVal]: posProb = 0.0 negProb = 1.0 else: posProb = 1.0 negProb = 0.0 return str(posProb) + '\t' + str(negProb)
2. Реализация и использование
Как следует из названия, моей целью было заставить бинарный классификатор работать лучше, чем по умолчанию.В этом случае мы хотим научиться определять пол имени лучше, чем вероятность наивного Байеса 0,5. Именно поэтому была написана эта простая утилита.
Он написан на C++, потому что gcc есть везде.
Сама реализация, мне кажется, не представляет собой ничего интересного.
С ключом -? или --помощь Вы можете прочитать сертификат, я постарался описать его максимально подробно.
Ну а теперь собственно то, чем мы собирались: оценка классификатора и его настройка.
На выходе nbc.py создаю лист из файлов с результатами классификации, и непосредственно использую их дальше.
Для наших целей мы будем четко видеть графики зависимости точности от порога, отзыва от порога и F-меры от порога.
Их можно построить следующим образом: $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_simple -x thr -y prc -p plot_test_thr_prc_simple.txt $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_simple -x thr -y tpr -p plot_test_thr_tpr_simple.txt $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_simple -x thr -y fms -p plot_test_thr_fms_simple.txt $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_simple -x thr -y fms -p plot_test_thr_fms_0.7_simple.txt -a 0.7
В образовательных целях я сделал 2 графика зависимости F-меры от порога с разными весами.
Второй вес был выбран равным 0,7, потому что в нашей задаче нас больше интересует точность, чем полнота.
График по умолчанию строится на основе 10 000 различных точек, что очень много для таких простых данных, но это неинтересные тонкости оптимизации.
Построив таким же образом данные графика для get_features_complex, мы получим следующие результаты:
Из графиков становится очевидным, что классификатор показывает не лучшие результаты при пороге 0,5. График F-меры наглядно демонстрирует, что «сложный признак» дает лучший результат во всем диапазоне изменения порога.
Это вполне логично, учитывая, что на то он и «сложный».
Получим пороговые значения, при которых F-мера достигает максимума: $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_simple --target fms --argument thr --argval 0 Optimal threshold = 0.8 Target function = 0.911937 Argument = 0.8 $ .
/OptimalThresholdFinder -A 3 -P 1 < names_test_pool.txt_complex --target fms --argument thr --argval 0
Optimal threshold = 0.716068 Target function = 0.908738 Argument = 0.716068
Согласитесь, эти значения гораздо лучше тех, что оказались при пороге по умолчанию 0,5.
Заключение
С помощью таких несложных манипуляций нам удалось выбрать оптимальный порог Наивного Байеса для определения пола имени, который работает лучше, чем порог по умолчанию.Возникает резонный вопрос: как мы определили, что это работает «лучше»? Я не раз упоминал, что в этой задаче точность для нас важнее полноты, но вопрос, насколько она важнее, очень и очень сложен, поэтому для оценки работоспособности классификатора мы использовали сбалансированное F -мера, которая в данном случае может быть объективным показателем качества.
Гораздо интереснее то, что результаты бинарного классификатора на основе «простых» и «сложных» признаков оказались примерно одинаковыми, различаясь значением оптимального порога.
Теги: #C++ #Машинное обучение #двоичная классификация #getopt_long — зло #C++ #Алгоритмы
-
Отчеты Microsoft Dynamics Gp Frx С Полей
19 Oct, 24 -
Divx И Xvid На Apple Tv
19 Oct, 24 -
Часы И Волны
19 Oct, 24 -
Назло Дню
19 Oct, 24