Οργανωμένη Προεπεξεργασία για Pandas Dataframe

Οργανωμένη Προεπεξεργασία για Pandas Dataframe

September 30, 2022 0 Von admin

Αυτό το άρθρο δημοσιεύτηκε ως μέρος του Data Science Blogathon.

είναι ένα ουσιαστικό βήμα στη μηχανική μάθηση. Υποτιμούμε την προεπεξεργασία, αλλά στην πραγματικότητα, η επιλογή της σωστής προεπεξεργασίας για τα δεδομένα μας είναι εξίσου σημαντική με την επιλογή του σωστού μοντέλου, αν όχι περισσότερο. Τις περισσότερες φορές προχωράμε σε κάποια τυχαία προεπεξεργασία και δεν την αλλάζουμε πολύ καθώς απαιτεί πολλές αλλαγές στον κώδικα. Για να το λύσουμε αυτό, πρέπει να οργανώσουμε την προεπεξεργασία έτσι ώστε να γίνεται ευκολότερος ο πειραματισμός με διαφορετικές προεπεξεργασίες.

Σε αυτό το άρθρο, θα εφαρμόσω λειτουργίες προεπεξεργασίας για – Καθαρισμός δεδομένων, κωδικοποίηση δεδομένων, κανονικοποίηση δεδομένων, διαχωρισμός Train-Val-Test, και Εκτέλεση Προεπεξεργασίας για το Σύνολο δεδομένων Cars93 χρησιμοποιώντας Pandas Dataframe. Μετά το τέλος αυτού του άρθρου, θα μπορούμε να προεπεξεργαζόμαστε τα δεδομένα μας σε τέσσερις μόνο γραμμές με οργανωμένο και απλό τρόπο. (Μετάβαση στη Σύνοψη για να λάβετε μια επισκόπηση)

Στόχοι

Για να κάνετε καθολικές συναρτήσεις

Θέλουμε οι συναρτήσεις μας να λειτουργούν για όλα τα σύνολα δεδομένων περνώντας ένα πλαίσιο δεδομένων pandas ως είσοδο στη συνάρτησή μας αντί να χρειάζεται να αλλάξουμε χειροκίνητα τον κώδικα για κάθε πλαίσιο δεδομένων. Ούτε μια φορά, σε καμία από τις συναρτήσεις, δεν θα χρησιμοποιήσουμε οτιδήποτε συγκεκριμένο για το σύνολο δεδομένων που έχουμε πάρει ως παράδειγμα.

Για να δημιουργήσετε μια ενιαία λειτουργία για κάθε εργασία προεπεξεργασίας

Για κάθε εργασία (καθαρισμός, κωδικοποίηση, κανονικοποίηση, διαχωρισμός) θέλουμε να δημιουργήσουμε μια συνδυασμένη συνάρτηση όπου μπορούμε να κάνουμε την εργασία χρησιμοποιώντας απλώς αυτήν τη μεμονωμένη συνάρτηση και παίζοντας με τα ορίσματα που περνάμε στη συνάρτηση.

Για να κάνετε την προεπεξεργασία όσο πιο απλή και ευέλικτη γίνεται

Θέλουμε η κύρια λειτουργία μας να καθιστά δυνατή την προεπεξεργασία των δεδομένων με τον τρόπο που θέλουμε χωρίς να χρειάζεται να αλλάξουμε τίποτα στον κώδικα. Θα το κάνουμε αυτό με μια έξυπνη επιλογή επιχειρημάτων.

Για να κάνετε πολύ εύκολο τον πειραματισμό με διαφορετική προεπεξεργασία

Δεδομένου ότι η προεπεξεργασία των δεδομένων μας θα γίνει απλή με τις λειτουργίες μας, δεν θα νιώθουμε τεμπέληδες να δοκιμάσουμε διαφορετικές προεπεξεργασίες για να αυξήσουμε την ακρίβειά μας. Θα μας εξοικονομήσει πολύ χρόνο που διαφορετικά θα είχαμε ξοδέψει κάνοντας αλλαγές μέσω του κώδικα ακόμα και για μικρές αλλαγές στην προεπεξεργασία.

Προεπεξεργασία

Θα εφαρμόσουμε τις ακόλουθες Λειτουργίες Προεπεξεργασίας

Θα τα εξηγήσω περαιτέρω στο άρθρο καθώς τα εφαρμόζουμε

Δεδομένα καθαρισμού

  • Αφαίρεση δεδομένων που λείπουν
  • Κατάργηση δεδομένων αναντιστοιχίας
  • Μετατροπή αριθμητικών δεδομένων που έχουν αποθηκευτεί ως συμβολοσειρά σε αριθμητική μορφή.
  • Single Function Συνδυάζοντας όλα τα παραπάνω βήματα καθαρισμού δεδομένων.

Κωδικοποίηση δεδομένων

  • Κωδικοποίηση ετικέτας (με παραγγελία)
  • Κωδικοποίηση ετικέτας (χωρίς παραγγελία)
  • One Hot Encoding
  • Μονή συνάρτηση Συνδυάζει όλες τις παραπάνω κωδικοποιήσεις

Κανονικοποίηση δεδομένων

  • Διαιρέστε με το μεγαλύτερο
  • Διαιρέστε με Constant
  • Διαιρέστε με το Constant x Largest
  • Min-Max Κανονοποίηση
  • Μέση Κανονικοποίηση
  • Μονή λειτουργία Συνδυάζει όλες τις παραπάνω κανονικοποιήσεις

Διαίρεση δεδομένων

  • Διαχωρισμός Train-Validation-Test (με χρήση sklearn)
  • Ενιαία λειτουργία για διαίρεση Train-Test & Train-Validation-Test Split

Σύνδεσμος στο σύνολο δεδομένων – Σύνολο δεδομένων Cars93

Εισαγωγή δεδομένων

import pandas as pd

df = pd.read_csv(path+'Cars93.csv')

df = df[['Model','Manufacturer','Type','Price','AirBags','Cylinders','Horsepower','RPM']]

# We keep a few features only for our purpose

df.head(3)
Εισαγωγή δεδομένων |  Προεπεξεργασία

 

Cleaning Data

We need to clean the data so that we do not face any issues later when we apply a model to our data.

Removing Missing Data

We need to remove data where the value of any feature is nan or na or empty.

def remove_missing(df) : 
  remove = []
  for i, row in df.iterrows():
    if row.isna().values.any() : remove.append(i)
  df.drop(remove,axis=0,inplace=True)

Κατάργηση δεδομένων αναντιστοιχίας

Πρέπει να αφαιρέσουμε δεδομένα με αναντιστοιχίες. Για πχ. ένα σημείο δεδομένων με τιμή συμβολοσειράς για ένα αριθμητικό χαρακτηριστικό. Για αυτό, θα ελέγξουμε ποιος τύπος δεδομένων είναι η πλειοψηφία για κάθε δυνατότητα και θα καταργήσουμε τα δεδομένα με διαφορετικό τύπο δεδομένων για αυτές τις λειτουργίες.

Παρέχουμε επίσης «εξαιρέσεις» όπου μπορούμε να καθορίσουμε χαρακτηριστικά για τα οποία οι τιμές μπορούν να έχουν διαφορετικούς τύπους δεδομένων και δεν θέλουμε να αφαιρέσουμε αναντιστοιχίες.

def remove_mismatch(df,exceptions=[]) : 
  for col in df : 
    if col in exceptions : continue
    df.reset_index(drop=True, inplace=True)
    s = [False]*len(df[col])
    for i,cell in enumerate(df[col]) : 
      try : n = int(cell)
      except : s[i] = True
    t = s.count(True)
    f = s.count(False)
    st = False
    if(t>f) : st = True
    remove = [i for i in range(len(df[col])) if s[i]!=st]
    df.drop(remove,axis=0,inplace=True)

Μετατροπή αριθμητικών δεδομένων που είναι αποθηκευμένα ως συμβολοσειρά σε αριθμητική μορφή –

Μερικές φορές τα Αριθμητικά Δεδομένα (π.χ. int) αποθηκεύονται ως συμβολοσειρά, οδηγώντας σε σφάλμα όταν εκπαιδεύουμε το μοντέλο μας ή κανονικοποιούμε τα δεδομένα μας. Πρέπει να εντοπίσουμε τέτοιες περιπτώσεις και να τις μετατρέψουμε στην αρχική τους αριθμητική μορφή.

def str_to_num(df) : 
  for col in df : 
    try : df[col] = pd.to_numeric(df[col])
    except : pass

Ενιαία λειτουργία για καθαρισμό δεδομένων

def clean(df,exceptions_mismatch=[]) : 
  remove_missing(df) 
  remove_mismatch(df,exceptions=exceptions_mismatch)
  str_to_num(df)
clean(df,exceptions_mismatch=['Model'])

Κωδικοποίηση δεδομένων

Κωδικοποίηση ετικέτας- Εκχώρηση ενός ακέραιου σε κάθε μοναδική τιμή μιας στήλης/χαρακτηριστικού.
One Hot Encoding- Μετατροπή 1 στήλης σε n στήλες όπου n είναι ο αριθμός των μοναδικών τιμών σε αυτήν τη στήλη. Κάθε νέα στήλη αντιπροσωπεύει μια μοναδική τιμή στην αρχική στήλη και περιέχει είτε 0 είτε 1. Έτσι, σε κάθε γραμμή, μόνο μία από τις n στήλες θα έχει την τιμή 1 και οι υπόλοιπες n-1 στήλες θα έχουν την τιμή 0.
Θα αναπαραστήσουμε τον τύπο κωδικοποίησης που θέλουμε για κάθε στήλη χρησιμοποιώντας ένα λεξικό, όπου τα κλειδιά θα είναι τα ονόματα στηλών/χαρακτηριστικών και οι τιμές τους θα είναι ο τύπος κωδικοποίησης που θέλουμε.

labels = {}
labels['AirBags'] = ['None','Driver only','Driver & Passenger']
labels['Type'] = None
labels['Manufacturer'] = []
labels['Model'] = []
  • „Κανένα“ θα σημαίνει One Hot Encoding
  • ‚[]‘ θα σήμαινε Κωδικοποίηση ετικέτας χωρίς συγκεκριμένη σειρά
  • ‚[a,b,c…]‘ θα σήμαινε Κωδικοποίηση ετικέτας με τη λίστα να είναι η σειρά

Με αυτόν τον τρόπο ο πειραματισμός με διαφορετική κωδικοποίηση θα γίνει πολύ εύκολος. Για παράδειγμα, εάν θέλουμε να αλλάξουμε την κωδικοποίηση της στήλης «Τύπος» από One Hot σε Label, μπορούμε να το κάνουμε αλλάζοντας απλώς την τιμή της στο λεξικό ετικετών από Καμία σε [].

Κωδικοποίηση ετικέτας

Η συνάρτηση λαμβάνει ως είσοδο το όνομα και τη σειρά της στήλης.

Lets say, df['col'] = ['b','a','b','c']
  • order = []
  • order = ['a','b','c']
  • order = ['a']
def encode_label(df,col,order=[]) :
  if(order==[]) : order = list(df[col].unique())
  for i,cell in enumerate(df[col]) : 
    try : 
      df.at[i,col] = order.index(df[col][i])
    except : 
      df.at[i,col] = -1


One Hot Encoding

The function takes the column name as input.

Lets say, df['col'] = ['b','a','b','c']

After One Hot Encoding -
  • df['col_b'] = [1,0,1,0]
  • df['col_a'] = [0,1,0,0]
  • df['col_c'] = [0,0,0,1]
def encode_onehot(df,col) :
  k = {}
  n = df[col].shape[0]
  unique = df[col].unique()
  for unq in unique : k[unq] = [0]*n
  for i in range(n) :
    k[df.at[i,col]][i] = 1
  for unq in unique : df[f"{col}_{unq}"] = k[unq] 
  df.drop(col,axis=1,inplace=True)

Ενιαία Λειτουργία για Κωδικοποίηση Δεδομένων

def encode(df,cols) : 
  for col in cols.keys() : 
    if(cols[col] is None) : encode_onehot(df,col)
    else : encode_label(df,col,cols[col])
Μονή Συνάρτηση για Κωδικοποίηση Δεδομένων|  Προεπεξεργασία

Κανονικοποίηση δεδομένων

  • Διαίρεση με το μεγαλύτερο: Διαιρέστε όλες τις τιμές μιας στήλης με τη μεγαλύτερη τιμή σε αυτήν τη στήλη
  • Διαίρεση με σταθερά: Διαιρέστε όλες τις τιμές μιας στήλης με μια σταθερή τιμή (π.χ. 255 σε περίπτωση εικόνας)
  • Διαίρεση με Constant x Largesr: Διαιρέστε όλες τις τιμές μιας στήλης με μια δεδομένη σταθερά x μεγαλύτερη τιμή σε αυτήν τη στήλη
  • Κανονοποίηση Ελάχιστου-Μέγιστου: Αφαίρεση της ελάχιστης τιμής από όλες τις τιμές μιας στήλης και στη συνέχεια διαίρεση όλων των τιμών με τη μεγαλύτερη τιμή αυτής της στήλης (το νέο ελάχιστο θα είναι 0 και το νέο μέγιστο θα είναι 1)
  • Μέση κανονικοποίηση: Αφαίρεση του μέσου όρου από όλες τις τιμές μιας στήλης και στη συνέχεια διαίρεση όλων των τιμών με (μεγαλύτερη-μικρότερη).
# Dividing by largest
def normalize_dbl(df,cols,round=None) : 
  if(type(cols)!=list) : cols = [cols]
  for col in cols : 
    l = df[col].max()
    if round is None : df[col] = df[col].div(l)
    else : df[col] = df[col].div(l).round(round)
# Dividing by constant
def normalize_dbc(df,cols,round=None,c=1) :
  if(type(cols)!=list) : cols = [cols]
  for col in cols : 
    if round is None : df[col] = df[col].div(c)
    else : df[col] = df[col].div(c).round(round)
# Dividing by constant x largest
def normalize_dblc(df,cols,round=None,c=1) :
  if(type(cols)!=list) : cols = [cols]
  for col in cols : 
    l = df[col].max() * c
    if round is None : df[col] = df[col].div(l)
    else : df[col] = df[col].div(l).round(round)
# min-max normalization
def normalize_rescale(df,cols,round=None) :
  if(type(cols)!=list) : cols = [cols]
  for col in cols : 
    df[col] = df[col] - df[col].min()
    l = df[col].max()
    if round is None : df[col] = df[col].div(l)
    else : df[col] = df[col].div(l).round(round)
# mean normalization
def normalize_mean(df,cols,round=None) :
  if(type(cols)!=list) : cols = [cols]
  for col in cols : 
    mean = df[col].mean()
    l = df[col].max() - df[col].min()
    df[col] = df[col] - mean
    if round is None : df[col] = df[col].div(l)
    else : df[col] = df[col].div(l).round(round)


Single Function for Normalizing Data
def normalize(df,cols=None,kinds="dbl",round=None,c=1,exceptions=[]) :
  if(cols is None) : 
    cols = []
    for col in df : 
      if(pd.api.types.is_numeric_dtype(df[col])) : 
        if(max(df[col])>1 or min(df[col])<-1) : 
          if(col not in exceptions) : cols.append(col)
  if(type(cols)!=list) : cols = [cols]
  n = len(cols)
  if(type(kinds)!=list) : kinds = [kinds]*n
  for i,kind in enumerate(kinds) : 
    if(kind=='dbl') : normalize_dbl(df,cols[i],round)
    if(kind=='dbc') : normalize_dbc(df,cols[i],round,c)
    if(kind=='dblc') : normalize_dblc(df,cols[i],round,c)
    if(kind in ['min-max','rescale','scale']) : normalize_rescale(df,cols[i],round)
    if(kind=='mean') : normalize_mean(df,cols[i],round)

We can vastly vary the overall normalizations by easily making changes in the parameters of this function when we call it. This helps in experimenting with different normalizations.

Some examples of various ways in which we can normalize our data using this function –

If we want to normalize all columns (it detects numeric columns) –

normalize(df)

Αν θέλουμε να κάνουμε κανονικοποίηση και στρογγυλοποίηση σε 3 δεκαδικά ψηφία –

normalize(df,round=3)

Αν θέλουμε να κανονικοποιήσουμε όλες τις στήλες με άλλο είδος από τη διαίρεση με το μεγαλύτερο –

normalize(df,kinds="mean")

Αν θέλουμε να κανονικοποιήσουμε κάποιες στήλες με ένα είδος και κάποιες στήλες με άλλο είδος –

normalize(df,['Price','Horsepower'],'dbl')
normalize(df,['AirBags','Cylinders'],'min-max')
normalize(df,['RPM'],'dblc',c=1.25)

ή

normalize(df,['Price','AirBags','Cylinders','Horsepower','RPM'],['dbl','min-max','min-max','dbl','dblc'],c=1.25)

Αν θέλουμε να κανονικοποιήσουμε όλες τις στήλες εκτός από μερικές –

normalize(df,kinds="min-max",exceptions=['AirBags','RPM'],round=4)

Διαίρεση δεδομένων

Θα χρησιμοποιήσουμε το sklearn και θα δημιουργήσουμε μια συνάρτηση για να χωρίσουμε δεδομένα όπου δεν θα χρειάζεται καν να αναφέρουμε εάν χωρίζουμε τα δεδομένα μας σε 2 ή 3 μέρη.

Πρέπει επίσης να επαναφέρουμε τον δείκτη των x_train, x_test, κ.λπ., διαφορετικά, μπορεί να αντιμετωπίσουμε προβλήματα κατά την επανάληψη τους στο μέλλον.

from sklearn.model_selection import train_test_split
x = df.drop(['Price'], axis=1)
y = df.loc[:,'Price']

Way Split

def train_test(x,y,train_size=-1,test_size=-1) :

if(train_size==-1) : train_size = 1-test_size

x_train,x_test,y_train,y_test = train_test_split(x,y,train_size=train_size,random_state=101)

x_train.reset_index(drop=True,inplace=True)

x_test.reset_index(drop=True,inplace=True)

y_train.reset_index(drop=True,inplace=True)

y_test.reset_index(drop=True,inplace=True)

return x_train,x_test,y_train,y_test

Way Split

def train_val_test(x,y,train_size=-1,val_size=-1,test_size=-1) :

if(train_size==-1) : train_size = 1-val_size-test_size

if(val_size==-1) : val_size = 1-train_size-test_size

x_train,x_val,y_train,y_val = train_test_split(x,y,train_size=train_size,random_state=101)

x_val,x_test,y_val,y_test = train_test_split(x_val,y_val,train_size=(val_size/(1-train_size)),random_state=101)

x_train.reset_index(drop=True,inplace=True)

x_val.reset_index(drop=True,inplace=True)

x_test.reset_index(drop=True,inplace=True)

y_train.reset_index(drop=True,inplace=True)

y_val.reset_index(drop=True,inplace=True)

y_test.reset_index(drop=True,inplace=True)

return x_train,x_val,x_test,y_train,y_val,y_test

Μονή συνάρτηση για διαχωρισμό δεδομένων

Αν περάσουμε δύο μεγέθη στη συνάρτηση (π.χ. τρένο_μέγεθος & βαλ_μέγεθος) τότε θα είναι διαχωρισμός τριών κατευθύνσεων, αν περάσουμε ένα μέγεθος (π.χ. τρένο_μέγεθος) θα είναι διπλής κατεύθυνσης.

def split(x,y,train_size=-1,val_size=-1,test_size=-1):

if(train_size==-1 and val_size==-1) : return train_test(x,y,train_size=1-test_size)

if(train_size==-1 and test_size==-1) : return train_test(x,y,train_size=1-val_size)

if(val_size==-1 and test_size==-1) : return train_test(x,y,train_size=train_size)

επιστροφή train_val_test(x,y,train_size,val_size,test_size)

Διαχωρισμός δοκιμής επικύρωσης αμαξοστοιχίας

x_train,x_val,x_test,y_train,y_val,y_test = split(x,y,train_size=0.7,val_size=0.15)

Διαχωρισμός τρένου-δοκιμών:

x_train,x_test,y_train,y_test = split(x,y,train_size=0.75)

Συμπέρασμα για την προεπεξεργασία

Σε αυτό το άρθρο, εφαρμόσαμε λειτουργίες προεπεξεργασίας για τον καθαρισμό, την κωδικοποίηση, την κανονικοποίηση και τον διαχωρισμό δεδομένων. Είδαμε πώς η οργανωμένη προεπεξεργασία διευκολύνει τη δουλειά μας.

Μετά την εισαγωγή των δεδομένων, μπορούμε να τα προεπεξεργαζόμαστε σύμφωνα με τις ανάγκες μας 4 γραμμές. Μπορούμε να συνεχίσουμε να τροποποιούμε τις παραμέτρους για να πειραματιστούμε με διαφορετική προεπεξεργασία.

import pandas as pd
df = pd.read_csv(path+'Cars93.csv')
df = df[['Model','Manufacturer','Type','Price','AirBags','Cylinders','Horsepower','RPM']]
clean(df,exceptions_mismatch=['Model'])

encode(df,{'AirBags':['None','Driver only','Driver & Passenger'],'Type':None,'Manufacturer':[],'Model':[]})

normalize(df,['Price','AirBags','Cylinders','Horsepower','RPM'],'min-max')

x_train,x_test,y_train,y_test = split(df.drop(['Price'],axis=1),df.loc[:,'Price'],train_size=0.8)
Προεπεξεργασία

Βασικά Takeaways

  • Η οργανωμένη προεπεξεργασία εξοικονομεί χρόνο και μας βοηθά να προεπεξεργαζόμαστε διαφορετικά σύνολα δεδομένων και να δοκιμάζουμε διαφορετική προεπεξεργασία χωρίς πολλές αλλαγές στον κώδικα.
  • Καθαρισμός δεδομένων: Πρέπει να αφαιρέσουμε (ή να αντικαταστήσουμε) σειρές με τιμές na/nan, να καταργήσουμε σειρές με λάθος τύπο δεδομένων για οποιοδήποτε χαρακτηριστικό και να μετατρέψουμε τα αριθμητικά δεδομένα που είναι αποθηκευμένα ως μορφή συμβολοσειράς στο αρχείο CSV/excel στην αρχική τους μορφή.
  • Κωδικοποίηση δεδομένων: Πρέπει να κωδικοποιήσουμε δεδομένα καθώς τα περισσότερα μοντέλα ML απαιτούν αριθμητικά δεδομένα. Υλοποιήσαμε την κωδικοποίηση ετικετών και μία hot encoding.
  • Κανονικοποίηση δεδομένων: Βοηθά στη μείωση της προκατάληψης προς ένα χαρακτηριστικό και μερικές φορές μειώνει τον χρόνο υπολογισμού. Εφαρμόσαμε 5 τεχνικές κανονικοποίησης.
  • Διαχωρισμός δεδομένων: Πρέπει να χωρίσουμε τα δεδομένα μας στο τμήμα αμαξοστοιχίας (για την τοποθέτηση του μοντέλου) και στο τμήμα δοκιμής (για την αξιολόγηση του μοντέλου). Μερικές φορές, χωρίζουμε επίσης σε ένα τρίτο τμήμα – επικύρωση, το οποίο χρησιμοποιούμε για να βρούμε τις βέλτιστες παραμέτρους για το μοντέλο μας.

Ελπίζω αυτό το σεμινάριο να σας βοήθησε. Εκτός από την προεπεξεργασία, είναι καλό να κρατάμε οργανωμένο τον κώδικά μας, βοηθάει στην πραγματοποίηση αλλαγών αργότερα. Θα πρέπει επίσης να προσπαθήσουμε να δημιουργήσουμε καθολικές συναρτήσεις λαμβάνοντας το σύνολο δεδομένων ως όρισμα αντί να δημιουργούμε συναρτήσεις με σκληρό κώδικα που θα λειτουργούν μόνο για το σύνολο δεδομένων που χρησιμοποιούμε εκείνη τη στιγμή.

Τα μέσα που εμφανίζονται σε αυτό το άρθρο δεν ανήκουν στο Analytics Vidhya και χρησιμοποιούνται κατά την κρίση του συγγραφέα.