W3docs

Machine Learning mit logistischer Regression in Python

Lernen Sie, wie logistische Regression funktioniert, wie Sie binäre und Mehrklassen-Klassifikatoren in Python mit scikit-learn trainieren und evaluieren.

Logistische Regression ist ein überwachter Klassifikationsalgorithmus, der die Wahrscheinlichkeit schätzt, dass eine Stichprobe zu einer bestimmten Klasse gehört. Trotz des Begriffs „Regression" im Namen wird sie für Klassifikationsaufgaben verwendet – zur Vorhersage eines kategorialen Labels wie Spam/kein Spam, Krankheit/gesund oder Klick/kein Klick.

Dieses Kapitel behandelt:

  • Wie logistische Regression funktioniert (die Sigmoid-Funktion und Log-Odds)
  • Aufbau eines binären Klassifikators in Python mit scikit-learn
  • Bewertung eines Klassifikators jenseits der reinen Genauigkeit
  • Umgang mit Mehrklassen-Problemen
  • Regularisierung und wann sie angepasst werden sollte
  • Feature-Skalierung und warum sie wichtig ist
  • Wann logistische Regression gegenüber anderen Klassifikatoren zu bevorzugen ist

So funktioniert logistische Regression

Von linearer Regression zu Wahrscheinlichkeiten

Lineare Regression sagt einen kontinuierlichen Wert vorher. Würde man sie für Klassifikation verwenden, könnten die Vorhersagen außerhalb von [0, 1] liegen und wären als Wahrscheinlichkeiten nicht interpretierbar. Logistische Regression löst dieses Problem, indem die lineare Kombination durch die Sigmoid-Funktion geleitet wird:

σ(z) = 1 / (1 + e^(-z))

Dabei ist z = w₀ + w₁x₁ + w₂x₂ + … + wₙxₙ die gewichtete Summe der Eingabe-Features. Die Sigmoid-Funktion quetscht jede reelle Zahl in den Bereich (0, 1) und liefert so eine gültige Wahrscheinlichkeitsschätzung.

Entscheidungsgrenze

Das Modell sagt Klasse 1 vorher, wenn die Wahrscheinlichkeit einen Schwellenwert (Standard 0,5) überschreitet, andernfalls Klasse 0:

ŷ = 1  if σ(z) ≥ 0.5
ŷ = 0  if σ(z) < 0.5

Der Schwellenwert σ(z) = 0.5 entspricht z = 0, der die Entscheidungsgrenze definiert – eine Hyperebene im Feature-Raum, die die beiden Klassen trennt.

Log-Odds (Logit)

Der Logarithmus des Quotenverhältnisses zeigt, warum das Modell in den Parametern linear ist:

log(p / (1 - p)) = w₀ + w₁x₁ + … + wₙxₙ

Jeder Koeffizient wᵢ gibt die Änderung der Log-Odds für eine Einheitserhöhung in Feature xᵢ an, wenn alle anderen Features konstant gehalten werden. Das macht die logistische Regression interpretierbar.

Wie Parameter gelernt werden

Anders als bei der linearen Regression gibt es keine geschlossene Lösung. Das Modell minimiert die Log-Loss-Kostenfunktion (Kreuzentropie) mit einem iterativen Optimierer (standardmäßig lbfgs in scikit-learn):

Loss = -1/m Σ [ yᵢ log(p̂ᵢ) + (1 - yᵢ) log(1 - p̂ᵢ) ]

Ein niedrigerer Log-Loss bedeutet, dass die vorhergesagten Wahrscheinlichkeiten besser auf die tatsächlichen Labels kalibriert sind.

Binäre Klassifikation in Python

Das folgende Beispiel verwendet den Breast-Cancer-Wisconsin-Datensatz – 569 Stichproben, 30 numerische Features, binäres Ziel (bösartig = 1, gutartig = 0). Er ist in scikit-learn enthalten, sodass keine externen Dateien benötigt werden.

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report

# 1. Load data
data = load_breast_cancer()
X, y = data.data, data.target           # X: (569, 30)  y: 0=malignant, 1=benign

# 2. Split into train (80 %) and test (20 %)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 3. Scale features — logistic regression converges faster and more reliably
#    when features are on a similar scale
scaler = StandardScaler()
X_train_sc = scaler.fit_transform(X_train)
X_test_sc  = scaler.transform(X_test)

# 4. Train
clf = LogisticRegression(max_iter=1000, random_state=42)
clf.fit(X_train_sc, y_train)

# 5. Evaluate
y_pred = clf.predict(X_test_sc)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(classification_report(y_test, y_pred, target_names=data.target_names))

Erwartete Ausgabe:

Accuracy: 0.974
              precision    recall  f1-score   support

   malignant       0.98      0.95      0.96        43
      benign       0.97      0.99      0.98        71

    accuracy                           0.97       114
   macro avg       0.97      0.97      0.97       114
weighted avg       0.97      0.97      0.97       114

Das Modell erreicht ~97 % Genauigkeit auf den zurückgehaltenen Daten. Beachten Sie, dass scikit-learns LogisticRegression standardmäßig L2-Regularisierung hinzufügt (C=1.0), was die Generalisierung verbessert.

Warum Feature-Skalierung wichtig ist

Logistische Regression verwendet gradientenbasierte Optimierung. Ohne Skalierung dominiert ein Feature mit großen Werten (z. B. mittlerer Radius ~14) die Gradientenaktualisierungen, verlangsamt die Konvergenz oder lässt den Solver versagen. StandardScaler transformiert jedes Feature auf null Mittelwert und Einheitsvarianz.

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Without scaling — needs more iterations, may warn about convergence
clf_raw = LogisticRegression(max_iter=200, random_state=42)
clf_raw.fit(X_train, y_train)
print(f"Unscaled accuracy : {clf_raw.score(X_test, y_test):.3f}")

# With scaling
scaler = StandardScaler()
clf_sc = LogisticRegression(max_iter=200, random_state=42)
clf_sc.fit(scaler.fit_transform(X_train), y_train)
print(f"Scaled accuracy   : {clf_sc.score(scaler.transform(X_test), y_test):.3f}")

Passen Sie den Scaler immer nur auf den Trainingsdatensatz an und verwenden Sie denselben angepassten Scaler zum Transformieren von Trainings- und Testdaten – das verhindert Datenlecks.

Bewertung eines Klassifikators

Genauigkeit allein kann irreführend sein, wenn die Klassen unausgewogen sind. Verwenden Sie eine Konfusionsmatrix und die daraus abgeleiteten Metriken.

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
X_train_sc = scaler.fit_transform(X_train)
X_test_sc  = scaler.transform(X_test)

clf = LogisticRegression(max_iter=1000, random_state=42)
clf.fit(X_train_sc, y_train)
y_pred = clf.predict(X_test_sc)

cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(cm, display_labels=data.target_names)
disp.plot(cmap="Blues")
plt.title("Logistic Regression — Breast Cancer")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

Wichtige Metriken aus der Konfusionsmatrix:

MetrikFormelBedeutung
PräzisionTP / (TP + FP)Von allen vorhergesagten Positiven, wie viele sind wirklich positiv
Recall (Sensitivität)TP / (TP + FN)Von allen tatsächlichen Positiven, wie viele hat das Modell erkannt
F1-Score2 × (P × R) / (P + R)Harmonisches Mittel aus Präzision und Recall
SpezifitätTN / (TN + FP)Von allen tatsächlichen Negativen, wie viele hat das Modell korrekt abgelehnt

Bei der medizinischen Diagnose ist der Recall (Sensitivität) oft wichtiger als die Präzision – ein übersehener bösartiger Befund ist schlimmer als ein falscher Alarm.

Wahrscheinlichkeits-Scores und die AUC-ROC-Kurve

Anstelle einer harten Vorhersage kann die Wahrscheinlichkeit der positiven Klasse mit predict_proba() abgerufen werden:

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_auc_score

data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
clf = LogisticRegression(max_iter=1000, random_state=42)
clf.fit(scaler.fit_transform(X_train), y_train)

# Probability of the positive class (benign = 1)
y_proba = clf.predict_proba(scaler.transform(X_test))[:, 1]
print(f"AUC-ROC: {roc_auc_score(y_test, y_proba):.3f}")

Erwartete Ausgabe:

AUC-ROC: 0.997

Ein AUC-Wert nahe 1,0 bedeutet, dass das Modell positive Stichproben fast perfekt über negative einordnet. Im Kapitel zur AUC-ROC-Kurve erfahren Sie, wie die vollständige Kurve gezeichnet und interpretiert wird.

Mehrklassen-Klassifikation

Wenn das Ziel mehr als zwei Klassen hat, erweitert scikit-learn die logistische Regression automatisch. Ab scikit-learn 1.5 verwendet der lbfgs-Solver immer den Multinomial-(Softmax-)Ansatz, der ein einzelnes Modell mit einer Softmax-Ausgabeschicht trainiert und die Kreuzentropie über alle Klassen gemeinsam minimiert. Dies ist im Allgemeinen genauer als die ältere One-vs-Rest-(OvR-)Strategie, die einen separaten binären Klassifikator pro Klasse trainierte.

Der Iris-Datensatz enthält drei Blumenarten – ein natürliches Mehrklassen-Beispiel:

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score

data = load_iris()
X, y = data.data, data.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
X_train_sc = scaler.fit_transform(X_train)
X_test_sc  = scaler.transform(X_test)

# From scikit-learn 1.5+, multinomial softmax is the default for lbfgs
clf = LogisticRegression(solver="lbfgs", max_iter=1000, random_state=42)
clf.fit(X_train_sc, y_train)

y_pred = clf.predict(X_test_sc)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")

# Class probabilities for the first three test samples
print("\nClass probabilities (first 3 samples):")
for proba in clf.predict_proba(X_test_sc)[:3]:
    print([f"{p:.3f}" for p in proba])

Erwartete Ausgabe:

Accuracy: 1.000

Class probabilities (first 3 samples):
['0.011', '0.876', '0.113']
['0.964', '0.036', '0.000']
['0.000', '0.003', '0.997']

Regularisierung

Regularisierung bestraft große Koeffizienten, um Overfitting zu verhindern. scikit-learn bietet zwei Typen über den Parameter penalty:

ParameterTypAuswirkung
penalty='l2' (Standard)RidgeSchrumpft alle Koeffizienten gegen null; behält alle Features
penalty='l1'LassoTreibt einige Koeffizienten genau auf null; implizite Feature-Selektion
penalty='elasticnet'MixKombiniert L1 und L2; erfordert solver='saga'
penalty=NoneKeineKeine Regularisierung; nur verwenden, wenn die Daten groß und sauber sind

Die Stärke der Regularisierung wird durch C gesteuert (der Kehrwert der Regularisierungsstärke – kleineres C bedeutet stärkere Regularisierung):

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import numpy as np

data = load_breast_cancer()
X, y = data.data, data.target

results = {}
for C in [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]:
    pipe = Pipeline([
        ("scaler", StandardScaler()),
        ("clf", LogisticRegression(C=C, max_iter=1000, random_state=42)),
    ])
    scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
    results[C] = scores.mean()
    print(f"C={C:7.3f}  CV accuracy: {scores.mean():.4f} ± {scores.std():.4f}")

Dabei wird Kreuzvalidierung verwendet, um den C-Wert zu finden, der am besten generalisiert. Für eine systematische Suche über mehrere Hyperparameter siehe Grid Search.

Verwendung einer Pipeline

Eine Pipeline verbindet die Vorverarbeitung und das Modell zu einem einzigen Objekt. Das verhindert versehentliche Datenlecks und vereinfacht Kreuzvalidierung und Deployment:

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score

data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("clf", LogisticRegression(C=1.0, max_iter=1000, random_state=42)),
])

pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")

# Predict probabilities on a new sample (raw, unscaled)
new_sample = X_test[:1]  # first test sample
print(f"Predicted class   : {pipe.predict(new_sample)[0]}")
print(f"Class probability : {pipe.predict_proba(new_sample)[0]}")

Erwartete Ausgabe:

Accuracy: 0.974
Predicted class   : 1
Class probability : [0.11359025 0.88640975]

Die Pipeline übernimmt die Skalierung intern – Sie rufen predict() mit rohen Feature-Werten auf.

Koeffizienten inspizieren

Die trainierten Koeffizienten zeigen, welche Features die Vorhersage in Richtung jeder Klasse treiben. Größere absolute Werte bedeuten einen stärkeren Einfluss:

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
import numpy as np

data = load_breast_cancer()
X, y = data.data, data.target

scaler = StandardScaler()
clf = LogisticRegression(max_iter=1000, random_state=42)
clf.fit(scaler.fit_transform(X), y)

# Sort by absolute coefficient value
coefs = clf.coef_[0]          # shape (n_features,) for binary classification
sorted_idx = np.argsort(np.abs(coefs))[::-1]

print(f"{'Feature':<35} {'Coefficient':>12}")
print("-" * 48)
for i in sorted_idx[:5]:
    print(f"{data.feature_names[i]:<35} {coefs[i]:>12.4f}")

Erwartete Ausgabe (Top-5-Features nach absolutem Gewicht):

Feature                              Coefficient
------------------------------------------------
worst texture                            -1.3206
radius error                             -1.2893
worst radius                             -1.0266
area error                               -0.9989
worst area                               -0.9947

Negative Koeffizienten (nach Skalierung) treiben in Richtung Klasse 0 (bösartig); positive Koeffizienten treiben in Richtung Klasse 1 (gutartig).

Vorteile und Einschränkungen

Wann logistische Regression verwendet werden sollte

  • Sie benötigen Wahrscheinlichkeitsschätzungen, nicht nur Klassen-Labels.
  • Die Beziehung zwischen Features und den Log-Odds ist annähernd linear.
  • Sie benötigen ein interpretierbares Modell – Koeffizienten sind aussagekräftig.
  • Als schnelle Basislinie, bevor komplexere Modelle wie Entscheidungsbäume oder Ensemble-Methoden ausprobiert werden.
  • Datensätze sind groß (logistische Regression skaliert gut mit vielen Stichproben).

Einschränkungen

EinschränkungAbhilfemaßnahme
Setzt eine lineare Entscheidungsgrenze vorausVerwenden Sie Polynomfeatures oder wechseln Sie zu Entscheidungsbaum / K-Nearest Neighbors
Empfindlich gegenüber Feature-SkalierungWenden Sie immer StandardScaler oder MinMaxScaler an
Probleme bei stark korrelierten FeaturesEntfernen oder regularisieren Sie mit L1 (penalty='l1')
Nicht geeignet für sehr komplexe Feature-InteraktionenVerwenden Sie Ensemble-Methoden oder neuronale Netze

Logistische Regression vs. verwandte Klassifikatoren

AlgorithmusEntscheidungsgrenzeSkalierung erforderlichProbabilistische Ausgabe
Logistische RegressionLinearJaJa (kalibriert)
EntscheidungsbaumNichtlinear (achsenausgerichtet)NeinJa (weniger kalibriert)
K-Nearest NeighborsNichtlinear (instanzbasiert)JaJa
Lineare RegressionLinear (kontinuierliche Ausgabe)JaNein

Wichtigste Erkenntnisse

  • Logistische Regression schätzt eine Wahrscheinlichkeit mithilfe der Sigmoid-Funktion; die Klasse wird durch Schwellenwertbildung dieser Wahrscheinlichkeit zugewiesen.
  • Skalieren Sie Features immer mit StandardScaler vor dem Training – es beschleunigt die Konvergenz und verbessert die Genauigkeit.
  • Verwenden Sie eine Pipeline, um Skalierung und Modell zu bündeln; sie verhindert Datenlecks und vereinfacht das Deployment.
  • Bewerten Sie mit Präzision, Recall, F1 und AUC-ROC statt nur mit Genauigkeit, besonders bei unausgewogenen Daten. Siehe die Kapitel zur Konfusionsmatrix und AUC-ROC-Kurve.
  • Kontrollieren Sie Overfitting mit dem Parameter C (kleiner = stärkere Regularisierung); verwenden Sie Kreuzvalidierung oder Grid Search zur Abstimmung.
  • Für Mehrklassen-Probleme verwenden Sie solver="lbfgs" (Standard); scikit-learn 1.5+ verwendet immer Softmax (multinomial), das überlappende Klassen gut behandelt.
Was this page helpful?