Les jeux de données pour alimenter un dispositif d'apprentissage automatique ne sont pas toujours homogènes ou cohérents. Il y a parfois des 'trous' dans les données. Ces manques peuvent avoir diverses origines: mauvais relevé, erreur de type ou d'encodage.
La méthode info() d'un dataframe permet de connaitre l'état général des données : type et remplissage!;
dt.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 20 entries, 0 to 19 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 X 16 non-null float64 1 y 20 non-null float64 dtypes: float64(2) memory usage: 448.0 bytesici , on traitera des données de type 'float' et 4 données de la première colonne sont manquantes:
None ou 'nan' :not a number
Le détail par ligne:
dt[dt.isnull().values] X y 3 NaN -52.517783 5 NaN -23.697502 10 NaN -13.255462 12 NaN 8.366929
Il n'est pas recommandé de conserver des données nulles dans son jeu de données. Les frameworks d'apprentissage
risquent de dysfonctionner. Face à ce problème, il peut y avoir plusieurs stratégies:
Supprimer la ligne entière ou essayer de 'combler' les trous.
Supprimer les lignes incomplètes est une option valable quand le nombre de lignes 'saines' est important.
Dans le cas présent, le jeu de données serait amputé de 4 lignes sur 20 => 1/5eme, la proportion est trop importante.
l'opération est plutôt simple, elle se fait par la méthode dropna()
Penser à ajouter l'option inplace=True pour mettre à jour le dataframe.
dt.dropna() X y 0 -1.913280 -87.286608 1 -1.724918 -79.815577 2 -1.412304 -58.442734 4 -0.908024 -27.520687 6 -0.469474 -19.956148La ligne 3 a été supprimée.
Les solutions pour combler les manques.
On peut utiliser des méthodes issues de Pandas ou d'autres plus sophistiquées portées par le framework scikit-learn (sklearn).
Les solutions Pandas
Elles sont couvertes par les méthodes: replace() , fillna() , interpolate().
Replace est la plus généraliste: elle permet de remplacer une donnée par une autre.
Dans le cas présent il faut déterminer la valeur de remplacement. On peut comme ici mettre la valeur 0 en lieu et place des valeurs indéfinies.
La valeur a remplacer est portée par le module numpy
dt.replace(np.nan , 0) X y 0 -1.913280 -87.286608 1 -1.724918 -79.815577 2 -1.412304 -58.442734 3 0.000000 -52.517783 4 -0.908024 -27.520687
La méthode fillna() est plus puissante , on peut choisir la valeur de remplacement suivant plusieurs méthodes:
‘backfill’, ‘bfill’, ‘ffill’, None et defaut None
Pandas utilisera la valeur, avant ou apres pour remplir les manques.
Exemple
dt.fillna(method = 'bfill') # ou dt.bfill() X y 0 -1.913280 -87.286608 1 -1.724918 -79.815577 2 -1.412304 -58.442734 3 -0.908024 -52.517783 4 -0.908024 -27.520687
L'ordre des données est important, peut-être faut il trier les valeurs avant.
Ci dessous, un jeu de données est généré à partir de sklearn, assemblé dans un dataframe puis trié sur la colonne 'X'.
from sklearn.datasets import make_regression X, y = make_regression(n_samples=20, n_features=1, noise=5, random_state=42) print(X.shape) print(y.shape) dt = pd.DataFrame(zip(X.flat, y), columns = ['X', 'y']) dt.sort_values('X', inplace =True) (20, 1) (20,) X y 15 -1.913280 -87.286608 3 -1.724918 -79.815577 5 -1.412304 -58.442734 7 -1.012831 -52.517783 4 -0.908024 -27.520687Pour terminer avec Pandas, la méthode interpolate() offre la possibilité de prédire les données manquantes en utilisant une regression linéaire. Ici l'ordre de presentation importe peu.
Elle propose un bon nombre de résolution :
- 'linear’
- ‘time’ pour les dates
- ‘index’, ‘values’
- ‘pad’
- ‘nearest’
- ,‘zero’
- ‘slinear’
- ‘quadratic’
- ‘cubic’
- ‘from_derivatives’
etc.
SKLearn , propose trois méthodes principales:
- SimpleImputer : très basique, il remplace les valeurs par la moyenne , la médiane etc.
- KNNImputer: utilise un algorithme basé sur le calcul de distance de voisinage de point
- IterativeImputer: module experimental et très puissant.
Pour utiliser ces modèles, il est préférable de décharger le dataframe dans des structures numpy:
from sklearn.impute import KNNImputer,SimpleImputer imp = IterativeImputer(random_state=0) np1 = dt[['X', 'y']].to_numpy() np2 = imp.fit_transform(np1) simpl = SimpleImputer() np3 = simpl.fit_transform(np1) kn = KNNImputer() np4 = kn.fit_transform(np1)
Le graphisme ci-dessous visualise les résultats obtenus avec les différentes méthodes.On commence par introduire des valeurs np.nan dans l'axe des X.
Par:
dt.iat[3, 0] = np.nandt.iat[10, 0] = np.nandt.iat[12, 0] = np.nandt.iat[5,0] = np.nan
Conclusion: ceux qui s'en sortent le mieux sont :
Pour Pandas : interpolate()
Pour SKLearn : KNNImputer (le meilleur) suivi de IterativeImputer mais il faudrait tester pour chacun les options disponibles.
from sklearn.metrics import mean_squared_error print(mean_squared_error(dt_nan.X, np3[:,0] ))# SimpleImputer print(mean_squared_error(dt_nan.X, np4[:,0] )) #KNNImputer print(mean_squared_error(dt_nan.X, np2[:,0] )) # iterativeImputer print(mean_squared_error(dt_nan.X, dt_inter.X )) #pandas interpolate 0.05726013724292493 # SimpleImputer 0.000988070710285649 #KNNImputer 0.002632595263623769 # iterativeImputer 0.003185180237325761 #pandas interpolate
Pour rappel, il n'est pas possible de connaitre à l'avance quel sera la meilleure solution.
Aucun commentaire:
Enregistrer un commentaire