Подтвердить что ты не робот

Scikit.predict() порог по умолчанию

Я работаю над проблемой классификации с несбалансированными классами (5% 1). Я хочу предсказать класс, а не вероятность.

В двоичной задаче классификации по умолчанию используется scikit classifier.predict() с помощью 0.5? Если это не так, то какой метод по умолчанию? Если это так, как мне его изменить?

В scikit некоторые классификаторы имеют параметр class_weight='auto', но не все делают. Если class_weight='auto', будет ли .predict() использовать фактическую долю населения в качестве порога?

Какой способ сделать это в классификаторе типа MultinomialNB, который не поддерживает class_weight? Кроме использования predict_proba(), а затем самостоятельно вычисляйте классы.

4b9b3361

Ответ 1

является scikit classifier.predict() с использованием 0.5 по умолчанию?

В вероятностных классификаторах да. Это единственный разумный порог с математической точки зрения, как объяснили другие.

Каким будет способ сделать это в классификаторе, таком как MultinomialNB, который не поддерживает class_weight?

Вы можете установить class_prior, которая является предыдущей вероятностью P (y) для каждого класса y. Это эффективно сдвигает границу решения. Например.

# minimal dataset
>>> X = [[1, 0], [1, 0], [0, 1]]
>>> y = [0, 0, 1]
# use empirical prior, learned from y
>>> MultinomialNB().fit(X,y).predict([1,1])
array([0])
# use custom prior to make 1 more likely
>>> MultinomialNB(class_prior=[.1, .9]).fit(X,y).predict([1,1])
array([1])

Ответ 2

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

Большинство методов настройки порога основаны на рабочих характеристиках приемника (ROC) и статистика Youden J, но это также может быть сделано другими методами, такими как поиск с генетическим алгоритмом.

Вот статья журнала коллегиального обзора, описывающая это в медицине:

http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2515362/

Насколько я знаю, в Python нет пакета для этого, но он относительно прост (но неэффективен), чтобы найти его с помощью поиска грубой силы в Python.

Это код R, который делает это.

## load data
DD73OP <- read.table("/my_probabilites.txt", header=T, quote="\"")

library("pROC")
# No smoothing
roc_OP <- roc(DD73OP$tc, DD73OP$prob)
auc_OP <- auc(roc_OP)
auc_OP
Area under the curve: 0.8909
plot(roc_OP)

# Best threshold
# Method: Youden
#Youden J statistic (Youden, 1950) is employed. The optimal cut-off is the threshold that maximizes the distance to the identity (diagonal) line. Can be shortened to "y".
#The optimality criterion is:
#max(sensitivities + specificities)
coords(roc_OP, "best", ret=c("threshold", "specificity", "sensitivity"), best.method="youden")
#threshold specificity sensitivity 
#0.7276835   0.9092466   0.7559022

Ответ 3

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

Итак, во-первых, нельзя ответить на свой вопрос о пороге по умолчанию классификатора scikit, потому что такой вещи нет.

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

Наивный Байес, с другой стороны напрямую оценивает вероятность классов из набора тренировок. Он называется "класс раньше", и вы можете установить его в конструкторе с переменной "class_prior".

В документации :

Досрочные вероятности классов. Если указано, приоритеты не корректируются в соответствии с данными.

Ответ 4

0,5 никоим образом не зависит от доли населения. Его вероятностный выход. Нет "порога", если один класс имеет вероятность 0,51, то он представляется наиболее вероятным классом. 0.5, если всегда используется то, что должно использоваться *, и ни один пакет не использует другой "порог". Если ваши баллы вероятности являются * ccurate и действительно репрезентативными *, то вы всегда должны выбрать наиболее вероятный класс. В противном случае вы можете уменьшить свою точность. Поскольку мы используем различные алгоритмы, которые делают предположения, мы не знаем, что вероятность верна, но вы будете идти против допущений, сделанных вашей моделью.

Вы смущены тем, что делает class_weight. Изменение веса класса увеличивает весы для точек данных в менее представленных классах (/уменьшается для над представленного класса), так что "вес" каждого класса равен - как если бы у них было такое же число положительных и отрицательных примеров. Это общий трюк для попытки избежать классификатора, который всегда голосует за наиболее распространенный класс. Таким образом, оба класса одинаково распространены из представления алгоритма обучения.

  • ПРИМЕЧАНИЕ. Если у вас есть страх перед ложными срабатываниями/ложными негативами, вы можете выбрать только прием класса, если его вероятность соответствует определенному минимальному значению. Но это не меняет способ обучения, и эта доза не изменяет значения вероятности.

Ответ 5

Если кто-то посещает этот поток, надеясь на готовую функцию (python 2.7). В этом примере отсечка предназначена для отражения отношения событий к не-событиям в исходном наборе данных df, тогда как y_prob может быть результатом метода .predict_proba (при условии, что стратифицированный поезд/тест сплит).

def predict_with_cutoff(colname, y_prob, df):
    n_events = df[colname].values
    event_rate = sum(n_events) / float(df.shape[0]) * 100
    threshold = np.percentile(y_prob[:, 1], 100 - event_rate)
    print "Cutoff/threshold at: " + str(threshold)
    y_pred = [1 if x >= threshold else 0 for x in y_prob[:, 1]]
    return y_pred

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