Skip to content

Sklearn Random Forest: Vollständiger Leitfaden zu Classification und Regression in Python

Updated on

Sie haben einen Decision Tree erstellt, der 95% Training-Accuracy erreicht, und er erzielt dann 62% auf neuen Daten. Ein einzelner Decision Tree memorisiert das Training-Set – jeder Split, jedes Leaf ist auf die exakten Samples abgestimmt, die er gesehen hat. Das Ergebnis ist ein Modell, das auf dem Papier großartig aussieht, aber in der Produktion versagt.

Dieses Overfitting-Problem ist nicht nur akademisch. Teams deployen Modelle, die in Development-Notebooks gut performen, aber unzuverlässige Predictions auf Live-Daten generieren. Ein einzelner Decision Tree hat eine hohe Variance: kleine Änderungen in den Trainingsdaten produzieren völlig unterschiedliche Tree-Strukturen. Sie können einem Modell nicht vertrauen, das so sensitiv gegenüber seinen Trainingsdaten ist.

Random Forest löst dies, indem hunderte von Decision Trees auf zufälligen Subsets von Daten und Features gebaut werden, und dann deren Predictions durch Majority Voting (Classification) oder Averaging (Regression) kombiniert werden. Dieser Ensemble-Ansatz reduziert die Variance dramatisch, während die Accuracy erhalten bleibt. Scikit-learns RandomForestClassifier und RandomForestRegressor bieten eine produktionsreife Implementierung mit eingebauter Feature Importance, Out-of-Bag-Evaluation und parallelem Training.

📚

Was ist Random Forest?

Random Forest ist eine Ensemble Learning Methode, die multiple Decision Trees kombiniert, um eine einzelne, robustere Prediction zu produzieren. Es verwendet eine Technik namens Bagging (Bootstrap Aggregating):

  1. Bootstrap Sampling: Erstellen Sie multiple zufällige Subsets der Trainingsdaten durch Sampling mit Zurücklegen. Jedes Subset ist ungefähr 63% der originalen Daten.
  2. Random Feature Selection: Bei jedem Split in jedem Tree werden nur eine zufällige Auswahl von Features betrachtet (typischerweise sqrt(n_features) für Classification, n_features/3 für Regression).
  3. Independent Training: Trainieren Sie einen Decision Tree auf jedem Bootstrap Sample mit der Random Feature Constraint.
  4. Aggregation: Kombinieren Sie Predictions durch Majority Vote (Classification) oder Mean (Regression).

Die Randomness sowohl im Data Sampling als auch in der Feature Selection stellt sicher, dass individuelle Trees dekorelliert sind. Selbst wenn ein Tree ein bestimmtes Pattern overfittet, werden die meisten anderen Trees das nicht tun, und das Ensemble mittelt das Noise aus.

Wann Random Forest verwenden

SzenarioRandom Forest?Warum
Tabellarische Daten mit gemischten Feature-TypenJaHandhabt numerische und kategorische Features, kein Scaling nötig
Sie benötigen Feature Importance RankingsJaEingebautes feature_importances_ Attribut
Small to Medium Datasets (bis ~100K Zeilen)JaSchnelles Training mit paralleler Verarbeitung
Imbalanced ClassificationJaUnterstützt class_weight='balanced'
Sie benötigen interpretierbare PredictionsModeratIndividuelle Trees sind interpretierbar, aber das Ensemble weniger
Sehr hochdimensionale Sparse Data (Text)NeinLineare Models oder Gradient Boosting sind typischerweise besser
Real-time Inference mit strikter LatencyVorsichtGroße Forests können zur Prediction-Zeit langsam sein

RandomForestClassifier: Classification Beispiel

Hier ist ein vollständiges Classification Beispiel mit dem Wine Dataset:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
from sklearn.datasets import load_wine
 
# Load dataset
wine = load_wine()
X, y = wine.data, wine.target
feature_names = wine.feature_names
 
print(f"Dataset: {X.shape[0]} samples, {X.shape[1]} features")
print(f"Classes: {wine.target_names}")
 
# Split data
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
 
# Train Random Forest
rf = RandomForestClassifier(
    n_estimators=100,
    max_depth=None,
    min_samples_split=2,
    min_samples_leaf=1,
    random_state=42,
    n_jobs=-1
)
rf.fit(X_train, y_train)
 
# Evaluate
y_pred = rf.predict(X_test)
print(f"\nAccuracy: {accuracy_score(y_test, y_pred):.4f}")
print(f"\nClassification Report:")
print(classification_report(y_test, y_pred, target_names=wine.target_names))

Wichtige Parameter erklärt

ParameterDefaultBeschreibungTuning Tipp
n_estimators100Anzahl der Trees im ForestMehr Trees = bessere Performance aber langsamer. 100-500 ist typisch.
max_depthNoneMaximale Tiefe jedes TreesNone bedeutet vollständig gewachsen. Setzen Sie auf 10-30, um Overfitting zu reduzieren.
min_samples_split2Minimale Samples zum Splitten eines NodesErhöhen auf 5-20, um Overfitting auf noisy Daten zu verhindern.
min_samples_leaf1Minimale Samples in einem Leaf NodeErhöhen auf 2-10 für glattere Predictions.
max_features'sqrt'Features, die bei jedem Split betrachtet werden'sqrt' für Classification, 'log2' oder ein Bruchteil für Alternativen.
bootstrapTrueBootstrap Sampling verwendenAuf False setzen für kleine Datasets, um alle Daten pro Tree zu verwenden.
class_weightNoneGewichte für jede Klasse'balanced' für Imbalanced Datasets verwenden.
n_jobsNoneAnzahl der parallelen JobsAuf -1 setzen, um alle CPU Cores zu verwenden.
oob_scoreFalseOut-of-Bag Samples für Evaluation verwendenAuf True setzen für einen eingebauten Validation Estimate ohne Holdout Set.

Out-of-Bag (OOB) Score

Jeder Tree wird auf ungefähr 63% der Daten trainiert. Die verbleibenden 37% (Out-of-Bag Samples) können als kostenloses Validation Set verwendet werden:

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
rf = RandomForestClassifier(
    n_estimators=200,
    oob_score=True,
    random_state=42,
    n_jobs=-1
)
rf.fit(X_train, y_train)
 
print(f"OOB Score:  {rf.oob_score_:.4f}")
print(f"Test Score: {rf.score(X_test, y_test):.4f}")

Der OOB Score gibt Ihnen einen Validation Estimate, ohne dass ein separates Holdout Set nötig ist. Dies ist besonders nützlich, wenn Daten limitiert sind.

RandomForestRegressor: Regression Beispiel

Random Forest Regression predicted kontinuierliche Werte durch Averaging der Outputs aller Trees:

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.datasets import fetch_california_housing
import numpy as np
 
# Load California housing dataset
housing = fetch_california_housing()
X, y = housing.data, housing.target
feature_names = housing.feature_names
 
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
 
# Train regressor
rf_reg = RandomForestRegressor(
    n_estimators=200,
    max_depth=20,
    min_samples_leaf=5,
    random_state=42,
    n_jobs=-1
)
rf_reg.fit(X_train, y_train)
y_pred = rf_reg.predict(X_test)
 
# Evaluation metrics
r2 = r2_score(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mae = mean_absolute_error(y_test, y_pred)
 
print(f"R-squared: {r2:.4f}")
print(f"RMSE:      {rmse:.4f}")
print(f"MAE:       {mae:.4f}")

Regressoren vergleichen

from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.datasets import fetch_california_housing
import numpy as np
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
regressors = {
    'Linear Regression': LinearRegression(),
    'Ridge': Ridge(alpha=1.0),
    'Decision Tree': DecisionTreeRegressor(max_depth=10, random_state=42),
    'Random Forest': RandomForestRegressor(n_estimators=100, max_depth=20, random_state=42, n_jobs=-1),
    'Gradient Boosting': GradientBoostingRegressor(n_estimators=100, max_depth=5, random_state=42),
}
 
print(f"{'Model':<25} {'CV R² (mean)':>12} {'CV R² (std)':>12}")
print("-" * 52)
 
for name, model in regressors.items():
    scores = cross_val_score(model, X_train, y_train, cv=5, scoring='r2', n_jobs=-1)
    print(f"{name:<25} {scores.mean():>12.4f} {scores.std():>12.4f}")

Random Forest übertrifft typischerweise einen einzelnen Decision Tree und lineare Models auf Datasets mit nicht-linearen Beziehungen, während es mit Gradient Boosting konkurriert.

Hyperparameter Tuning

GridSearchCV: Exhaustive Search

GridSearchCV testet jede Kombination der spezifizierten Parameterwerte:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.datasets import load_wine
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
param_grid = {
    'n_estimators': [100, 200, 300],
    'max_depth': [None, 10, 20],
    'min_samples_split': [2, 5, 10],
    'min_samples_leaf': [1, 2, 4],
}
 
rf = RandomForestClassifier(random_state=42, n_jobs=-1)
grid_search = GridSearchCV(
    rf,
    param_grid,
    cv=5,
    scoring='accuracy',
    n_jobs=-1,
    verbose=1
)
grid_search.fit(X_train, y_train)
 
print(f"Best Parameters: {grid_search.best_params_}")
print(f"Best CV Score:   {grid_search.best_score_:.4f}")
print(f"Test Score:      {grid_search.score(X_test, y_test):.4f}")

RandomizedSearchCV: Efficient Search

Wenn der Parameter Space groß ist, sampled RandomizedSearchCV eine feste Anzahl von Parameterkombinationen, anstatt alle zu testen:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import RandomizedSearchCV, train_test_split
from sklearn.datasets import load_wine
from scipy.stats import randint, uniform
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
param_distributions = {
    'n_estimators': randint(50, 500),
    'max_depth': [None, 5, 10, 15, 20, 30],
    'min_samples_split': randint(2, 20),
    'min_samples_leaf': randint(1, 10),
    'max_features': ['sqrt', 'log2', 0.3, 0.5, 0.7],
    'bootstrap': [True, False],
}
 
rf = RandomForestClassifier(random_state=42, n_jobs=-1)
random_search = RandomizedSearchCV(
    rf,
    param_distributions,
    n_iter=100,
    cv=5,
    scoring='accuracy',
    random_state=42,
    n_jobs=-1,
    verbose=1
)
random_search.fit(X_train, y_train)
 
print(f"Best Parameters: {random_search.best_params_}")
print(f"Best CV Score:   {random_search.best_score_:.4f}")
print(f"Test Score:      {random_search.score(X_test, y_test):.4f}")

Parameter Importance für Tuning

Nicht alle Parameter haben gleichen Impact. Fokussieren Sie Ihr Tuning Budget auf die Parameter, die am meisten zählen:

ParameterImpactPrioritätNotizen
n_estimatorsHoch1.Mehr Trees hilft fast immer, bis zu diminishing returns (~200-500)
max_depthHoch2.Kontrolliert Overfitting direkt. Versuchen Sie None, 10, 20, 30
min_samples_leafMittel3.Glättet Predictions. Versuchen Sie 1, 2, 5, 10
max_featuresMittel4.Kontrolliert Tree Diversity. 'sqrt' ist normalerweise gut für Classification
min_samples_splitNiedrig5.Weniger Impact als min_samples_leaf in der Praxis
bootstrapNiedrig6.True ist fast immer besser. Nur False bei sehr kleinen Datasets testen

Feature Importance

Einer der stärksten Vorteile von Random Forest ist die eingebaute Feature Importance. Zu verstehen, welche Features die Predictions treiben, hilft bei der Modellinterpretation, Feature Selection und Domain Insights.

Impurity-Based Feature Importance

Das default feature_importances_ Attribut misst, wie sehr jedes Feature die Impurity (Gini für Classification, Variance für Regression) über alle Trees hinweg reduziert:

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)
 
# Get feature importances
importances = rf.feature_importances_
feature_names = wine.feature_names
indices = np.argsort(importances)[::-1]
 
# Print ranked features
print("Feature Ranking:")
for i, idx in enumerate(indices):
    print(f"  {i+1}. {feature_names[idx]:25s} ({importances[idx]:.4f})")
 
# Plot
plt.figure(figsize=(10, 6))
plt.barh(range(len(indices)), importances[indices[::-1]], align='center')
plt.yticks(range(len(indices)), [feature_names[i] for i in indices[::-1]])
plt.xlabel('Feature Importance (Gini)')
plt.title('Random Forest Feature Importance - Wine Dataset')
plt.tight_layout()
plt.savefig('rf_feature_importance.png', dpi=150)
plt.show()

Permutation Importance

Impurity-based Importance kann biased gegenüber High-Cardinality Features sein. Permutation Importance misst den Drop in Modellperformance, wenn die Werte eines Features zufällig geshuffelt werden:

from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)
 
# Compute permutation importance on the test set
perm_imp = permutation_importance(
    rf, X_test, y_test,
    n_repeats=30,
    random_state=42,
    n_jobs=-1
)
 
# Sort and display
sorted_idx = perm_imp.importances_mean.argsort()[::-1]
 
print("Permutation Importance (test set):")
for idx in sorted_idx:
    mean = perm_imp.importances_mean[idx]
    std = perm_imp.importances_std[idx]
    print(f"  {wine.feature_names[idx]:25s}: {mean:.4f} +/- {std:.4f}")
 
# Plot with error bars
plt.figure(figsize=(10, 6))
plt.barh(
    range(len(sorted_idx)),
    perm_imp.importances_mean[sorted_idx[::-1]],
    xerr=perm_imp.importances_std[sorted_idx[::-1]],
    align='center'
)
plt.yticks(range(len(sorted_idx)), [wine.feature_names[i] for i in sorted_idx[::-1]])
plt.xlabel('Decrease in Accuracy')
plt.title('Permutation Importance - Wine Dataset')
plt.tight_layout()
plt.savefig('rf_permutation_importance.png', dpi=150)
plt.show()

Welche Importance Methode verwenden?

MethodeProsConsBest für
Impurity-based (feature_importances_)Schnell, keine extra BerechnungBiased gegenüber High-Cardinality FeaturesQuick screening, initiale Exploration
Permutation ImportanceUnbiased, funktioniert auf TestdatenLangsamer, beeinflusst von korrelierten FeaturesFinale Feature Selection, Reporting

Cross-Validation mit Random Forest

Basic Cross-Validation

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_wine
 
wine = load_wine()
X, y = wine.data, wine.target
 
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
scores = cross_val_score(rf, X, y, cv=5, scoring='accuracy')
 
print(f"CV Accuracy: {scores.mean():.4f} (+/- {scores.std():.4f})")
print(f"Per-fold:    {scores}")

StratifiedKFold für Imbalanced Data

StratifiedKFold bewahrt die Klassenverteilung in jedem Fold, was kritisch für Imbalanced Datasets ist:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.datasets import load_wine
import numpy as np
 
wine = load_wine()
X, y = wine.data, wine.target
 
# Stratified 10-fold cross-validation
skf = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
 
scores = cross_val_score(rf, X, y, cv=skf, scoring='accuracy')
print(f"Stratified 10-Fold Accuracy: {scores.mean():.4f} (+/- {scores.std():.4f})")
 
# Multiple metrics
from sklearn.model_selection import cross_validate
 
results = cross_validate(
    rf, X, y, cv=skf,
    scoring=['accuracy', 'f1_weighted', 'precision_weighted', 'recall_weighted'],
    n_jobs=-1
)
 
for metric in ['test_accuracy', 'test_f1_weighted', 'test_precision_weighted', 'test_recall_weighted']:
    vals = results[metric]
    name = metric.replace('test_', '')
    print(f"{name:>20s}: {vals.mean():.4f} (+/- {vals.std():.4f})")

Handling Imbalanced Data

Wenn eine Klasse deutlich mehr Samples hat als andere, kann ein Modell hohe Accuracy erreichen, indem es immer die Majority Klasse predicted. Random Forest bietet mehrere Tools, um dies zu handhaben.

Verwendung von class_weight='balanced'

Der class_weight='balanced' Parameter passt Gewichte automatisch invers proportional zu Klassenhäufigkeiten an:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_classification
 
# Create imbalanced dataset (95% class 0, 5% class 1)
X, y = make_classification(
    n_samples=2000,
    n_features=20,
    weights=[0.95, 0.05],
    flip_y=0,
    random_state=42
)
 
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
 
# Without class weight
rf_default = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
rf_default.fit(X_train, y_train)
print("=== Without class_weight ===")
print(classification_report(y_test, rf_default.predict(X_test)))
 
# With balanced class weight
rf_balanced = RandomForestClassifier(
    n_estimators=200,
    class_weight='balanced',
    random_state=42,
    n_jobs=-1
)
rf_balanced.fit(X_train, y_train)
print("=== With class_weight='balanced' ===")
print(classification_report(y_test, rf_balanced.predict(X_test)))

Integration von SMOTE für Oversampling

SMOTE (Synthetic Minority Oversampling Technique) erstellt synthetische Samples für die Minority Klasse. Verwenden Sie es mit imblearns Pipeline:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline as ImbPipeline
 
# Create imbalanced dataset
X, y = make_classification(
    n_samples=2000,
    n_features=20,
    weights=[0.95, 0.05],
    flip_y=0,
    random_state=42
)
 
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
 
# SMOTE + Random Forest pipeline
pipeline = ImbPipeline([
    ('smote', SMOTE(random_state=42)),
    ('rf', RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1))
])
pipeline.fit(X_train, y_train)
 
print("=== SMOTE + Random Forest ===")
print(classification_report(y_test, pipeline.predict(X_test)))

Model Evaluation

Classification Report und Confusion Matrix

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import (
    classification_report, confusion_matrix,
    ConfusionMatrixDisplay, accuracy_score
)
from sklearn.datasets import load_wine
import matplotlib.pyplot as plt
 
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    wine.data, wine.target, test_size=0.2, random_state=42, stratify=wine.target
)
 
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)
 
# Metrics
print(f"Accuracy: {accuracy_score(y_test, y_pred):.4f}")
print(f"\n{classification_report(y_test, y_pred, target_names=wine.target_names)}")
 
# Confusion matrix plot
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=wine.target_names)
disp.plot(cmap='Blues')
plt.title('Random Forest - Wine Classification')
plt.tight_layout()
plt.savefig('rf_confusion_matrix.png', dpi=150)
plt.show()

ROC Curve für Binary Classification

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, roc_auc_score, RocCurveDisplay
from sklearn.datasets import load_breast_cancer
import matplotlib.pyplot as plt
 
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, test_size=0.2, random_state=42, stratify=cancer.target
)
 
rf = RandomForestClassifier(n_estimators=200, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train)
 
# Predict probabilities
y_prob = rf.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_prob)
 
# Plot ROC curve
RocCurveDisplay.from_estimator(rf, X_test, y_test)
plt.title(f'Random Forest ROC Curve (AUC = {auc:.4f})')
plt.tight_layout()
plt.savefig('rf_roc_curve.png', dpi=150)
plt.show()

Random Forest vs Other Algorithms

FeatureRandom ForestXGBoostGradient BoostingDecision Tree
Ensemble TypeBagging (parallel)Boosting (sequential)Boosting (sequential)Single model
AccuracyHochSehr HochSehr HochModerat
Training SpeedSchnell (parallelisierbar)ModeratLangsam (sequential)Sehr Schnell
Prediction SpeedModeratSchnellModeratSehr Schnell
Overfitting RiskNiedrigNiedrig (mit Tuning)Niedrig (mit Tuning)Hoch
Hyperparameter SensitivityNiedrigHochHochModerat
Feature Scaling RequiredNeinNeinNeinNein
Handles Missing ValuesNein (benötigt Imputation)Ja (eingebaut)Nein (benötigt Imputation)Nein
Built-in Feature ImportanceJaJaJaJa
InterpretabilityModeratNiedrigNiedrigHoch
Best ForGeneral-purpose, erstes ModellKaggle competitions, maximale AccuracyStrukturierte tabellarische DatenQuick Baselines, kleine Datasets

Wann Random Forest gegenüber Alternativen wählen:

  • Sie benötigen ein starkes Baseline Modell mit minimalem Tuning
  • Training Speed ist wichtig und Sie haben multiple CPU Cores
  • Sie wollen zuverlässige Feature Importance Estimates
  • Sie jagen nicht die letzten 0.5% Accuracy, die Boosting Methoden bieten könnten

Real-World Pipeline: End-to-End Beispiel

Diese Pipeline kombiniert Preprocessing, Feature Engineering, Model Training, Evaluation und Prediction in einem Production-style Workflow:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.datasets import load_breast_cancer
import numpy as np
import pandas as pd
 
# Load and prepare data
cancer = load_breast_cancer()
df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
df['target'] = cancer.target
 
# Introduce some missing values to simulate real data
np.random.seed(42)
mask = np.random.random(df.shape) < 0.05
df_missing = df.mask(mask.astype(bool))
df_missing['target'] = cancer.target  # Keep target clean
 
X = df_missing.drop('target', axis=1)
y = df_missing['target']
 
# Split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
 
# Build preprocessing + model pipeline
numeric_features = X.columns.tolist()
numeric_transformer = Pipeline([
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler()),
])
 
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, numeric_features),
    ]
)
 
pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(
        n_estimators=300,
        max_depth=20,
        min_samples_leaf=2,
        class_weight='balanced',
        random_state=42,
        n_jobs=-1
    ))
])
 
# Cross-validation
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
cv_scores = cross_val_score(pipeline, X_train, y_train, cv=skf, scoring='accuracy')
print(f"Cross-validation accuracy: {cv_scores.mean():.4f} (+/- {cv_scores.std():.4f})")
 
# Train final model
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
 
# Evaluation
print(f"\nTest Set Results:")
print(classification_report(y_test, y_pred, target_names=cancer.target_names))
 
# Make predictions on new data
sample = X_test.iloc[:3]
predictions = pipeline.predict(sample)
probabilities = pipeline.predict_proba(sample)
 
print(f"\nSample Predictions:")
for i, (pred, prob) in enumerate(zip(predictions, probabilities)):
    class_name = cancer.target_names[pred]
    confidence = prob[pred]
    print(f"  Sample {i+1}: {class_name} (confidence: {confidence:.2%})")

Modell speichern und laden

import joblib
 
# Save the trained pipeline
joblib.dump(pipeline, 'rf_pipeline.joblib')
 
# Load and use later
loaded_pipeline = joblib.load('rf_pipeline.joblib')
new_predictions = loaded_pipeline.predict(X_test[:5])
print(f"Loaded model predictions: {new_predictions}")

Ergebnisse mit PyGWalker erkunden

Nach dem Training Ihres Random Forest Modells müssen Sie oft Feature Importance Patterns, Prediction Distributions und Misclassification Fälle im Detail erkunden. PyGWalker (opens in a new tab) lässt Sie Ihren Results DataFrame direkt in eine interaktive Tableau-ähnliche Exploration Interface in Jupyter verwandeln:

import pandas as pd
import pygwalker as pyg
 
# Build a results DataFrame
results = pd.DataFrame(X_test.values, columns=cancer.feature_names)
results['actual'] = y_test.values
results['predicted'] = y_pred
results['correct'] = y_test.values == y_pred
results['prob_malignant'] = pipeline.predict_proba(X_test)[:, 0]
results['prob_benign'] = pipeline.predict_proba(X_test)[:, 1]
 
# Launch interactive exploration
walker = pyg.walk(results)

Ziehen Sie Features auf Achsen, filtern Sie nach misclassified Samples und färben Sie nach Prediction Confidence, um zu identifizieren, wo das Modell Schwierigkeiten hat. Diese Art von visueller Analyse hilft Ihnen zu entscheiden, welche Features Sie engineeren oder welche Samples eine genauere Untersuchung benötigen.

Für das Ausführen Ihres vollständigen ML Experimentation Workflows – vom Data Loading über Model Comparison bis zur finalen Evaluation – bietet RunCell (opens in a new tab) eine AI-powered Jupyter Umgebung, die Ihnen hilft, schneller auf Experimenten zu iterieren, Evaluation Code auto-zu-generieren und Ihren Notebook Workflow zu managen.

FAQ

Wie viele Trees sollte ich in einem Random Forest verwenden?

Beginnen Sie mit 100-200 Trees. Die Accuracy verbessert sich normalerweise mit mehr Trees, flacht aber nach einem bestimmten Punkt ab. Verwenden Sie Cross-Validation, um den Sweet Spot zu finden. Über 500 Trees hinaus sind die Gewinne normalerweise vernachlässigbar, während die Training Time zunimmt. Überwachen Sie den OOB Score, während Sie n_estimators erhöhen – wenn er nicht mehr verbessert, haben Sie genug Trees.

Benötigt Random Forest Feature Scaling?

Nein. Random Forest macht Splits basierend auf Feature Value Thresholds, daher beeinflusst die absolute Skala der Features nicht die Splitting Decisions. Im Gegensatz zu Logistic Regression, SVM oder Neural Networks handhabt Random Forest Features mit unterschiedlichen Ranges natürlich. Skalieren Sie nur, wenn Ihre Pipeline andere Komponenten enthält (wie PCA oder distance-based Preprocessing), die es erfordern.

Wie handhabt Random Forest fehlende Werte?

Scikit-learns RandomForestClassifier und RandomForestRegressor handhaben fehlende Werte nicht nativ. Sie müssen fehlende Daten vor dem Training imputieren – verwenden Sie SimpleImputer mit Median oder Mean Strategy für numerische Features, oder verwenden Sie fortgeschrittenere Imputation Methods wie IterativeImputer. Einige andere Implementierungen wie H2O oder LightGBM können fehlende Werte direkt handhaben.

Was ist der Unterschied zwischen Random Forest und Gradient Boosting?

Random Forest baut Trees unabhängig parallel (Bagging), während Gradient Boosting Trees sequentiell baut, wo jeder Tree die Fehler des vorherigen korrigiert (Boosting). Random Forest reduziert Variance, Gradient Boosting reduziert Bias. In der Praxis erreicht Gradient Boosting (besonders XGBoost) oft eine leicht höhere Accuracy, aber Random Forest ist einfacher zu tunen und weniger anfällig für Overfitting.

Kann Random Forest für Feature Selection verwendet werden?

Ja. Verwenden Sie feature_importances_ für ein schnelles Ranking oder permutation_importance für einen zuverlässigeren Estimate. Sie können dann low-importance Features droppen und retrainen. Alternativ verwenden Sie SelectFromModel mit einem Random Forest Estimator innerhalb einer Pipeline, um automatisch Features über einem Threshold zu selektieren.

Fazit

Random Forest ist einer der zuverlässigsten und vielseitigsten Algorithmen im Machine Learning. Es reduziert Overfitting durch die Kombination hunderter dekorellierter Decision Trees, handhabt sowohl Classification als auch Regression Tasks ohne Feature Scaling, und bietet eingebaute Feature Importance Rankings. Für die meisten tabellarischen Daten Probleme dient es als exzellentes erstes Modell, das oft gut genug für Production Use performt.

Beginnen Sie mit RandomForestClassifier oder RandomForestRegressor mit Default Parameters als Ihr Baseline. Tunen Sie n_estimators zuerst für Diminishing-Returns Analyse, dann max_depth und min_samples_leaf, um Overfitting zu kontrollieren. Verwenden Sie class_weight='balanced' für Imbalanced Data, Permutation Importance für zuverlässige Feature Rankings, und StratifiedKFold Cross-Validation für robuste Evaluation. Wenn Sie die absolute höchste Accuracy auf strukturierten Daten benötigen, erwägen Sie Gradient Boosting oder XGBoost, aber Random Forest bleibt die sicherste Default Choice, die selten schlecht versagt.

📚