0Pricing
R Academy · Lekcja

Drzewa decyzyjne: podstawa metod ensemble

Twórz i wizualizuj drzewa decyzyjne za pomocą rpart oraz poznaj kompromis obciążenie–wariancja.

Drzewa decyzyjne: podstawa metod ensemble to bezpłatna lekcja R Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.

Jak drzewa decyzyjne dzielą dane

Drzewo decyzyjne rekurencyjnie dzieli przestrzeń cech na prostokątne obszary. W każdym węźle algorytm przeszukuje wszystkie cechy i wszystkie możliwe punkty podziału, aby znaleźć podział, który najlepiej rozdziela zmienną docelową. Wynikiem jest drzewo reguł if-else.

library(rpart)

# Fit a classification tree
tree <- rpart(
  Species ~ .,
  data   = iris,
  method = 'class'  # use 'anova' for regression
)

print(tree)

Kryteria podziału: GINI a entropia

Kryterium podziału mierzy nieczystość węzła. Nieczystość Giniego mierzy prawdopodobieństwo błędnej klasyfikacji losowo wybranego elementu. Entropia (przyrost informacji) mierzy zmniejszenie nieuporządkowania informacyjnego. Oba kryteria zwykle prowadzą do podobnych drzew; Gini jest szybsze w obliczeniach i stanowi domyślne kryterium w rpart.

# Default: Gini impurity (parms = list(split = 'gini'))
tree_gini <- rpart(Species ~ ., data = iris, method = 'class')

# Using information gain (entropy)
tree_entropy <- rpart(
  Species ~ ., data = iris, method = 'class',
  parms = list(split = 'information')
)

cat('Gini root split:', tree_gini$frame$var[1])
cat('Entropy root split:', tree_entropy$frame$var[1])

printcp() — tabela złożoności

printcp(tree) wyświetla tabelę parametrów złożoności (CP). Każdy wiersz pokazuje rozmiar drzewa (liczbę podziałów), względny błąd na danych treningowych oraz błąd oszacowany za pomocą walidacji krzyżowej (xerror). Tabela CP służy do znalezienia optymalnego poziomu przycinania.

tree <- rpart(medv ~ ., data = MASS::Boston, method = 'anova',
              control = rpart.control(minsplit = 5, cp = 0.001))

printcp(tree)

# Identify the CP with minimum cross-validated error
best_cp <- tree$cptable[
  which.min(tree$cptable[, 'xerror']),
  'CP'
]
cat('Best CP:', best_cp)

prune() — przycinanie drzewa

prune(tree, cp) przycina drzewo do poziomu złożoności określonego przez cp. Przycinanie zapobiega przeuczeniu, zwijając gałęzie, które mają niewielką wartość predykcyjną. Standardowe podejście polega na znalezieniu wartości CP minimalizującej błąd walidacji krzyżowej, a następnie przycięciu drzewa.

best_cp <- tree$cptable[
  which.min(tree$cptable[, 'xerror']), 'CP'
]

pruned_tree <- prune(tree, cp = best_cp)

cat('Original tree nodes:', nrow(tree$frame))
cat('Pruned tree nodes:', nrow(pruned_tree$frame))

rpart.plot() — wizualizacja drzewa

rpart.plot(tree) z pakietu rpart.plot tworzy przejrzystą, kolorową wizualizację drzewa decyzyjnego. Każdy węzeł wewnętrzny pokazuje regułę podziału, a każdy liść — przewidywaną klasę i udział próbek treningowych.

library(rpart.plot)

tree <- rpart(Species ~ ., data = iris, method = 'class')
pruned <- prune(tree, cp = 0.02)

rpart.plot(
  pruned,
  type   = 4,     # split labels on branches
  extra  = 104,   # show class + probability
  fallen.leaves = TRUE
)

Kompromis między obciążeniem a wariancją

Głębokie, nieprzycięte drzewo ma niskie obciążenie (niemal idealnie dopasowuje się do danych treningowych), ale wysoką wariancję (niewielkie zmiany w danych prowadzą do powstania zupełnie innych drzew). Płytkie lub przycięte drzewo ma wyższe obciążenie, ale niższą wariancję. Optymalne drzewo równoważy te dwa źródła błędu.

Metody zespołowe, takie jak lasy losowe i boosting, bezpośrednio wykorzystują ten kompromis.

# Deep tree = low bias, high variance (overfits)
deep_tree <- rpart(medv ~ ., data = MASS::Boston,
                   control = rpart.control(minsplit = 2, cp = 0))

# Shallow tree = high bias, low variance (underfits)
shallow_tree <- rpart(medv ~ ., data = MASS::Boston,
                      control = rpart.control(maxdepth = 2))

cat('Deep nodes:', nrow(deep_tree$frame))
cat('Shallow nodes:', nrow(shallow_tree$frame))

Przeuczenie drzewa decyzyjnego

Nieprzycięte drzewo może osiągnąć zerowy błąd treningowy, zapamiętując każdy przykład treningowy. Gdy to samo drzewo zostanie ocenione na nieznanych danych, jego skuteczność gwałtownie spada. Jest to klasyczny przykład przeuczenia w uczeniu nadzorowanym.

set.seed(42)
train_idx <- sample(nrow(MASS::Boston), 400)
train_bos <- MASS::Boston[train_idx, ]
test_bos  <- MASS::Boston[-train_idx, ]

# Fully grown tree
full <- rpart(medv ~ ., data = train_bos,
              control = rpart.control(cp = 0, minsplit = 2))

train_pred <- predict(full, train_bos)
test_pred  <- predict(full, test_bos)

cat('Train RMSE:', sqrt(mean((train_pred - train_bos$medv)^2)))
cat('Test  RMSE:', sqrt(mean((test_pred  - test_bos$medv)^2)))

Ważność zmiennych w rpart

rpart zapisuje variable.importance dla każdego predyktora: całkowitą poprawę kryterium podziału przypisaną danej zmiennej we wszystkich podziałach. Daje to szybkie wskazanie, które cechy wpływają na decyzje modelu.

tree <- rpart(medv ~ ., data = MASS::Boston, method = 'anova')

# Variable importance (sorted)
imp <- sort(tree$variable.importance, decreasing = TRUE)
print(imp)

# Quick barplot
barplot(imp, las = 2, main = 'Variable Importance',
        col = 'steelblue', cex.names = 0.8)

Od drzew do metod zespołowych

Pojedyncze drzewo decyzyjne jest niestabilne: ponowne losowanie danych prowadzi do powstania bardzo różnych drzew. Metody zespołowe wykorzystują tę niestabilność:

  • Bagging / lasy losowe: uśredniają wiele drzew trenowanych na próbkach bootstrapowych.
  • Boosting: buduje drzewa sekwencyjnie, przy czym każde koryguje błędy poprzedniego drzewa.
  • Obie metody zmniejszają wariancję, zachowując ekspresyjność drzew.
# Demonstrating instability of a single tree
set.seed(1); t1 <- rpart(medv ~ ., data = MASS::Boston[sample(506, 400), ])
set.seed(2); t2 <- rpart(medv ~ ., data = MASS::Boston[sample(506, 400), ])

# Root split may differ between trees
cat('Tree 1 root split:', t1$frame$var[1])
cat('Tree 2 root split:', t2$frame$var[1])

Parametry sterujące rpart

rpart.control() określa sposób wzrostu drzewa. Najważniejsze parametry to: cp (kara za złożoność), minsplit (minimalna liczba obserwacji wymagana do podjęcia próby podziału), minbucket (minimalny rozmiar liścia) oraz maxdepth. Zrozumienie tych parametrów jest niezbędne do strojenia modeli opartych na drzewach.

ctrl <- rpart.control(
  cp        = 0.005,  # complexity penalty
  minsplit  = 20,     # min obs to try a split
  minbucket = 7,      # min obs in any leaf
  maxdepth  = 10      # max tree depth
)

tree <- rpart(medv ~ ., data = MASS::Boston,
              method = 'anova', control = ctrl)

printcp(tree)

Ocena skuteczności drzewa

Po przycięciu należy ocenić drzewo na wydzielonym zbiorze testowym. W przypadku regresji należy obliczyć RMSE i R-kwadrat, a w przypadku klasyfikacji — accuracy oraz macierz pomyłek. Warto porównać te miary z modelami referencyjnymi, aby zrozumieć wartość, jaką zapewnia pojedyncze drzewo.

pruned_tree <- prune(tree, cp = best_cp)

test_pred <- predict(pruned_tree, newdata = test_bos)

rmse <- sqrt(mean((test_pred - test_bos$medv)^2))
ss_res <- sum((test_pred - test_bos$medv)^2)
ss_tot <- sum((test_bos$medv - mean(test_bos$medv))^2)
r2 <- 1 - ss_res / ss_tot

cat('RMSE:', round(rmse, 3))
cat('R2:', round(r2, 3))

Szybkie sprawdzenie

Które stwierdzenie najlepiej opisuje cel wywołania prune(tree, cp = best_cp)?

Podsumowanie drzew decyzyjnych

Najważniejsze informacje z lekcji „Drzewa decyzyjne — podstawa metod zespołowych”:

  • Drzewa rekurencyjnie dzielą przestrzeń cech; podziały wykorzystują kryterium Giniego lub entropię.
  • rpart(y ~ ., data, method) dopasowuje drzewo, a printcp() wyświetla tabelę złożoności.
  • Należy znaleźć wartość CP zapewniającą minimalny błąd walidacji krzyżowej, a następnie użyć prune(tree, cp).
  • rpart.plot() wizualizuje strukturę drzewa.
  • Głębokie drzewa ulegają przeuczeniu (niskie obciążenie, wysoka wariancja), a płytkie drzewa — niedouczeniu.
  • tree$variable.importance szereguje predyktory według ich całkowitej poprawy podziału.
  • Metody zespołowe (lasy losowe, boosting) przezwyciężają niestabilność pojedynczego drzewa.
# Standard rpart workflow
tree <- rpart(y ~ ., data = train, method = 'anova',
              control = rpart.control(cp = 0.001))

best_cp <- tree$cptable[which.min(tree$cptable[, 'xerror']), 'CP']
pruned  <- prune(tree, cp = best_cp)

test_pred <- predict(pruned, newdata = test)
rmse <- sqrt(mean((test_pred - test$y)^2))
cat('Pruned Tree RMSE:', rmse)

Często zadawane pytania

Czy lekcja „Drzewa decyzyjne: podstawa metod ensemble” jest bezpłatna?

Tak — pełny tekst „Drzewa decyzyjne: podstawa metod ensemble” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Drzewa decyzyjne: podstawa metod ensemble”?

Twórz i wizualizuj drzewa decyzyjne za pomocą rpart oraz poznaj kompromis obciążenie–wariancja. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć R Academy?

Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Drzewa decyzyjne: podstawa metod ensemble”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?

Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Drzewa decyzyjne: podstawa metod ensemble
  2. Lasy losowe za pomocą ranger
  3. Gradient boosting za pomocą xgboost
  4. Ważność cech i interpretacja modeli
← Powrót do R Academy