Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert
Lernende unterscheiden Data Drift und Concept Drift anhand eines Zeitreihenbeispiels und verstehen, warum Data Drift nicht immer eine Verschlechterung der Modellleistung bedeutet.
Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert ist eine kostenlose Machine Learning Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Machine Learning Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Machine Learning Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist Concept Drift?
Concept Drift tritt auf, wenn sich die Beziehung zwischen den Eingabemerkmalen X und der Zielvariable Y im Laufe der Zeit verändert, selbst wenn die Merkmalsverteilungen unverändert bleiben. Bei der Betrugserkennung lernen Betrüger, welche Transaktionen markiert werden, und ändern ihre Muster. Dadurch wirken Transaktionen, die 2022 betrügerisch aussahen, im Jahr 2024 unauffällig. Das erlernte Konzept – also wie Betrug aussieht – hat sich verändert, während die Merkmalsverteilungen unverändert erscheinen können. Dadurch ist Concept Drift schwerer zu erkennen als Data Drift.
Data Drift vs. Concept Drift: der entscheidende Unterschied
Der entscheidende Unterschied: Data Drift ist eine Veränderung von P(X), also der Verteilung der Eingabemerkmale. Concept Drift ist eine Veränderung von P(Y|X), also der bedingten Beziehung zwischen Merkmalen und Labels. Data Drift verschlechtert die Modellleistung nicht immer, wenn die neue Verteilung weiterhin innerhalb der erlernten Entscheidungsgrenze liegt. Concept Drift verschlechtert die Leistung immer, weil die vom Modell erlernte Abbildung von X auf Y nun unabhängig davon falsch ist, ob X unverändert aussieht.
import numpy as np
import pandas as pd
# Scenario: credit scoring model
# Feature: income. Label: 1 = defaults, 0 = repays
# Training period: incomes 30-50k correlate with defaults
np.random.seed(42)
train_income = np.random.normal(40000, 8000, 1000)
train_default = (train_income < 35000).astype(int) # low income -> default
# Concept drift: inflation shifts threshold; now defaults start at 50k
prod_income = np.random.normal(40000, 8000, 500) # SAME distribution (no data drift)
prod_default = (prod_income < 50000).astype(int) # new relationship
print('Train default rate:', train_default.mean().round(3))
print('Prod default rate:', prod_default.mean().round(3))
print('Feature distribution same (no data drift).',
'But Y|X relationship has changed (concept drift).')Arten von Concept Drift
Concept Drift tritt in vier Formen auf. Plötzlicher Drift: Die Beziehung ändert sich abrupt, beispielsweise durch COVID-19, das Konsummuster über Nacht verändert. Allmählicher Drift: Das alte Konzept verliert langsam an Bedeutung und ein neues entsteht, beispielsweise durch eine sich über Monate verändernde Definition von Spam. Inkrementeller Drift: Eine kontinuierliche, langsame Verschiebung ohne klaren Wendepunkt. Wiederkehrender Drift: Saisonale Muster – die Beziehung an Weihnachten unterscheidet sich von der im Juli, kehrt im Juli aber schließlich wieder zurück.
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(0, 100, 1000)
# Sudden drift: step function at t=50
sudden = np.where(t < 50, 0.8, 0.3) # accuracy drops at t=50
# Gradual drift: linear transition
gradual = np.where(t < 40, 0.8,
np.where(t > 60, 0.4,
0.8 - (t - 40) * 0.02))
# Recurring drift: seasonal pattern
recurring = 0.6 + 0.2 * np.sin(2 * np.pi * t / 20)
for name, series in [('Sudden', sudden), ('Gradual', gradual), ('Recurring', recurring)]:
print(f'{name} drift -- min acc: {series.min():.2f}, max: {series.max():.2f}')Concept Drift durch Performance-Monitoring erkennen
Das zuverlässigste Signal für Concept Drift ist eine sinkende Modellleistung bei gelabelten Produktionsdaten. Verfolgen Sie Ihre gewählte Kennzahl (Accuracy, F1, AUC) über ein gleitendes Fenster aktueller Vorhersagen, für die inzwischen Ground-Truth-Labels verfügbar sind. Ein sinkender Leistungstrend, der nicht durch Data Drift erklärt wird (die Merkmale sehen unverändert aus), ist ein starker Hinweis auf Concept Drift. Dafür benötigen Sie eine Feedbackschleife: Sie müssen die tatsächlichen Labels für Produktionsvorhersagen erfassen, was je nach Aufgabe Tage bis Monate dauern kann.
import numpy as np
import pandas as pd
np.random.seed(42)
# Simulate weekly model accuracy tracking
weekly_accuracy = [
0.92, 0.91, 0.90, 0.89, 0.88, # slight decline
0.86, 0.83, 0.79, 0.74, 0.68, # accelerating decline = concept drift
0.65, 0.61
]
df = pd.DataFrame({'week': range(1, 13), 'accuracy': weekly_accuracy})
df['rolling_mean'] = df['accuracy'].rolling(3).mean()
df['alert'] = df['accuracy'] < 0.75 # threshold
print(df.to_string(index=False))
print('Weeks with alerts:', df[df['alert']]['week'].tolist())Concept Drift ohne Labels erkennen
Auf Ground-Truth-Labels zu warten, dauert lange. Wenn Labels erst mit großer Verzögerung eintreffen, können Sie das Monitoring der Vorhersageverteilung als Frühwarnsignal verwenden. Wenn P(X) stabil ist (kein Data Drift), sich die Verteilung der vom Modell vorhergesagten Labels aber deutlich verschiebt, deutet dies darauf hin, dass sich das zugrunde liegende Konzept verändert hat. Wenn beispielsweise die Rate positiver Vorhersagen eines binären Klassifikators ohne Veränderung der Merkmalsverteilungen von 30 % auf 5 % sinkt, sieht das Modell wahrscheinlich eine andere Beziehung zwischen den Merkmalen und der positiven Klasse.
import numpy as np
# Monitoring prediction distributions as a proxy for concept drift
# Period 1 (training distribution): ~30% positive predictions
period1_probs = np.random.beta(2, 5, 1000) # right-skewed, ~30% above 0.5
period1_pos_rate = (period1_probs > 0.5).mean()
# Period 2 (concept drifted): only ~5% positive predictions (model confused)
period2_probs = np.random.beta(1, 15, 500) # very right-skewed
period2_pos_rate = (period2_probs > 0.5).mean()
print(f'Period 1 positive rate: {period1_pos_rate:.2%}')
print(f'Period 2 positive rate: {period2_pos_rate:.2%}')
print(f'Rate drop: {(period1_pos_rate - period2_pos_rate):.2%}')
print('Possible concept drift detected!')Erneutes Training mit Datenfenstern: Anpassung an Concept Drift
Die häufigste Strategie zum Umgang mit Concept Drift ist das erneute Training mit Datenfenstern: Trainieren Sie das Modell regelmäßig nur mit den aktuellsten N Beispielen und verwerfen Sie ältere Daten, die veraltete Muster widerspiegeln. Ein gleitendes Fenster enthält die aktuellsten N Beispiele; ein expandierendes Fenster verwendet alle Daten mit einer Gewichtung nach Aktualität. Die optimale Fenstergröße hängt davon ab, wie schnell sich das Konzept entwickelt. Schnelllebige Bereiche wie Finanzmärkte benötigen kleinere Fenster als langsam veränderliche Bereiche wie Wettervorhersagen.
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
np.random.seed(42)
def simulate_concept_drift(n, t):
X = np.random.normal(0, 1, (n, 2))
# Decision boundary rotates over time
y = ((X[:, 0] * np.cos(t) - X[:, 1] * np.sin(t)) > 0).astype(int)
return X, y
# Full retrain vs sliding window retrain
for window_size in [100, 500, None]: # None = all data
all_X, all_y = [], []
accs = []
for t in np.linspace(0, np.pi, 10):
X, y = simulate_concept_drift(200, t)
all_X.append(X)
all_y.append(y)
if window_size:
train_X = np.vstack(all_X[-window_size//200:])
train_y = np.hstack(all_y[-window_size//200:])
else:
train_X = np.vstack(all_X)
train_y = np.hstack(all_y)
clf = LogisticRegression().fit(train_X, train_y)
accs.append(clf.score(X, y))
print(f'Window={window_size}: avg accuracy={np.mean(accs):.3f}')Beispielgewichtung: ältere Daten geringer gewichten
Statt Daten anhand einer festen Fenstergrenze abzuschneiden, weisen Sie Trainingsbeispielen exponentiell abnehmende Gewichte zu, sodass aktuelle Beispiele stärker zum Modell beitragen. Beispiele aus der vergangenen Woche erhalten das Gewicht 1,0, Beispiele aus dem vergangenen Monat 0,5 und Beispiele von vor sechs Monaten 0,1. Viele scikit-learn-Schätzer akzeptieren in ihrer fit-Methode den Parameter sample_weight. Dadurch lässt sich dieser Ansatz einfach umsetzen, ohne Daten zu verwerfen.
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
np.random.seed(42)
# Simulate 1000 training examples collected over 10 weeks
X = np.random.normal(0, 1, (1000, 5))
y = (X[:, 0] + np.random.normal(0, 0.5, 1000) > 0).astype(int)
weeks_ago = np.linspace(10, 0, 1000) # example 0 is oldest, 999 is newest
# Exponential decay: half-life of 3 weeks
half_life = 3.0
sample_weights = np.exp(-weeks_ago * np.log(2) / half_life)
sample_weights /= sample_weights.sum()
clf = GradientBoostingClassifier(n_estimators=100, random_state=42)
clf.fit(X, y, sample_weight=sample_weights * len(y)) # scale up
print('Model trained with recency-weighted samples.')
print('Weight ratio new/old:', round(sample_weights[-1] / sample_weights[0], 2))CUSUM- und ADWIN-Drift-Detektoren
Dedizierte Algorithmen zur Erkennung von Konzeptdrift liefern fundiertere Warnungen. CUSUM (Cumulative Sum) erkennt Änderungen im Mittelwert einer Sequenz, indem Abweichungen von einem Referenzwert kumuliert werden. ADWIN (Adaptive Windowing) verwaltet ein Fenster variabler Länge und verkleinert es, wenn ein statistischer Test eine Verteilungsänderung innerhalb des Fensters erkennt. Die Bibliothek river (früher scikit-multiflow) implementiert beide Verfahren für Streaming-Daten.
# Using the river library for streaming drift detection
# pip install river
# from river.drift import ADWIN
# adwin = ADWIN(delta=0.002) # delta controls sensitivity
# error_sequence = [0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1] # errors over time
#
# for i, error in enumerate(error_sequence):
# adwin.update(error)
# if adwin.drift_detected:
# print(f'ADWIN detected drift at step {i}')
# adwin = ADWIN(delta=0.002) # reset detector
# Manual CUSUM example:
def cusum(errors, threshold=5, drift=0.01):
cum_sum, alerts = 0, []
for i, e in enumerate(errors):
cum_sum = max(0, cum_sum + e - drift)
if cum_sum > threshold:
alerts.append(i)
cum_sum = 0
return alerts
errors = [0]*10 + [1]*15 # errors spike after step 10
print('CUSUM drift alerts at steps:', cusum(errors))Konzeptdrift vs. Saisonalität
Saisonalität bezeichnet vorhersehbare periodische Schwankungen (Spitzen bei Weihnachtseinkäufen, Reisemuster im Sommer), während Konzeptdrift eine unvorhersehbare Verschiebung in eine Richtung ist. Ein gutes Überwachungssystem unterscheidet beides, indem es historische saisonale Muster prüft. Wenn die aktuelle Verteilung der Verteilung desselben Zeitraums im vergangenen Jahr entspricht, handelt es sich wahrscheinlich um Saisonalität und nicht um Drift. Nehmen Sie Jahreszeitmerkmale in Ihr Modell auf, um vorhersehbare Saisonalität zu berücksichtigen, statt unnötiges erneutes Training auszulösen.
import numpy as np
from scipy.stats import ks_2samp
np.random.seed(42)
# Training: July 2023 data
july_2023 = np.random.normal(100, 20, 1000) # low activity (summer)
# Monitoring: July 2024 (seasonal -- same month last year)
july_2024 = np.random.normal(102, 21, 500) # similar to last July
# Monitoring: December 2024 (seasonal spike -- same as Dec 2023)
dec_2024 = np.random.normal(180, 30, 500) # high activity (Christmas)
stat_july, p_july = ks_2samp(july_2023, july_2024)
stat_dec, p_dec = ks_2samp(july_2023, dec_2024)
print(f'July 2024 vs July 2023: KS={stat_july:.3f} p={p_july:.3f} -> {"drift" if p_july < 0.05 else "seasonal OK"}')
print(f'Dec 2024 vs July 2023: KS={stat_dec:.3f} p={p_dec:.3f} -> Expected seasonal shift')Einen Reaktionsplan für Konzeptdrift erstellen
Reagieren Sie mit einem abgestuften Plan auf Konzeptdrift. Stufe 1 (Frühwarnung): Lösen Sie bei Verschiebungen der Vorhersageverteilung eine Warnung aus, ohne auf Labels zu warten. Stufe 2 (Bestätigung): Sobald Labels eintreffen, bestätigen Sie, dass die Leistungsverschlechterung relativ mehr als 5 % beträgt. Stufe 3 (Maßnahme): Lösen Sie ein automatisches erneutes Training mit Zeitfenster aus und verwenden Sie den Zeitstempel der Drifterkennung als Grenze des Fensters. Stufe 4 (Eskalation): Wenn das erneute Training die Leistung nicht wiederherstellt, eskalieren Sie den Fall zur Überprüfung des Feature Engineerings an eine Data-Science-Fachkraft.
def concept_drift_response(current_accuracy, baseline_accuracy,
data_drift_detected, prediction_rate_shift):
relative_drop = (baseline_accuracy - current_accuracy) / baseline_accuracy
if relative_drop > 0.10:
return ('TIER 4 ESCALATION: >10% accuracy drop. '
'Manual feature engineering review required.')
elif relative_drop > 0.05:
return ('TIER 3 ACTION: 5-10% accuracy drop. '
'Trigger windowed retraining immediately.')
elif data_drift_detected or prediction_rate_shift > 0.15:
return ('TIER 2 MONITOR: Early warning signals present. '
'Increase monitoring to daily. Queue retraining.')
else:
return 'TIER 1 OK: No significant concept drift detected.'
print(concept_drift_response(0.84, 0.92, False, 0.05)) # TIER 3
print(concept_drift_response(0.91, 0.92, True, 0.18)) # TIER 2
print(concept_drift_response(0.91, 0.92, False, 0.03)) # TIER 1Ensemble-Modelle und Widerstandsfähigkeit gegenüber Konzeptdrift
Ensemble-Verfahren wie Random Forests und Gradient Boosting können Konzeptdrift länger verdecken als einzelne Modelle, da ihre Vielfalt sie weniger empfindlich gegenüber der Verschiebung der Verteilung eines einzelnen Features macht. Diese Widerstandsfähigkeit ist jedoch ein zweischneidiges Schwert: Das Modell verschlechtert sich langsamer und unauffälliger. Überwachen Sie in einem Forest die Rate der Uneinigkeit zwischen den einzelnen Bäumen — wenn die Bäume bei den Vorhersagen zunehmend voneinander abweichen, ist dies ein frühes Signal dafür, dass sich das Konzept verschiebt und das Ensemble Schwierigkeiten hat, einen Konsens zu erreichen.
import numpy as np
from sklearn.ensemble import RandomForestClassifier
# Measure inter-tree disagreement on current data as drift signal
def inter_tree_disagreement(forest, X):
predictions = np.array([tree.predict(X) for tree in forest.estimators_])
# Fraction of pairs of trees that disagree per sample, averaged over samples
n_trees = len(forest.estimators_)
disagreement_per_sample = []
for i in range(X.shape[0]):
preds = predictions[:, i]
disagree = (preds != preds[0]).sum() / n_trees
disagreement_per_sample.append(disagree)
return np.mean(disagreement_per_sample)
# Higher disagreement = more concept drift
# print(inter_tree_disagreement(model, X_current))Schnelltest
Testen Sie Ihr Verständnis der Konzepte aus dieser Lektion zum Thema Machine Learning mit Python.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: Konzeptdrift ist eine Änderung von P(Y|X) — der Zuordnung von Features zu Labels — und kann auch dann auftreten, wenn die Feature-Verteilungen stabil erscheinen, eine abnehmende Modellleistung bei gelabelten Produktionsdaten ist das eindeutige Signal für Konzeptdrift und erneutes Training mit Zeitfenstern sowie die Gewichtung von Stichproben sind die wichtigsten Anpassungsstrategien, um Modelle bei sich verändernden Konzepten aktuell zu halten. Als Nächstes betrachten wir die Überwachung von Vorhersageverteilungen und Konfidenzwerten als Frühwarnsystem, wenn die tatsächlichen Labels noch nicht verfügbar sind.
Lerne Python mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 30
- Lektionen
- 120
Häufig gestellte Fragen
Ist die Lektion „Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert“ kostenlos?
Ja — der vollständige Text von „Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Machine Learning Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Machine Learning Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert“?
Lernende unterscheiden Data Drift und Concept Drift anhand eines Zeitreihenbeispiels und verstehen, warum Data Drift nicht immer eine Verschlechterung der Modellleistung bedeutet. Du übst Machine Learning Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Machine Learning Academy zu starten?
Keine Vorkenntnisse erforderlich. Machine Learning Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Machine Learning Academy-Lektion Code schreiben und ausführen?
Ja. Jede Machine Learning Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Data Drift: Verschiebungen der Feature-Verteilung im Zeitverlauf
- Concept Drift: Wenn sich die Beziehung zwischen X und Y ändert
- Vorhersageverteilungen und Konfidenzwerte überwachen
- Eine Drift-Warnpipeline mit Evidently AI erstellen