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):
- Bootstrap Sampling: Erstellen Sie multiple zufällige Subsets der Trainingsdaten durch Sampling mit Zurücklegen. Jedes Subset ist ungefähr 63% der originalen Daten.
- 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/3für Regression). - Independent Training: Trainieren Sie einen Decision Tree auf jedem Bootstrap Sample mit der Random Feature Constraint.
- 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
| Szenario | Random Forest? | Warum |
|---|---|---|
| Tabellarische Daten mit gemischten Feature-Typen | Ja | Handhabt numerische und kategorische Features, kein Scaling nötig |
| Sie benötigen Feature Importance Rankings | Ja | Eingebautes feature_importances_ Attribut |
| Small to Medium Datasets (bis ~100K Zeilen) | Ja | Schnelles Training mit paralleler Verarbeitung |
| Imbalanced Classification | Ja | Unterstützt class_weight='balanced' |
| Sie benötigen interpretierbare Predictions | Moderat | Individuelle Trees sind interpretierbar, aber das Ensemble weniger |
| Sehr hochdimensionale Sparse Data (Text) | Nein | Lineare Models oder Gradient Boosting sind typischerweise besser |
| Real-time Inference mit strikter Latency | Vorsicht | Groß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
| Parameter | Default | Beschreibung | Tuning Tipp |
|---|---|---|---|
n_estimators | 100 | Anzahl der Trees im Forest | Mehr Trees = bessere Performance aber langsamer. 100-500 ist typisch. |
max_depth | None | Maximale Tiefe jedes Trees | None bedeutet vollständig gewachsen. Setzen Sie auf 10-30, um Overfitting zu reduzieren. |
min_samples_split | 2 | Minimale Samples zum Splitten eines Nodes | Erhöhen auf 5-20, um Overfitting auf noisy Daten zu verhindern. |
min_samples_leaf | 1 | Minimale Samples in einem Leaf Node | Erhö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. |
bootstrap | True | Bootstrap Sampling verwenden | Auf False setzen für kleine Datasets, um alle Daten pro Tree zu verwenden. |
class_weight | None | Gewichte für jede Klasse | 'balanced' für Imbalanced Datasets verwenden. |
n_jobs | None | Anzahl der parallelen Jobs | Auf -1 setzen, um alle CPU Cores zu verwenden. |
oob_score | False | Out-of-Bag Samples für Evaluation verwenden | Auf 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:
| Parameter | Impact | Priorität | Notizen |
|---|---|---|---|
n_estimators | Hoch | 1. | Mehr Trees hilft fast immer, bis zu diminishing returns (~200-500) |
max_depth | Hoch | 2. | Kontrolliert Overfitting direkt. Versuchen Sie None, 10, 20, 30 |
min_samples_leaf | Mittel | 3. | Glättet Predictions. Versuchen Sie 1, 2, 5, 10 |
max_features | Mittel | 4. | Kontrolliert Tree Diversity. 'sqrt' ist normalerweise gut für Classification |
min_samples_split | Niedrig | 5. | Weniger Impact als min_samples_leaf in der Praxis |
bootstrap | Niedrig | 6. | 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?
| Methode | Pros | Cons | Best für |
|---|---|---|---|
Impurity-based (feature_importances_) | Schnell, keine extra Berechnung | Biased gegenüber High-Cardinality Features | Quick screening, initiale Exploration |
| Permutation Importance | Unbiased, funktioniert auf Testdaten | Langsamer, beeinflusst von korrelierten Features | Finale 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
| Feature | Random Forest | XGBoost | Gradient Boosting | Decision Tree |
|---|---|---|---|---|
| Ensemble Type | Bagging (parallel) | Boosting (sequential) | Boosting (sequential) | Single model |
| Accuracy | Hoch | Sehr Hoch | Sehr Hoch | Moderat |
| Training Speed | Schnell (parallelisierbar) | Moderat | Langsam (sequential) | Sehr Schnell |
| Prediction Speed | Moderat | Schnell | Moderat | Sehr Schnell |
| Overfitting Risk | Niedrig | Niedrig (mit Tuning) | Niedrig (mit Tuning) | Hoch |
| Hyperparameter Sensitivity | Niedrig | Hoch | Hoch | Moderat |
| Feature Scaling Required | Nein | Nein | Nein | Nein |
| Handles Missing Values | Nein (benötigt Imputation) | Ja (eingebaut) | Nein (benötigt Imputation) | Nein |
| Built-in Feature Importance | Ja | Ja | Ja | Ja |
| Interpretability | Moderat | Niedrig | Niedrig | Hoch |
| Best For | General-purpose, erstes Modell | Kaggle competitions, maximale Accuracy | Strukturierte tabellarische Daten | Quick 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.