Stratifierad korsvalidering och korsvalidering för tidsserier
Ni kommer att använda StratifiedKFold för att bevara klassfördelningen och TimeSeriesSplit för att förhindra att framtida data läcker in i tidigare foldar i tidsordnade datamängder.
Stratifierad korsvalidering och korsvalidering för tidsserier är en gratis lektion i Machine Learning Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Machine Learning Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.
När standard-K-Fold inte fungerar
StandardKFold delar upp data slumpmässigt utan hänsyn till klassfördelning eller tidsordning. Detta skapar två allvarliga problem: (1) för obalanserade datamängder kan vissa foldar innehålla mycket få eller inga exempel från minoritetsklassen, vilket gör variationen mellan foldarna extrem; (2) för tidsordnade data innebär träning på framtida exempel för att förutsäga det förflutna att data läcker, vilket blåser upp CV-resultaten långt över den verkliga prestandan. Specialiserade CV-strategier löser dessa problem utan att den rättvisande utvärderingen försämras.
Stratified K-Fold: bevara klassförhållanden
StratifiedKFold säkerställer att varje fold innehåller ungefär samma andel av varje klass som hela datamängden. Om till exempel 10 % av Era data är bedrägerier kommer varje fold att innehålla ungefär 10 % bedrägerifall. Detta förhindrar situationer där en fold inte innehåller några bedrägerifall, vilket skulle göra det omöjligt för klassificeraren att lära sig upptäcka bedrägerier i den omgången. Använd StratifiedKFold när Ni har fler än 2 klasser eller en betydande klassobalans.
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(RandomForestClassifier(random_state=42), X, y, cv=skf)
print('Stratified 5-fold:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4), 'Std:', round(scores.std(), 4))Verifiera stratifiering
Ni kan verifiera att StratifiedKFold bevarar klassförhållandena genom att granska målvariabelns fördelning i varje fold. För varje testfold bör andelen positiva exempel motsvara den övergripande andelen positiva exempel. Om Ni jämför klassfördelningarna från standardKFold och StratifiedKFold på en obalanserad datamängd blir det tydligt varför stratifiering är viktig – klassförhållandena mellan foldarna kan skilja sig med mer än 20 % utan stratifiering.
from sklearn.model_selection import StratifiedKFold, KFold
import numpy as np
# Imbalanced data: 90% negative, 10% positive
np.random.seed(42)
y = np.array([0]*90 + [1]*10)
X = np.random.randn(100, 5)
for name, cv in [('KFold', KFold(n_splits=5, shuffle=True, random_state=42)),
('StratifiedKFold', StratifiedKFold(n_splits=5, shuffle=True, random_state=42))]:
ratios = [y[test].mean() for _, test in cv.split(X, y)]
print(f'{name} positive rates per fold:', np.round(ratios, 2))cross_val_score använder stratifiering automatiskt
När Ni skickar cv=5 (ett heltal) till cross_val_score för klassificeringsuppgifter använder scikit-learn automatiskt StratifiedKFold. För regression används vanlig KFold. Det innebär att de flesta användare får stratifiering automatiskt utan att uttryckligen skapa ett StratifiedKFold-objekt. Åsidosätt endast detta standardbeteende när Ni behöver ett anpassat uppdelningsbeteende (till exempel gruppuppdelning, tidsserieuppdelning eller ett annat antal foldar med blandning).
Tidsseriedata: den särskilda utmaningen
Finansiella data, sensordata, väderdata och många andra verkliga datamängder är ordnade i tid. En viktig egenskap hos tidsseriemodeller är att förutsägelser måste göras med endast tidigare data. Om Ni tränar en modell på data från april och använder den för att förutsäga värden för januari tränar Ni på framtiden – detta kallas tidsmässigt dataläckage. Även standard-K-Fold bryter mot detta: när fold 3 är testmängden och fold 4 ingår i träningsmängden används framtida data för att förutsäga det förflutna. TimeSeriesSplit förhindrar detta.
TimeSeriesSplit: träna alltid på det förflutna
TimeSeriesSplit skapar foldar där träningsdata alltid föregår testdata kronologiskt. I varje uppdelning utökas träningsmängden genom att den föregående testfolden inkluderas. Med 5 uppdelningar tränar till exempel uppdelning 1 på de första 20 % och testar på nästa 20 %, medan uppdelning 2 tränar på de första 40 % och testar på nästa 20 %, och så vidare. Detta säkerställer att ingen framtida information kommer in i träningsmängden och att CV-resultatet speglar realistisk generalisering över tid.
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
n = 100
X = np.random.randn(n, 5)
y = np.random.randn(n)
tscv = TimeSeriesSplit(n_splits=5)
for fold, (train_idx, test_idx) in enumerate(tscv.split(X, y), 1):
print(f'Fold {fold}: train [{train_idx[0]}-{train_idx[-1]}], '
f'test [{test_idx[0]}-{test_idx[-1]}]')Använda TimeSeriesSplit med cross_val_score
Skicka ett TimeSeriesSplit-objekt direkt till parametern cv i cross_val_score. De resulterande resultaten mäter hur väl modellen generaliserar när den tränas på tidigare data och utvärderas på senare data – vilket är precis det verkliga användningsfallet. Observera att träningsmängderna växer mellan foldarna, så tidigare foldar har färre träningsexempel och kan ge lägre resultat – detta är förväntat, inte ett fel.
from sklearn.model_selection import TimeSeriesSplit, cross_val_score
from sklearn.ensemble import GradientBoostingRegressor
import numpy as np
# Simulated time-series: price = trend + noise
np.random.seed(42)
n = 200
X = np.arange(n).reshape(-1, 1) + np.random.randn(n, 1) * 5
y = 0.5 * np.arange(n) + np.random.randn(n) * 10
tscv = TimeSeriesSplit(n_splits=5)
scores = cross_val_score(GradientBoostingRegressor(n_estimators=50, random_state=42),
X, y, cv=tscv, scoring='r2')
print('TimeSeriesSplit R² scores:', np.round(scores, 4))
print('Mean R²:', round(scores.mean(), 4))GroupKFold: förhindra läckage mellan stickprov
Vissa datamängder har flera stickprov per entitet – flera EKG:n per patient, flera transaktioner per användare eller flera bilder per scen. Om samma patient förekommer i både tränings- och testfoldar lär sig modellen patientspecifika mönster i stället för generella mönster. GroupKFold säkerställer att alla stickprov från samma grupp (patient, användare eller scen) hamnar i samma fold och förhindrar därmed läckage inom gruppen. Skicka gruppidentifierarna till parametern groups i cross_val_score.
from sklearn.model_selection import GroupKFold, cross_val_score
from sklearn.linear_model import LogisticRegression
import numpy as np
np.random.seed(42)
n = 100
X = np.random.randn(n, 5)
y = np.random.randint(0, 2, n)
groups = np.repeat(np.arange(10), 10) # 10 patients, 10 samples each
gkf = GroupKFold(n_splits=5)
scores = cross_val_score(LogisticRegression(max_iter=1000), X, y, cv=gkf, groups=groups)
print('GroupKFold scores:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4))Expanderande fönster jämfört med glidande fönster för tidsserier
TimeSeriesSplit använder ett expanderande fönster: träningsmängden växer vid varje uppdelning. Ett alternativ är ett glidande fönster: använd endast de senaste N dagarna/månaderna för träning och ta bort äldre data. Glidande fönster är bättre när sambandet mellan egenskaper och målvariabel förändras över tid (konceptdrift) och äldre data inte längre är representativa. scikit-learn tillhandahåller inte korsvalidering med glidande fönster direkt, men Ni kan implementera det med en anpassad CV-generator eller TimeSeriesSplit med max_train_size.
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
# Sliding window: fix the training size
tscv = TimeSeriesSplit(n_splits=4, max_train_size=50) # max 50 training samples
X = np.random.randn(200, 3)
for fold, (train_idx, test_idx) in enumerate(tscv.split(X), 1):
print(f'Fold {fold}: train size={len(train_idx)}, '
f'test [{test_idx[0]}-{test_idx[-1]}]')Välj rätt CV-strategi
En enkel beslutsväg: (1) klassificering med balanserade klasser → standard-KFold eller ett heltal till cross_val_score (automatisk stratifiering); (2) klassificering med obalanserade klasser → StratifiedKFold uttryckligen; (3) tidsordnade data → TimeSeriesSplit; (4) flera stickprov per entitet → GroupKFold; (5) obalanserade och grupperade data → StratifiedGroupKFold (scikit-learn 0.24+). Om Ni väljer fel CV-strategi kan en modell som generaliserar dåligt verka utmärkt eller en bra modell verka medioker – anpassa alltid CV-metoden efter det verkliga användningsscenariot.
Walk-forward-validering i produktion
I verkliga tidsseriesystem i produktion tränas modeller om regelbundet och utvärderas på den efterföljande perioden. Walk-forward-validering simulerar detta: träna på månaderna 1–6 och utvärdera på månad 7; träna på månaderna 1–7 och utvärdera på månad 8; och så vidare. Detta motsvarar TimeSeriesSplit med parametern gap, som lägger till en buffert mellan slutet av träningen och början av testet (för att undvika läckage från tidsmässigt närliggande tidpunkter). Den resulterande resultatserien visar också om modellens prestanda är stabil över tid eller försämras.
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
# Simulate 24 months of data
n_months = 24
np.random.seed(42)
X = np.random.randn(n_months, 5)
y = np.random.randn(n_months)
# Walk-forward: 12 train periods, 1 test each
tscv = TimeSeriesSplit(n_splits=12, test_size=1)
for fold, (tr, te) in enumerate(tscv.split(X), 1):
if fold <= 3 or fold == 12:
print(f'Fold {fold:2d}: train months 1-{len(tr)}, test month {te[0]+1}')Snabb kontroll
Testa Era förståelse av stratifierad korsvalidering och tidsseriekorsvalidering från den här lektionen.
Sammanfattning av lektionen
I den här lektionen har Ni lärt Er: StratifiedKFold bevarar klassandelarna mellan foldarna vid obalanserad klassificering, TimeSeriesSplit förhindrar tidsmässigt läckage genom att alltid träna på tidigare data och GroupKFold förhindrar läckage inom grupper när flera stickprov tillhör samma entitet. Härnäst jämför vi Grid Search och Random Search för hyperparameteroptimering.
Lär dig Python med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”Stratifierad korsvalidering och korsvalidering för tidsserier” gratis?
Ja – hela texten till ”Stratifierad korsvalidering och korsvalidering för tidsserier” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Machine Learning Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Stratifierad korsvalidering och korsvalidering för tidsserier”?
Ni kommer att använda StratifiedKFold för att bevara klassfördelningen och TimeSeriesSplit för att förhindra att framtida data läcker in i tidigare foldar i tidsordnade datamängder. Ni övar på Machine Learning Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Machine Learning Academy?
Du behöver inga förkunskaper. Utbildningen i Machine Learning Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”Stratifierad korsvalidering och korsvalidering för tidsserier”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Machine Learning Academy-lektionen?
Ja. Varje Machine Learning Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- K-faldig korsvalidering: Uppdelning utan läckage
- Stratifierad korsvalidering och korsvalidering för tidsserier
- Grid Search jämfört med Random Search
- Nästlad korsvalidering: Urval och utvärdering samtidigt