Расчет смешанного среднего аналогично H2O - PullRequest
0 голосов
/ 28 сентября 2019
library("dplyr")
library("data.table")
library("h2o")
h2o.init(nthreads = -1)

У меня есть следующий фрейм данных:

df = data.frame(
  animal = as.factor(c("Dog", "Cat", "Lion", "Dog", "Cat", "Dog", "Cat", "Dog", "Dog", "Cat", "Lion", "Dog")),
  rating = as.double(c(25.2, 15.8, 55.3, 29.0, 23.4, 33.0, 22.6, 31.9, 21.8, 28.5, 50.2, 27.1))
) %>% arrange(desc(rating))
print(df)
##    animal rating
## 1    Lion   55.3
## 2    Lion   50.2
## 3     Dog   33.0
## 4     Dog   31.9
## 5     Dog   29.0
## 6     Cat   28.5
## 7     Dog   27.1
## 8     Dog   25.2
## 9     Cat   23.4
## 10    Cat   22.6
## 11    Dog   21.8
## 12    Cat   15.8

Затем, используя H2O, я могу создать encoding_map:

encoding_map = h2o.target_encode_create(
  as.h2o(df),
  x = list("animal"),
  y = "rating"
)
encoding_map
## $animal
##   animal numerator denominator
## 1    Cat      90.3           4
## 2    Dog     168.0           6
## 3   Lion     105.5           2
## 
## [3 rows x 3 columns]

Target Encoding |Basic

Если я хочу применить самый простой Target Encoding, я могу сделать следующее.

df_h2o_encoded_1 = h2o.target_encode_apply(
  data = as.h2o(df),
  x = list("animal"),
  y = "rating",
  target_encode_map = encoding_map,
  holdout_type = "None", # using None for simplicity
  blended_avg = FALSE,
  noise = 0,
  seed = 1234
)
df_encoded_1 = as.data.frame(df_h2o_encoded_1)
df_encoded_1 = cbind(data.frame(id = 1:nrow(df_encoded_1)), df_encoded_1)
df_encoded_1
##    id animal rating TargetEncode_animal
## 1   1    Cat   28.5              22.575
## 2   2    Cat   23.4              22.575
## 3   3    Cat   22.6              22.575
## 4   4    Cat   15.8              22.575
## 5   5    Dog   33.0              28.000
## 6   6    Dog   31.9              28.000
## 7   7    Dog   29.0              28.000
## 8   8    Dog   27.1              28.000
## 9   9    Dog   25.2              28.000
## 10 10    Dog   21.8              28.000
## 11 11   Lion   55.3              52.750
## 12 12   Lion   50.2              52.750

Мы можем очень легко получить тот же результат сбумага и карандаш.Нам просто нужно рассчитать среднее значение для каждой категории по: animal.Вот и все.

Target Encoding |Blended Average

На encoding_map выше мы видим категорию: Lion отображается только по нескольким наблюдениям (в сравнении с другими значениями).Тогда вычисленное среднее может быть ненадежным.

Чтобы справиться с этим, H2O поддерживает параметр: blended_avg, как мы видим на:

http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/algo-params/blended_avg.html

Здесь мы можем прочитать:

«Параметр blended_avg определяет, следует ли взвешивать целевое среднее значение на основе счетчика группы.Часто бывает, что в некоторых группах может быть небольшое количество записей, и целевое среднее значение будет ненадежным.Чтобы предотвратить это, смешанное среднее принимает средневзвешенное значение целевого значения группы и глобального целевого значения. »

Давайте используем параметр: blended_avg:

df_h2o_encoded_2 = h2o.target_encode_apply(
  data = as.h2o(df),
  x = list("animal"),
  y = "rating",
  target_encode_map = encoding_map,
  holdout_type = "None", # using None for simplicity
  blended_avg = TRUE,
  noise = 0,
  seed = 1234
)
df_encoded_2 = as.data.frame(df_h2o_encoded_2)
df_encoded_2 = cbind(data.frame(id = 1:nrow(df_encoded_2)), df_encoded_2)
df_encoded_2
##    id animal rating TargetEncode_animal
## 1   1    Cat   28.5            29.01621
## 2   2    Cat   23.4            29.01621
## 3   3    Cat   22.6            29.01621
## 4   4    Cat   15.8            29.01621
## 5   5    Dog   33.0            29.85839
## 6   6    Dog   31.9            29.85839
## 7   7    Dog   29.0            29.85839
## 8   8    Dog   27.1            29.85839
## 9   9    Dog   25.2            29.85839
## 10 10    Dog   21.8            29.85839
## 11 11   Lion   55.3            33.49886
## 12 12   Lion   50.2            33.49886

Сравнение обоих Target Encoding значений

df_comp = df_encoded_1
df_comp = df_comp %>% left_join(as.data.frame(encoding_map$animal), by = "animal") %>% select(-numerator)
df_comp = df_comp %>% left_join(df_encoded_2[,c("id", "TargetEncode_animal")], by = "id") %>% select(-c(id))
colnames(df_comp) = c("animal", "rating", "encoding_simple", "num_obs", "encoding_blended")
setcolorder(df_comp, c("animal", "rating", "num_obs", "encoding_simple", "encoding_blended"))
df_comp = df_comp %>% mutate(encoding_diff = encoding_blended - encoding_simple)
df_comp
##    animal rating num_obs encoding_simple encoding_blended encoding_diff
## 1     Cat   28.5       4          22.575         29.01621      6.441209
## 2     Cat   23.4       4          22.575         29.01621      6.441209
## 3     Cat   22.6       4          22.575         29.01621      6.441209
## 4     Cat   15.8       4          22.575         29.01621      6.441209
## 5     Dog   33.0       6          28.000         29.85839      1.858393
## 6     Dog   31.9       6          28.000         29.85839      1.858393
## 7     Dog   29.0       6          28.000         29.85839      1.858393
## 8     Dog   27.1       6          28.000         29.85839      1.858393
## 9     Dog   25.2       6          28.000         29.85839      1.858393
## 10    Dog   21.8       6          28.000         29.85839      1.858393
## 11   Lion   55.3       2          52.750         33.49886    -19.251141
## 12   Lion   50.2       2          52.750         33.49886    -19.251141

Как видно из таблицы выше, дискретные значения с наблюдениями с большим числом почти не меняли значения кодирования.С другой стороны, значения с меньшим числом наблюдений сильно изменяют свои значения кодирования, перемещая их ближе к глобальному среднему.

Это имеет смысл для: Target Encoding, когда он будет использоваться наLearning Model потому что таким образом Target Encoding для переменных с меньшим числом наблюдений не окажет большого влияния на целевую переменную.

Моя цель

Учитывая последнюю таблицу сравнения, которая мне нужнаЧтобы вычислить значение для столбца: encoding_blended, используя значения в предыдущих столбцах.

Знаете ли вы, какую формулу я могу использовать для достижения этой цели?

Спасибо!

...