Quando devemos discretizar / classificar variáveis ​​/ recursos independentes contínuos e quando não devemos?

21

Quando devemos discretizar / bin variáveis ​​/ recursos independentes e quando não devemos?

Minhas tentativas de responder à pergunta:

  • Em geral, não devemos fazer bin, porque o binning perderá informações.
  • Na verdade, o binning está aumentando o grau de liberdade do modelo; portanto, é possível causar um ajuste excessivo após o binning. Se tivermos um modelo de "alto viés", o binning pode não ser ruim, mas se tivermos um modelo de "alta variância", devemos evitar o binning.
  • Depende do modelo que estamos usando. Se for um modo linear, e os dados tiverem muitas probabilidades de binning "outliers", é melhor. Se tivermos um modelo de árvore, então, outlier e binning farão muita diferença.

Estou certo? e o que mais?


Eu pensei que essa pergunta deveria ser feita muitas vezes, mas não consigo encontrá-la no CV apenas nessas postagens

Devemos bin variáveis ​​contínuas?

Qual é o benefício de dividir uma variável preditora contínua?

Haitao Du
fonte
Não acho que essa pergunta seja uma duplicata porque a resposta realmente não aborda esse problema ("devemos fazê-lo").
Firebug
8
As abordagens de CART / floresta aleatória são mais ou menos variáveis ​​binárias contínuas (ajustando funções constantes por partes), mas estão fazendo isso de uma maneira muito melhor. Se você pré-bin, você está negando sua árvore-construção de algoritmo a flexibilidade para colocar as quebras em um lugar ideal ...
Ben Bolker

Respostas:

16

Parece que você também está procurando uma resposta do ponto de vista preditivo, então montei uma breve demonstração de duas abordagens em R

  • Agrupando uma variável em fatores de tamanho igual.
  • Splines cúbicos naturais.

Abaixo, eu forneci o código para uma função que comparará os dois métodos automaticamente para qualquer função de sinal verdadeiro

test_cuts_vs_splines <- function(signal, N, noise,
                                 range=c(0, 1), 
                                 max_parameters=50,
                                 seed=154)

Essa função criará conjuntos de dados de treinamento e teste ruidosos a partir de um determinado sinal e ajustará uma série de regressões lineares aos dados de treinamento de dois tipos

  • O cutsmodelo inclui preditores binados, formados pela segmentação do intervalo de dados em intervalos semiabertos de tamanho igual e, em seguida, criando preditores binários indicando a qual intervalo cada ponto de treinamento pertence.
  • O splinesmodelo inclui uma expansão da base da spline cúbica natural, com nós igualmente espaçados em toda a faixa do preditor.

Os argumentos são

  • signal: Uma função de uma variável representando a verdade a ser estimada.
  • N: O número de amostras a serem incluídas nos dados de treinamento e teste.
  • noise: O amplo ruído gaussiano aleatório a ser adicionado ao sinal de treinamento e teste.
  • range: O intervalo dos xdados de treinamento e teste , dados gerados uniformemente dentro desse intervalo.
  • max_paramters: O número máximo de parâmetros a serem estimados em um modelo. Esse é o número máximo de segmentos no cutsmodelo e o número máximo de nós no splinesmodelo.

Observe que o número de parâmetros estimados no splinesmodelo é igual ao número de nós, portanto, os dois modelos são comparados de maneira justa.

O objeto de retorno da função possui alguns componentes

  • signal_plot: Um gráfico da função de sinal.
  • data_plot: Um gráfico de dispersão dos dados de treinamento e teste.
  • errors_comparison_plot: Um gráfico que mostra a evolução da soma da taxa de erro ao quadrado de ambos os modelos em uma faixa do número de parâmetros estimados.

Vou demonstrar com duas funções de sinal. A primeira é uma onda sinusal com uma tendência linear crescente sobreposta

true_signal_sin <- function(x) {
  x + 1.5*sin(3*2*pi*x)
}

obj <- test_cuts_vs_splines(true_signal_sin, 250, 1)

Aqui está como as taxas de erro evoluem

agrupamento vs splines treinam e testam o desempenho com diferentes graus de liberdade para aumentar a onda sinusal

O segundo exemplo é uma função maluca que eu mantenho por aí apenas para esse tipo de coisa, plote e veja

true_signal_weird <- function(x) {
  x*x*x*(x-1) + 2*(1/(1+exp(-.5*(x-.5)))) - 3.5*(x > .2)*(x < .5)*(x - .2)*(x - .5)
}

obj <- test_cuts_vs_splines(true_signal_weird, 250, .05)

agrupamento vs splines treina e testa o desempenho com diferentes graus de liberdade para aumentar a função bizarro

E por diversão, aqui está uma função linear chata

obj <- test_cuts_vs_splines(function(x) {x}, 250, .2)

agrupamento vs splines, desempenho do trem e do teste com grau de liberdade variável para função linear

Você pode ver isso:

  • As splines oferecem um desempenho geral melhor no teste geral quando a complexidade do modelo é ajustada adequadamente para ambos.
  • As splines oferecem desempenho ideal de teste com muito menos parâmetros estimados .
  • No geral, o desempenho dos splines é muito mais estável, pois o número de parâmetros estimados varia.

Portanto, splines sempre devem ser preferidos do ponto de vista preditivo.

Código

Aqui está o código que eu usei para produzir essas comparações. Coloquei tudo em uma função para que você possa testá-lo com suas próprias funções de sinal. Você precisará importar as bibliotecas ggplot2e splinesR.

test_cuts_vs_splines <- function(signal, N, noise,
                                 range=c(0, 1), 
                                 max_parameters=50,
                                 seed=154) {

  if(max_parameters < 8) {
    stop("Please pass max_parameters >= 8, otherwise the plots look kinda bad.")
  }

  out_obj <- list()

  set.seed(seed)

  x_train <- runif(N, range[1], range[2])
  x_test <- runif(N, range[1], range[2])

  y_train <- signal(x_train) + rnorm(N, 0, noise)
  y_test <- signal(x_test) + rnorm(N, 0, noise)

  # A plot of the true signals
  df <- data.frame(
    x = seq(range[1], range[2], length.out = 100)
  )
  df$y <- signal(df$x)
  out_obj$signal_plot <- ggplot(data = df) +
    geom_line(aes(x = x, y = y)) +
    labs(title = "True Signal")

  # A plot of the training and testing data
  df <- data.frame(
    x = c(x_train, x_test),
    y = c(y_train, y_test),
    id = c(rep("train", N), rep("test", N))
  )
  out_obj$data_plot <- ggplot(data = df) + 
    geom_point(aes(x=x, y=y)) + 
    facet_wrap(~ id) +
    labs(title = "Training and Testing Data")

  #----- lm with various groupings -------------   
  models_with_groupings <- list()
  train_errors_cuts <- rep(NULL, length(models_with_groupings))
  test_errors_cuts <- rep(NULL, length(models_with_groupings))

  for (n_groups in 3:max_parameters) {
    cut_points <- seq(range[1], range[2], length.out = n_groups + 1)
    x_train_factor <- cut(x_train, cut_points)
    factor_train_data <- data.frame(x = x_train_factor, y = y_train)
    models_with_groupings[[n_groups]] <- lm(y ~ x, data = factor_train_data)

    # Training error rate
    train_preds <- predict(models_with_groupings[[n_groups]], factor_train_data)
    soses <- (1/N) * sum( (y_train - train_preds)**2)
    train_errors_cuts[n_groups - 2] <- soses

    # Testing error rate
    x_test_factor <- cut(x_test, cut_points)
    factor_test_data <- data.frame(x = x_test_factor, y = y_test)
    test_preds <- predict(models_with_groupings[[n_groups]], factor_test_data)
    soses <- (1/N) * sum( (y_test - test_preds)**2)
    test_errors_cuts[n_groups - 2] <- soses
  }

  # We are overfitting
  error_df_cuts <- data.frame(
    x = rep(3:max_parameters, 2),
    e = c(train_errors_cuts, test_errors_cuts),
    id = c(rep("train", length(train_errors_cuts)),
           rep("test", length(test_errors_cuts))),
    type = "cuts"
  )
  out_obj$errors_cuts_plot <- ggplot(data = error_df_cuts) +
    geom_line(aes(x = x, y = e)) +
    facet_wrap(~ id) +
    labs(title = "Error Rates with Grouping Transformations",
         x = ("Number of Estimated Parameters"),
         y = ("Average Squared Error"))

  #----- lm with natural splines -------------  
  models_with_splines <- list()
  train_errors_splines <- rep(NULL, length(models_with_groupings))
  test_errors_splines <- rep(NULL, length(models_with_groupings))

  for (deg_freedom in 3:max_parameters) {
    knots <- seq(range[1], range[2], length.out = deg_freedom + 1)[2:deg_freedom]

    train_data <- data.frame(x = x_train, y = y_train)
    models_with_splines[[deg_freedom]] <- lm(y ~ ns(x, knots=knots), data = train_data)

    # Training error rate
    train_preds <- predict(models_with_splines[[deg_freedom]], train_data)
    soses <- (1/N) * sum( (y_train - train_preds)**2)
    train_errors_splines[deg_freedom - 2] <- soses

    # Testing error rate
    test_data <- data.frame(x = x_test, y = y_test)  
    test_preds <- predict(models_with_splines[[deg_freedom]], test_data)
    soses <- (1/N) * sum( (y_test - test_preds)**2)
    test_errors_splines[deg_freedom - 2] <- soses
  }

  error_df_splines <- data.frame(
    x = rep(3:max_parameters, 2),
    e = c(train_errors_splines, test_errors_splines),
    id = c(rep("train", length(train_errors_splines)),
           rep("test", length(test_errors_splines))),
    type = "splines"
  )
  out_obj$errors_splines_plot <- ggplot(data = error_df_splines) +
    geom_line(aes(x = x, y = e)) +
    facet_wrap(~ id) +
    labs(title = "Error Rates with Natural Cubic Spline Transformations",
         x = ("Number of Estimated Parameters"),
         y = ("Average Squared Error"))


  error_df <- rbind(error_df_cuts, error_df_splines)
  out_obj$error_df <- error_df

  # The training error for the first cut model is always an outlier, and
  # messes up the y range of the plots.
  y_lower_bound <- min(c(train_errors_cuts, train_errors_splines))
  y_upper_bound = train_errors_cuts[2]
  out_obj$errors_comparison_plot <- ggplot(data = error_df) +
    geom_line(aes(x = x, y = e)) +
    facet_wrap(~ id*type) +
    scale_y_continuous(limits = c(y_lower_bound, y_upper_bound)) +
    labs(
      title = ("Binning vs. Natural Splines"),
      x = ("Number of Estimated Parameters"),
      y = ("Average Squared Error"))

  out_obj
}
Matthew Drury
fonte
19

A agregação é substancialmente significativa (independentemente de o pesquisador estar ciente disso).

É necessário agrupar dados, incluindo variáveis ​​independentes, com base nos dados quando se deseja:

  • Hemorragiar o poder estatístico.

  • Desviar medidas de associação.

Uma literatura que comece, creio eu, com Ghelke e Biehl (1934 - definitivamente vale a pena ser lida, e sugestiva de algumas simulações de computador fáceis o suficiente para que você possa executar por si mesmo), e continuando especialmente na literatura sobre o "problema da unidade de área modificável" (Openshaw , 1983; Dudley, 1991; Lee e Kemp, 2000) tornam esses dois pontos claros.

A menos que se tenha uma teoria a priori da escala de agregação (quantas unidades agregar) e da função de categorização da agregação (quais observações individuais terminarão em quais unidades agregadas), não se deve agregar. Por exemplo, em epidemiologia, nos preocupamos com a saúde dos indivíduos e com a saúde das populações . As últimas não são simplesmente coleções aleatórias da primeira, mas definidas por, por exemplo, fronteiras geopolíticas, circunstâncias sociais como categorização étnica de raça, status carceral e categorias da história, etc. (Veja, por exemplo, Krieger, 2012)

Referências
Dudley, G. (1991). Escala, agregação e o problema da unidade de área modificável . [pago] The Operational Geographer, 9 (3): 28–33.

Gehlke, CE e Biehl, K. (1934). Certos efeitos do agrupamento sobre o tamanho do coeficiente de correlação no material do setor censitário . [pay-walled] Journal of the American Statistical Association , 29 (185): 169-170.

Krieger, N. (2012). Quem e o que é uma "população"? debates históricos, controvérsias atuais e implicações para a compreensão da “saúde da população” e para a correção das iniquidades em saúde . The Milbank Quarterly , 90 (4): 634–681.

Lee, HTK e Kemp, Z. (2000). Raciocínio hierárquico e processamento analítico on-line de dados espaciais e temporais . Em Anais do 9º Simpósio Internacional sobre Tratamento de Dados Espaciais , Beijing, PR China. União Geográfica Internacional.

Openshaw, S. (1983). O problema da unidade de área modificável. Conceitos e Técnicas em Geografia Moderna . Geo Books, Norwich, Reino Unido.

Alexis
fonte
10
Fiquei triste ao votar esta resposta porque seu representante agora é maior que 8888, o que foi esteticamente agradável para mim.
Sycorax diz Restabelecer Monica
@ hxd1011 e GeneralAbrial:: D: D: D: D
Alexis
Eu amo essa resposta, mas a resposta de @ MatthewDrury é realmente que eu quero ver.
Haitao Du
Obrigado por uma resposta convincente com várias referências interessantes!
precisa saber é o seguinte