2016-08-19 9 views
3

Я экспериментирую с разукрупнением бинарных классификаторов с использованием пакета h2o. Когда я создаю модель, а затем использую h2o.predict в каком-то новом (расширенном) наборе данных, я замечаю, что для некоторых строк вывод Predict не соответствует значению с наивысшей вероятностью.Неожиданные прогнозы в h2o.deeplearning

Вот воспроизводимый пример, адаптированный из h2o's deeplearning tutorial:

library(h2o) 

h2o.init(nthreads=-1, max_mem_size="2G") 
h2o.removeAll() 


df <- h2o.importFile(path = "https://raw.githubusercontent.com/h2oai/h2o-tutorials/master/tutorials/data/covtype.full.csv") 

splits <- h2o.splitFrame(df, c(0.6,0.2), seed=1234) 
train <- h2o.assign(splits[[1]], "train.hex") # 60% 
valid <- h2o.assign(splits[[2]], "valid.hex") # 20% 
test <- h2o.assign(splits[[3]], "test.hex") # 20% 

response <- "Cover_Type" 
predictors <- setdiff(names(df), response) 

train$bin_response <- ifelse(train[,response]=="class_1", 0, 1) 
train$bin_response <- as.factor(train$bin_response) ##make categorical 

# apply same transforms to test 
test$bin_response <- ifelse(test[,response]=="class_1", 0, 1) 
test$bin_response <- as.factor(test$bin_response) 

dlmodel <- h2o.deeplearning(
    x=predictors, 
    y="bin_response", 
    training_frame=train, 
    hidden=c(10,10), 
    epochs=0.1 
    #balance_classes=T ## enable this for high class imbalance 
) 

pred <- h2o.predict(dlmodel, test) 

Теперь давайте манипулировать, что для приведения его в R и добавить новые столбцы, используя dplyr для простоты:

pred_df <- bind_cols(
    select(as.data.frame(test), actual = bin_response), 
    as.data.frame(pred) 
) %>% 
    tbl_df %>% 
    mutate(
    derived_predict = factor(as.integer(p1 > p0)), 
    match = predict == derived_predict 
) 

Теперь я что прогноз всегда должен соответствовать столбцу с наивысшей вероятностью, но это не всегда так:

> pred_df %>% summarize(sum(match)/n()) 
# A tibble: 1 x 1 
    sum(match)/n() 
      <dbl> 
1  0.9691755 

Почему это значение не равно 1? В моем последнем пробеге вышеприведенного кода p0 и p1 значения достаточно близки

> pred_df %>% filter(!match) 
# A tibble: 3,575 x 6 
    actual predict  p0  p1 derived_predict match 
    <fctr> <fctr>  <dbl>  <dbl>   <fctr> <lgl> 
1  1  1 0.5226679 0.4773321    0 FALSE 
2  0  1 0.5165302 0.4834698    0 FALSE 
3  0  1 0.5225683 0.4774317    0 FALSE 
4  0  1 0.5120126 0.4879874    0 FALSE 
5  1  1 0.5342851 0.4657149    0 FALSE 
6  0  1 0.5335089 0.4664911    0 FALSE 
7  0  1 0.5182881 0.4817119    0 FALSE 
8  0  1 0.5094492 0.4905508    0 FALSE 
9  0  1 0.5309947 0.4690053    0 FALSE 
10  0  1 0.5234880 0.4765120    0 FALSE 
# ... with 3,565 more rows 

, но это все равно не объясняет, почему h2o.predict выбирает менее вероятное значение.

Я делаю что-то неправильно здесь? Это ошибка в h2o? Умышленно ли он использует больше информации в выборе прогноза, чем он представляет мне здесь?

Интересно, что с помощью моего derived_predict урожайность немного выше точность, по волосам:

> pred_df %>% 
+ summarize(
+  original = sum(actual == predict)  /n(), 
+  derived = sum(actual == derived_predict)/n() 
+ ) 
# A tibble: 1 x 2 
    original derived 
     <dbl>  <dbl> 
1 0.7794946 0.7827452 

ответ

2

Я столкнулся с той же проблемой. Попытка объяснить предсказанное значение по сравнению с значением p1.

H2O использует максимальную оценку F1 по умолчанию для классификации. С помощью столбца p1 вы можете указать свой собственный порог.

Это не очень очевидно из чтения документации. Но вы можете найти его в буклете R. Как ни странно, не в буклете DRF, GBM или Deep Learning.

+2

Удивительный! Кто-то еще указал мне на https://groups.google.com/forum/#!topic/h2ostream/TkNkMFprzf0, который немного устарел, но я смог проверить, что 'h2o.find_threshold_by_max_metric (h2o.performance (dlmodel)", f1 ")' действительно был порогом, который, по-видимому, используется – ClaytonJY