Kiedy powinniśmy dyskretyzować / bin ciągłe zmienne / funkcje niezależne, a kiedy nie?

22

Kiedy powinniśmy dyskretyzować / bin niezależne zmienne / cechy, a kiedy nie?

Moje próby odpowiedzi na pytanie:

  • Zasadniczo nie powinniśmy binować, ponieważ binowanie spowoduje utratę informacji.
  • Binning faktycznie zwiększa stopień swobody modelu, więc możliwe jest spowodowanie nadmiernego dopasowania po binningu. Jeśli mamy model „dużej odchylenia”, binowanie może nie być złe, ale jeśli mamy model „dużej wariancji”, powinniśmy unikać binowania.
  • To zależy od używanego modelu. Jeśli jest to tryb liniowy, a dane mają dużo „wartości odstających”, prawdopodobieństwo binowania jest lepsze. Jeśli mamy model drzewa, wówczas wartości odstające i binowanie będą zbyt duże.

Czy mam rację? i co jeszcze?


Myślałem, że to pytanie powinno być zadawane wiele razy, ale nie mogę znaleźć w CV tylko tych postów

Czy powinniśmy bin zmienne ciągłe?

Jaka jest korzyść z rozbicia ciągłej zmiennej predykcyjnej?

Haitao Du
źródło
Nie sądzę, aby to pytanie było duplikatem, ponieważ odpowiedź tak naprawdę nie rozwiązuje tego problemu („powinniśmy to zrobić”).
Firebug,
8
Podejścia CART / losowe do lasu są mniej lub bardziej binningowymi zmiennymi ciągłymi (dopasowującymi funkcje cząstkowe-stałe), ale robią to w znacznie lepszy sposób. Jeśli wstępnie kosztujesz, odmawiasz swemu algorytmowi tworzenia drzew elastyczności, aby umieścić przerwy w optymalnym miejscu ...
Ben Bolker

Odpowiedzi:

16

Wygląda na to, że szukasz odpowiedzi z predykcyjnego punktu widzenia, dlatego przygotowałem krótką prezentację dwóch podejść w R

  • Podział zmiennej na czynniki równej wielkości.
  • Naturalne splajny sześcienne.

Poniżej podałem kod funkcji, która automatycznie porówna dwie metody dla dowolnej funkcji prawdziwego sygnału

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

Ta funkcja utworzy hałaśliwe zestawy danych treningowych i testowych na podstawie danego sygnału, a następnie dopasuje szereg regresji liniowych do danych treningowych dwóch typów

  • cutsModel obejmuje binned predykcyjnych, utworzonych przez segmenty zakres danych w równych rozmiarach półotwartą odstępach czasu, a następnie tworząc predykcyjnych binarną wskazującą, do którego interwał każdy punkt należący szkolenia.
  • splinesModel obejmuje naturalną sześcienny Podstawa wielowypustowy rozprężania z węzłów równomiernie rozmieszczone na całym obszarze predyktora.

Argumenty są

  • signal: Funkcja jednej zmiennej reprezentująca prawdę, którą należy oszacować.
  • N: Liczba próbek, które należy uwzględnić zarówno w danych szkoleniowych, jak i testowych.
  • noise: Mnóstwo losowego hałasu gaussowskiego w celu zwiększenia sygnału treningowego i testowego.
  • range: Zakres danych szkoleniowych i testowych x, dane są generowane jednolicie w tym zakresie.
  • max_paramters: Maksymalna liczba parametrów do oszacowania w modelu. Jest to zarówno maksymalna liczba segmentów w cutsmodelu, jak i maksymalna liczba węzłów w splinesmodelu.

Zauważ, że liczba parametrów oszacowana w splinesmodelu jest taka sama jak liczba węzłów, więc oba modele są dość porównywane.

Obiekt zwrotny z funkcji ma kilka składników

  • signal_plot: Wykres funkcji sygnału.
  • data_plot: Wykres punktowy danych treningowych i testowych.
  • errors_comparison_plot: Wykres pokazujący ewolucję sumy kwadratowego poziomu błędu dla obu modeli w zakresie liczby ustalonych parametrów.

Pokażę z dwiema funkcjami sygnału. Pierwszą jest fala sinusoidalna z nakładającym się rosnącym trendem liniowym

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

obj <- test_cuts_vs_splines(true_signal_sin, 250, 1)

Oto jak ewoluują poziomy błędów

grupowanie vs splajny trenuje i testuje wydajność z różnym stopniem swobody w celu zwiększenia fali sinusoidalnej

Drugi przykład to szalona funkcja, którą trzymam tylko dla tego rodzaju rzeczy, wykreśl ją i zobacz

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)

grupowanie vs splajny trenuje i testuje wydajność z różnym stopniem swobody w celu zwiększenia funkcji bizarro

A dla zabawy jest to nudna funkcja liniowa

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

grupowanie vs splajny wydajność pociągu i testu o różnym stopniu swobody dla funkcji liniowej

Możesz to zobaczyć:

  • Splajny dają ogólnie lepszą ogólną wydajność testu, gdy złożoność modelu jest odpowiednio dostrojona dla obu.
  • Splajny zapewniają optymalną wydajność testu przy znacznie mniejszej liczbie szacowanych parametrów .
  • Ogólnie wydajność splajnów jest znacznie bardziej stabilna, ponieważ liczba szacowanych parametrów jest zróżnicowana.

Dlatego splajny należy zawsze wybierać z predykcyjnego punktu widzenia.

Kod

Oto kod, którego użyłem do stworzenia tych porównań. Założyłem to wszystko w funkcję, abyś mógł wypróbować to z własnymi funkcjami sygnałowymi. Konieczne będzie zaimportowanie bibliotek ggplot2i 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
źródło
19

Agregacja ma znaczenie merytoryczne (niezależnie od tego, czy badacz jest tego świadomy).

Należy binować dane, w tym zmienne niezależne, na podstawie samych danych, gdy chce się:

  • Do krwotoków mocy statystycznej.

  • Do stronniczości miar asocjacji.

Wydaje mi się, że literatura zaczyna się od Ghelke i Biehla (1934 - na pewno warta przeczytania i sugeruje kilka łatwych symulacji komputerowych, które można uruchomić dla siebie), a kontynuowana jest zwłaszcza w literaturze „problem z modyfikowalnymi jednostkami powierzchniowymi” (Openshaw , 1983; Dudley, 1991; Lee i Kemp, 2000) wyjaśniają oba te punkty.

Jeśli nie ma się teorii a priori o skali agregacji (do ilu jednostek należy agregować) i funkcji kategoryzacji agregacji (do których indywidualnych obserwacji dojdzie w których jednostkach agregujących), nie należy agregować. Na przykład w epidemiologii dbamy o zdrowie jednostek i zdrowie populacji . Te ostatnie nie są po prostu przypadkowymi zbiorami tych pierwszych, ale są zdefiniowane na przykład przez granice geopolityczne, okoliczności społeczne, takie jak kategoryzacja rasowo-etniczna, status karceralny i kategorie historyczne itp. (Zobacz na przykład Krieger, 2012)

Odnośniki
Dudley, G. (1991). Skala, agregacja i problem modyfikowalnej jednostki powierzchni . [płatny mur] The Operational Geographer, 9 (3): 28–33.

Gehlke, CE i Biehl, K. (1934). Pewne skutki grupowania na podstawie wielkości współczynnika korelacji w materiale kanału spisowego . [pay-walled] Journal of American Statistics Association , 29 (185): 169–170.

Krieger, N. (2012). Kto i czym jest „populacja”? historyczne debaty, aktualne kontrowersje i implikacje dla zrozumienia „zdrowia populacji” i niwelowania nierówności zdrowotnych . The Milbank Quarterly , 90 (4): 634–681.

Lee, HTK i Kemp, Z. (2000). Hierarchiczne rozumowanie i analityczne przetwarzanie on-line danych przestrzennych i czasowych . W postępowaniu z 9. Międzynarodowego Sympozjum na temat przetwarzania danych przestrzennych , Pekin, Chiny PR. Międzynarodowa Unia Geograficzna.

Openshaw, S. (1983). Problem z modyfikowalną jednostką powierzchniową. Koncepcje i techniki współczesnej geografii . Geo Books, Norwich, Wielka Brytania.

Alexis
źródło
10
Smutno mi było głosować za tą odpowiedzią, ponieważ twój przedstawiciel ma teraz więcej niż 8888, co było dla mnie estetyczne.
Sycorax mówi Przywróć Monikę
@ hxd1011 i GeneralAbrial:: D: D: D: D
Alexis
UWIELBIAM tę odpowiedź, ale odpowiedź @ MatthewDrury jest naprawdę taka, którą chcę zobaczyć.
Haitao Du
Dziękujemy za przekonującą odpowiedź z wieloma interesującymi referencjami!
y.selivonchyk