What is the difference between a validation dataset and a training dataset?

Antrenare și Testare: Cheia Modelării ML

18/12/2024

Rating: 4.02 (8636 votes)

În lumea fascinantă a științei datelor și a învățării automate (Machine Learning), succesul unui model predictiv depinde în mare măsură de modul în care gestionăm și pregătim datele. Un pas fundamental și adesea subestimat este împărțirea corectă a setului de date în două componente esențiale: setul de antrenare și setul de testare. Această abordare metodică nu este doar o bună practică, ci o necesitate absolută pentru a evalua obiectiv performanța și generalizabilitatea unui model. Fără o împărțire adecvată, riscul de a construi un model care performează excelent pe datele pe care le-a văzut deja, dar eșuează lamentabil pe date noi, este extrem de ridicat. Acest articol va explora diverse metode prin care poți realiza eficient această împărțire în Python, utilizând biblioteci puternice precum NumPy, scikit-learn și Pandas, oferind exemple practice și explicații detaliate pentru fiecare abordare.

What is a train test split?
The train test split is a way of checking if the ML model performs well on data it has not seen. This is applied to supervised learning problems, both classification and regression. How does the Train-Test split work? So you have a dataset that contains the labels (y) and predictors (features X). Split the dataset randomly into two subsets:
Cuprins

De Ce Este Crucială Împărțirea Datelor?

Atunci când antrenăm un model de învățare automată, scopul nostru este să descoperim tipare și relații în date care să permită modelului să facă predicții precise pe date nevăzute. În acest proces, pot apărea două erori comune care compromit performanța modelului: supraînvățarea (overfitting) și subînvățarea (underfitting).

Supraînvățarea (Overfitting)

Supraînvățarea apare atunci când un model învață "prea bine" datele de antrenare, memorând zgomotul și particularitățile specifice ale acestora, în loc să generalizeze tiparele subiacente. Gândește-te la un student care memorează răspunsurile la un set specific de întrebări, dar nu înțelege cu adevărat conceptul. Când este confruntat cu o întrebare formulată diferit, chiar dacă vizează același concept, studentul eșuează. Similar, un model supraînvățat va avea o precizie excepțională pe setul de antrenare, dar va performa slab pe date noi, nevăzute. Acest lucru se întâmplă adesea când modelul este prea complex pentru volumul sau natura datelor disponibile.

Subînvățarea (Underfitting)

Subînvățarea, pe de altă parte, se produce atunci când un model este prea simplu pentru a capta complexitatea relațiilor din date. Este ca un student care nu învață deloc sau învață superficial. Modelul nu reușește să reprezinte nici măcar datele din setul de antrenare, ducând la o precizie scăzută atât pe datele de antrenare, cât și pe cele de testare. Cauzele comune includ utilizarea unui algoritm prea simplu, lipsa de caracteristici relevante sau un set de date de antrenare insuficient de mare sau reprezentativ.

De ce să nu testăm pe datele de antrenare?

Este tentant să evaluăm performanța unui model folosind aceleași date pe care le-am folosit pentru a-l antrena. Însă, așa cum am discutat, un model supraînvățat va arăta o precizie fantastică pe datele de antrenare, dându-ți o falsă senzație de siguranță. Această precizie nu reflectă capacitatea reală a modelului de a face predicții pe date noi. Prin urmare, este esențial să avem un set de testare separat, complet independent de setul de antrenare. Acest set de testare acționează ca o verificare "în orb" a modelului, simulând modul în care acesta ar performa în lumea reală, pe date pe care nu le-a mai întâlnit. O precizie bună pe setul de testare ne oferă o încredere mult mai mare în robustetea și generalizabilitatea modelului nostru.

Raportul cel mai comun pentru împărțirea datelor este 80:20, adică 80% din date pentru antrenare și 20% pentru testare. Totuși, acest raport poate varia în funcție de mărimea totală a setului de date și de specificul problemei.

Metode Eficiente de Împărțire a Datelor în Python

Python, prin ecosistemul său bogat de biblioteci, oferă instrumente puternice și flexibile pentru împărțirea datelor. Iată cele mai utilizate metode:

1. Utilizarea Funcției

train_test_split

din Scikit-learn

Pentru o soluție robustă și standardizată, care gestionează eficient atât caracteristicile (X), cât și etichetele (y) asociate, funcția train_test_split din biblioteca scikit-learn este alegerea preferată. Aceasta realizează o împărțire aleatorie, asigurând că ambele seturi (antrenare și testare) sunt reprezentative pentru distribuția generală a datelor. Este extrem de utilă pentru a menține corespondența dintre intrări și ieșiri.

How do you split a dataset into training and test sets?
Top 6 Ways to Split a Dataset into Training and Test Sets … How can you effectively split a dataset into training and test datasets for cross-validation? 1. Using NumPy’s Random Shuffle 2. Using scikit-learn’s train_test_split 3. Multiple Test/Validation Sets 4. Stratified Sampling Approach 5. Comparing Performance of Different Methods 6.

Iată un exemplu de implementare:

from sklearn.model_selection import train_test_split import numpy as np import pandas as pd # Creăm un set de date eșantion data = np.arange(100).reshape((50, 2)) # 50 de rânduri, 2 coloane pentru X labels = np.random.randint(0, 2, 50) # 50 de etichete (0 sau 1) pentru y # Împărțim setul de date în seturi de antrenare și testare # test_size = 0.20 înseamnă că 20% din date vor fi pentru testare # random_state = 42 asigură reproductibilitatea împărțirii (aceleași rânduri de fiecare dată) x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.20, random_state=42) print(f"Dimensiune X antrenare: {x_train.shape}") print(f"Dimensiune X testare: {x_test.shape}") print(f"Dimensiune Y antrenare: {y_train.shape}") print(f"Dimensiune Y testare: {y_test.shape}") 

Parametrul test_size specifică proporția setului de testare (aici 20%). random_state este un concept crucial: prin setarea unei valori fixe, asigurăm că împărțirea este aceeași de fiecare dată când rulăm codul, ceea ce este esențial pentru reproductibilitatea experimentelor.

Împărțirea în Multiple Seturi: Antrenare, Testare și Validare

În scenarii mai complexe, în care nu doar antrenăm și testăm, ci și optimizăm hiperparametrii modelului, este adesea necesar un al treilea set: setul de validare. Acest set este folosit pentru a regla parametrii modelului și a compara diferite modele, fără a "scurge" informații din setul de testare final. Se poate realiza prin aplicarea succesivă a funcției train_test_split:

from sklearn.model_selection import train_test_split import numpy as np # Presupunem că avem X (caracteristici) și y (etichete) X = np.random.rand(1000, 10) # 1000 de eșantioane, 10 caracteristici y = np.random.randint(0, 5, 1000) # 1000 de etichete, 5 clase # Pasul 1: Împărțim datele inițial în set de antrenare și un set temporar (test + validare) # Aici, 70% pentru antrenare, 30% pentru setul temporar x_train, x_temp, y_train, y_temp = train_test_split(X, y, test_size=0.3, random_state=42) # Pasul 2: Împărțim setul temporar în set de testare și set de validare # Din cele 30% rămase, 50% vor fi test și 50% vor fi validare (adică 15% și 15% din total) x_test, x_val, y_test, y_val = train_test_split(x_temp, y_temp, test_size=0.5, random_state=42) print(f"Dimensiune X antrenare: {x_train.shape} (70%)") print(f"Dimensiune X testare: {x_test.shape} (15%)") print(f"Dimensiune X validare: {x_val.shape} (15%)") 

2. Împărțirea cu NumPy: Simplitate și Control

NumPy, biblioteca fundamentală pentru calcul numeric în Python, oferă metode simple pentru împărțirea datelor, mai ales dacă ai nevoie de un control fin asupra procesului sau lucrezi doar cu array-uri numerice.

Amestecarea Aleatorie Simplă cu

np.random.shuffle

Dacă obiectivul este o singură împărțire a unui set de date într-o manieră simplă, np.random.shuffle este o opțiune directă. Aceasta amestecă aleatoriu rândurile întregului set de date, după care poți pur și simplu să-l tai în proporțiile dorite.

import numpy as np # Creăm un set de date eșantion (100 de rânduri, 5 coloane) data = np.random.rand(100, 5) # Setăm o stare aleatorie pentru reproductibilitate np.random.seed(42) # Amestecăm datele np.random.shuffle(data) # Împărțim în seturi de antrenare și testare (80% antrenare, 20% testare) train_size = int(0.8 * len(data)) train_data, test_data = data[:train_size, :], data[train_size:, :] print(f"Dimensiune set antrenare: {train_data.shape}") print(f"Dimensiune set testare: {test_data.shape}") 

Gestionarea Indexurilor cu

np.random.permutation

O alternativă mai flexibilă, mai ales când vrei să ții evidența indexurilor originale sau să amesteci doar indexurile și să le aplici apoi datelor, este utilizarea np.random.permutation. Aceasta generează o secvență amestecată de indexuri, pe care le poți folosi apoi pentru a selecta rândurile din setul tău de date.

import numpy as np # Creăm un set de date eșantion data = np.random.rand(100, 5) # Generăm indexuri amestecate np.random.seed(42) indices = np.random.permutation(data.shape[0]) # Alocăm indexurile pentru antrenare și testare train_size = int(0.8 * len(data)) train_idx, test_idx = indices[:train_size], indices[train_size:] # Creăm seturile de date folosind indexurile train_data, test_data = data[train_idx, :], data[test_idx, :] print(f"Dimensiune set antrenare: {train_data.shape}") print(f"Dimensiune set testare: {test_data.shape}") 

3. Eșantionarea Stratificată: Păstrarea Proporțiilor Clasălor

În cazul seturilor de date dezechilibrate, unde anumite clase sunt mult mai puțin reprezentate decât altele (de exemplu, detectarea fraudelor, unde cazurile de fraudă sunt rare), o simplă împărțire aleatorie poate duce la situația în care setul de testare conține prea puține (sau niciuna) dintre instanțele clasei minoritare. Acest lucru face evaluarea modelului pe acea clasă extrem de dificilă sau imposibilă.

Eșantionarea stratificată rezolvă această problemă asigurându-se că proporția fiecărei clase este menținută în ambele seturi (antrenare și testare). Scikit-learn oferă această funcționalitate direct prin parametrul stratify în train_test_split. Dacă folosești un y (etichete) care reprezintă clasele, poți pur și simplu să-l pasezi parametrului stratify:

from sklearn.model_selection import train_test_split import numpy as np # Creăm un set de date cu o distribuție dezechilibrată X = np.random.rand(100, 2) y = np.array([0]*90 + [1]*10) # 90 de cazuri de clasa 0, 10 de clasa 1 # Împărțire stratificată x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y) print("Distribuția claselor în setul original:", np.bincount(y)) print("Distribuția claselor în setul de antrenare:", np.bincount(y_train)) print("Distribuția claselor în setul de testare:", np.bincount(y_test)) 

Observați cum proporția de 90/10% pentru clasele 0 și 1 este păstrată în ambele seturi împărțite.

How to split data in Python using train_test_split?
To split the data we will be using train_test_split from sklearn. train_test_split randomly distributes your data into training and testing set according to the ratio provided. Let’s see how it is done in python. Here we are using the split ratio of 80:20. The 20% testing data set is represented by the 0.2 at the end.

4. Împărțirea Datelor cu Pandas: Metoda

.sample()

Dacă lucrezi cu DataFrames Pandas, metoda .sample() oferă o modalitate elegantă de a extrage un eșantion aleatoriu din date. Aceasta este utilă pentru crearea setului de antrenare, iar apoi setul de testare poate fi obținut prin excluderea rândurilor eșantionate.

import pandas as pd import numpy as np # Creăm un DataFrame eșantion df = pd.DataFrame(np.random.rand(100, 3), columns=['feat1', 'feat2', 'target']) # Creăm setul de antrenare prin eșantionare (70% din date) # frac=0.7 înseamnă 70% din rânduri # random_state=200 pentru reproductibilitate train_df = df.sample(frac=0.7, random_state=200) # Creăm setul de testare prin excluderea rândurilor din setul de antrenare test_df = df.drop(train_df.index) print(f"Dimensiune DataFrame original: {df.shape}") print(f"Dimensiune DataFrame antrenare: {train_df.shape}") print(f"Dimensiune DataFrame testare: {test_df.shape}") 

5. Abordări Secvențiale Personalizate (Opțional)

În anumite scenarii specifice, cum ar fi datele de serie temporală unde ordinea este crucială și amestecarea ar distruge relațiile temporale, o împărțire secvențială (de exemplu, primele 80% pentru antrenare, ultimele 20% pentru testare) ar putea fi mai potrivită. Aceasta implică pur și simplu tăierea setului de date la un anumit punct. Cu toate acestea, pentru majoritatea problemelor de învățare automată, împărțirea aleatorie este preferată pentru a asigura că ambele seturi sunt reprezentative pentru întregul spațiu de date.

Tabel Comparativ: Metode de Împărțire a Datelor

Pentru a te ajuta să alegi metoda potrivită, iată o scurtă comparație a abordărilor discutate:

MetodăAvantajeDezavantajeCând să o folosești
train_test_split (Scikit-learn)
  • Standardizată și robustă
  • Gestionează X și y simultan
  • Suportă eșantionare stratificată (stratify)
  • Asigură reproductibilitate (random_state)
  • Necesită instalarea scikit-learn
  • Mai puțină flexibilitate pentru împărțiri non-standard
  • Majoritatea problemelor de clasificare/regresie
  • Seturi de date dezechilibrate (cu stratify)
  • Când vrei o soluție rapidă și fiabilă
NumPy (shuffle / permutation)
  • Control fin asupra procesului
  • Nu necesită biblioteci suplimentare în afara NumPy
  • Ideal pentru array-uri numerice simple
  • Necesită gestionarea manuală a X și y
  • Nu oferă nativ eșantionare stratificată (trebuie implementat manual)
  • Când ai nevoie de o flexibilitate maximă
  • Pentru seturi de date mici sau simple array-uri NumPy
  • Când nu vrei dependențe suplimentare
Pandas (.sample())
  • Elegantă și intuitivă pentru DataFrames
  • Ideală pentru selectarea unui procent specific de rânduri
  • Asigură reproductibilitate (random_state)
  • Nu oferă nativ eșantionare stratificată
  • Necesită gestionarea manuală a X și y dacă sunt în coloane separate
  • Când lucrezi predominant cu DataFrames Pandas
  • Pentru eșantionare aleatorie simplă fără stratificare

Considerații Suplimentare: Preprocesarea și Ordinea Operațiilor

Un aspect crucial, adesea trecut cu vederea, este ordinea în care se aplică pașii de preprocesare a datelor (cum ar fi scalarea, normalizarea sau imputarea valorilor lipsă) în raport cu împărțirea datelor. Este absolut esențial să efectuezi aceste operații după ce ai împărțit datele în seturi de antrenare și testare. Mai mult, orice transformare bazată pe statisticile datelor (medie, deviație standard, minim, maxim) trebuie calculată doar pe setul de antrenare și apoi aplicată atât setului de antrenare, cât și setului de testare.

De ce este important acest lucru? Dacă, de exemplu, scalezi întregul set de date înainte de împărțire, informațiile din setul de testare (care ar trebui să fie "nevăzute") vor "scurge" în setul de antrenare prin statisticile de scalare. Acest lucru ar duce la o evaluare prea optimistă a performanței modelului. Prin urmare, fluxul corect este:

  1. Împărțirea datelor în set de antrenare și set de testare.
  2. Aplicarea preprocesării (ex: scalare, imputare) pe setul de antrenare, calculând statisticile necesare (ex: media și deviația standard pentru scalare) doar din setul de antrenare.
  3. Aplicarea acelorași transformări (folosind statisticile calculate din setul de antrenare) pe setul de testare.

Întrebări Frecvente (FAQ)

Î: Care este cea mai bună metodă de a împărți seturile de date?

R: Cea mai bună metodă depinde de caracteristicile datelor tale. Pentru utilizare generală, train_test_split din scikit-learn este puternic recomandată datorită echilibrului său și ușurinței în utilizare. Pentru seturi de date dezechilibrate, utilizează opțiunea stratify din aceeași funcție.

Î: Cum pot asigura că împărțirile mele mențin distribuția claselor?

R: Utilizează metode de eșantionare stratificată. În scikit-learn, poți face acest lucru prin setarea parametrului stratify=y în funcția train_test_split, unde y sunt etichetele tale de clasă.

Î: Pot crea mai mult de un set de validare?

R: Da, poți crea multiple seturi de validare prin împărțirea succesivă a datelor după împărțirea inițială pentru antrenare, de obicei urmată de o partiționare ulterioară a setului de validare intermediar.

Împărțirea corectă a datelor este un pilon fundamental în construcția de modele de învățare automată performante și fiabile. Alegerea metodei potrivite și înțelegerea principiilor din spatele acestei practici te vor ajuta să eviți capcanele supraînvățării și subînvățării, asigurând că modelele tale generalizează eficient pe date noi. Prin aplicarea tehnicilor prezentate în acest articol, vei fi mai bine pregătit să construiești soluții de Machine Learning robuste și precise. Nu uita, practica este cheia, așa că experimentează cu diferite seturi de date și metode pentru a-ți consolida înțelegerea!

Dacă vrei să descoperi și alte articole similare cu Antrenare și Testare: Cheia Modelării ML, poți vizita categoria Fitness.

Go up