Rappresentazione: feature engineering

Nella programmazione tradizionale, l'attenzione è concentrata sul codice. Nei progetti di machine learning, l'attenzione si sposta sulla rappresentazione. In altre parole, un modo per perfezionare un modello è aggiungendo e migliorando le sue caratteristiche.

Mappatura di dati non elaborati alle caratteristiche

Il lato sinistro della Figura 1 mostra i dati non elaborati di un'origine dati di input; il lato destro mostra un vettore di caratteristiche, ovvero l'insieme di valori in virgola mobile che comprende gli esempi del set di dati. Feature engineering significa trasformare i dati non elaborati in un vettore di caratteristiche. Probabilmente dovrai dedicare molto tempo al feature engineering.

Molti modelli di machine learning devono rappresentare le caratteristiche come vettori numerati reali, poiché i valori delle caratteristiche devono essere moltiplicati per le ponderazioni del modello.

I dati non elaborati vengono mappati a un vettore di caratteristiche tramite un processo chiamato feature engineering.

Figura 1. Il feature engineering mappa i dati non elaborati alle caratteristiche di ML.

Mappatura di valori numerici

I dati interi e in virgola mobile non richiedono una codifica speciale perché possono essere moltiplicati per una ponderazione numerica. Come suggerito nella Figura 2, convertire il valore intero non elaborato 6 nel valore della caratteristica 6,0 è banale:

Esempio di una funzionalità che può essere copiata direttamente dai dati non elaborati

Figura 2. Mappare valori interi a valori in virgola mobile.

Mappatura dei valori categorici

Le caratteristiche di categoria hanno un insieme distinto di valori possibili. Ad esempio, potrebbe esistere una funzionalità chiamata street_name con opzioni che includono:

{'Charleston Road', 'North Shoreline Boulevard', 'Shorebird Way', 'Rengstorff Avenue'}

Poiché i modelli non possono moltiplicare le stringhe per i pesi appresi, utilizziamo il feature engineering per convertire le stringhe in valori numerici.

Possiamo farlo definendo una mappatura dai valori delle caratteristiche, che chiameremo vocabolario dei possibili valori, ai numeri interi. Poiché non tutte le strade del mondo saranno presenti nel nostro set di dati, possiamo raggruppare tutte le altre vie in una categoria "altro" generica, nota come bucket OOV (out-of-vocabulary).

Utilizzando questo approccio, ecco come possiamo mappare i nomi delle vie ai numeri:

  • mappa Charleston Road verso 0
  • mappa North Shoreline Boulevard al numero 1
  • mappa Shorebird Way to 2
  • mappa Rengstorff Avenue a 3
  • mappare tutto il resto (VOV) su 4

Tuttavia, se incorporiamo questi numeri di indice direttamente nel nostro modello, imporranno alcuni vincoli che potrebbero essere problematici:

  • Impareremo un singolo peso che si applica a tutte le strade. Ad esempio, se impariamo un peso di 6 per street_name, lo moltiplichiamo per 0 per Charleston Road, per 1 per North Shoreline Boulevard, 2 per Shorebird Way e così via. Prendiamo come esempio un modello che prevede i prezzi autopromozionali utilizzando street_name come funzionalità. È improbabile che ci sia un aggiustamento del prezzo lineare in base al nome della strada e questo presupporrebbe inoltre che tu abbia ordinato le strade in base al loro prezzo medio delle abitazioni. Il nostro modello richiede la flessibilità di apprendere pesi diversi per ogni strada che verranno aggiunti al prezzo stimato utilizzando le altre caratteristiche.

  • Non prendiamo in considerazione i casi in cui street_name può assumere più valori. Ad esempio, molte case si trovano all'angolo di due strade e non c'è modo di codificare queste informazioni nel valore street_name se contengono un singolo indice.

Per rimuovere entrambi questi vincoli, possiamo creare un vettore binario per ogni caratteristica categorica nel nostro modello che rappresenta i valori come segue:

  • Per i valori applicabili all'esempio, imposta gli elementi vettoriali corrispondenti su 1.
  • Imposta tutti gli altri elementi su 0.

La lunghezza di questo vettore è uguale al numero di elementi nel vocabolario. Questa rappresentazione è chiamata codifica one-hot quando un singolo valore è 1 e codifica multi-hot quando più valori sono 1.

La Figura 3 illustra la codifica one-hot di una determinata strada: Shorebird Way. L'elemento del vettore binario per Shorebird Way ha il valore 1, mentre gli elementi per tutte le altre strade hanno valore 0.

Mappatura di un valore stringa (

Figura 3. Mappatura dell'indirizzo tramite codifica one-hot.

Questo approccio crea in modo efficace una variabile booleana per ogni valore di caratteristica (ad es. il nome della via). Qui, se una casa si trova su Shorebird Way, il valore binario è 1 solo per Shorebird Way. Di conseguenza, il modello utilizza solo il peso per Shorebird Way.

Analogamente, se una casa si trova all'angolo di due strade, due valori binari sono impostati su 1 e il modello utilizza entrambe le rispettive ponderazioni.

Rappresentazione sparsa

Supponi di avere 1.000.000 di nomi di vie diversi nel set di dati che vuoi includere come valori per street_name. La creazione esplicita di un vettore binario di 1.000.000 di elementi in cui solo uno o due elementi sono veri è una rappresentazione molto inefficiente in termini di tempo di archiviazione e calcolo, durante l'elaborazione di questi vettori. In questo caso, un approccio comune consiste nell'utilizzare una rappresentazione sparsa in cui sono archiviati solo i valori diversi da zero. Nelle rappresentazioni sparse, viene comunque acquisita una ponderazione del modello indipendente per ogni valore delle caratteristiche, come descritto sopra.