Un lavoro di analisi dati inizia sempre data un dataset. Questo può essere stato consegnato dal cliente, trovato pubblicamente su siti come Kaggle.com oppure creato da noi e il nostro team.

In qualsiasi di questi casi, il dataset mostrerà una anatomia che varierà in base al tipo di fenomeno che vuole descrivere, e avrà un certo numero di colonne che comporranno tale struttura.

Durante lo sviluppo del nostro progetto, il team sarà interessato a diversi aspetti di questo dataset:

  1. Quanto i dati contenuti in esso sono rappresentativi del fenomeno che deve descrivere?
  2. Quali sono i data type delle nostre colonne?
  3. Quante righe e quante colonne sono presenti?

E molte altre. Diventa importante rispondere a queste domande perché contribuiscono a definire l'ambito di indagine del nostro team. Ci aiutano a capire quanta EDA (exploratory data analysis, analisi esplorativa del dato) fare, cosa possiamo predire e in che modo farlo (con il machine learning oppure con altri metodi statistici) e a strutturare un piano di preprocessing del dato.

Ho toccato alcuni di questi temi in articoli dedicati. Puoi leggerli qui

Una pipeline di analisi passa solitamente attraverso diversi step, e uno di questi prende il nome di feature engineering (ingegnerizzazione delle feature).

Durante questa fase, l'analista modifica, trasforma e aggiunge le colonne (anche dette feature, dimensioni, variabili e così via) presenti nel dataset con lo scopo di arricchire le informazioni riguardo al fenomeno che viene descritto. Solitamente questo viene fatto in vista di una fase di modellazione del fenomeno stesso.

Ad esempio, se stiamo studiando una serie temporale, una attività di feature engineering può essere quella di creare delle colonne addizionali partendo dalla data presente all'interno della serie per estrarre anno, mese, giorno, giorni appartenenti al weekend e così via.

L'ipotesi è che la variabile target (se stiamo parlando di apprendimento supervisionato) può essere modellata meglio se andiamo ad aggiungere più informazioni - in questo caso stiamo andando ad arricchire la serie andando ad ingegnerizzare le feature temporali.

Ma a volte questo processo può creare problemi invece che risolverne, e può essere difficile riconoscere le cause di tali problematiche. Queste portano, spesso e volentieri, ad overfittare il training set.

Ho già scritto di overfitting e del perché sia uno dei maggiori ostacoli nel machine learning. Vi consiglio di dare una lettura a questo articolo se vi interessa scoprire di più al riguardo.

In questo articolo scriverò nello specifico delle problematiche che possono sorgere quando ci si spinge troppo in là con il feature engineering, quindi quando si aggiungono troppe informazioni.

Perché fare feature engineering?

Il motivo che ci spinge a fare feature engineering è quello di aumentare la disponibilità di informazioni di valore e addestrare il modello includendo questa "prospettiva" nuova sui dati.

L'interpretazione di questa attività è, giustamente, corretta. Voler aggiungere informazione è generalmente una attività da perseguire, ma solo se si ha certezza che il dato sia in realtà veramente utile al modello.

Come spesso scrivo e pubblico sul web, la nostra prima preoccupazione dovrebbe quella di raccogliere dati di alta qualità, possibilmente quanti più possibili, in modo da poter rappresentare al meglio il fenomeno che vogliamo studiare e modellare.

Per "alta qualità" intendo dati che contengono esempi quanto più vicini alla realtà osservabile di un evento del mondo.

Vogliamo essere sicuri che le risposte alle nostre domande siano contenute nel nostro dataset.

Fare feature engineering, quindi, può aiutarci nel rispondere a tali domande in una fase di analisi oppure aiutare il nostro modello a trovare una via più facile nel predire il target.

Perché è un problema avere un grosso numero di feature?

L'analista incauto però potrebbe incorrere in problemi se inserisce troppe variabili nuove nel suo dataset.

Alcune di queste potrebbero effettivamente essere utili, altre potrebbero addirittura ostacolare il nostro modello alla generalizzazione.

Un modello che riceve delle informazioni potenzialmente irrilevanti farà più difficoltà a generalizzare correttamente il fenomeno.

Formalizzando, l'analista potrebbe commettere degli errori se aggiunge troppe colonne al suo dataset, quali

  • aggiungere informazioni non rilevanti, aumentando il rapporto segnale / rumore (signal-to-noise ratio)
  • aumentare la complessità del fenomeno da mappare
  • inserire dei confound nel dataset
  • avere più colonne che righe

Ognuno di questi aspetti può influenzare negativamente l'abilità del nostro modello a dare risultati usabili. Vediamo come.

Aggiungere informazioni non rilevanti (aumentare il rapporto segnale-rumore)

Più gli esempi nel nostro dataset sono rappresentativi del fenomeno, più il rapporto segnale-rumore sarà alto. Vogliamo sempre massimizzare questo rapporto in modo tale da poter allineare quanto più possibile il campione con la popolazione di dati raccolti.

Ogni esempio nel nostro dataset dovrebbe essere descritto da certe feature che lo rendono rappresentativo del fenomeno che vogliamo studiare.

Se questo non avviene, rendiamo tale esempio essenzialmente inutile. Questa inutilità non viene però filtrata dal nostro modello, che cercherà di apprendere il modo migliore di mappare \( X \) a \( y \) usando queste informazioni rumorose. Questo deteriora le performance del modello.

Aumentare la complessità del fenomeno da mappare

Più complesso è il fenomeno che vogliamo modellare, più sarà difficile per il modello trovare una funzione che descriva il suo comportamento.

Cosa si intende per complessità? In questo caso si intende il numero di colonne. Ogni colonna descrive qualcosa del fenomeno, e una descrizione più ricca cresce naturalmente di complessità.

A volte un fenomeno è intrinsecamente complesso da modellare (come ad esempio fare previsioni meteorologiche) - in questo caso dobbiamo essere abili a comprendere quanto le colonne che aggiungiamo vadano a complicare ulteriormente il problema.

Inserire dei confound

Un confound è una variabile che "confonde" il modello. Variabili correlate tra di loro, ma che non sono realmente impattanti (correlazioni spurie e simili) possono confondere il modello in fase di training.

In questo caso, il modello impara erroneamente che la variabile \( K \) esercita un grosso impatto sul target - quando poi quest'ultimo viene deployato in produzione le performance risultano lontane da quelle viste in training.

Anche in questo caso, la soluzione è la stessa: studiare attentamente la natura della variabile aggiunta al dataset, ragionando su come questa potrebbe effettivamente aiutare il modello.

Avere più colonne che righe

Questo è uno scenario un po' limite, ma può accadere se l'analista utilizza librerie esterne per fare feature engineering. Ad esempio, se si vuole fare FE su una serie temporale formata da candele finanziarie, delle librerie di analisi tecnica andrebbero ad applicare centinaia di colonne in più al dataset.

Ragiono in questo modo quando si parla di valutare numero di colonne vs numero di righe

Colonne: cose da apprendere
Righe: esempi dai quali apprendere

Tendenzialmente, il mio consiglio è quello di evitare sempre lo scenario dove abbiamo più colonne che righe.

Come identificare le feature più importanti?

Abbiamo visto come avere un processo troppo liberale di feature engineering possa arrecare danno al nostro modello.

Il processo per identificare invece quali siano le feature da includere, poiché importanti, nel nostro dataset si chiama feature selection.

La selezione delle feature ci aiuta a isolare le variabili che contribuiscono di più alla performance del modello.

Ci sono vari approcci alla feature selection. Questo articolo non andrà in dettaglio in questo tema, ma posso linkarvi un pezzo su Boruta, una libreria per la feature selection in Python. Questa libreria è facile da usare e permette di calcolare l'importanza di ogni feature nel dataset. Una feature importante è sicuramente da includere nel training set, mentre alcune potrebbero essere addirittura rimosse o trasformate.

📂
Un collega data scientist chiamato Andrea Palladino ha pubblicato un repository Git implementando una tecnica emergente di feature selection. Tale tecnica inserisce delle feature rumorose all'interno del dataset, rendendo le feature rilevanti più salienti e quindi identificabili.
GitHub - apalladi/feature-selection-adding-noise
Contribute to apalladi/feature-selection-adding-noise development by creating an account on GitHub.

Conclusione

L'ingegnerizzazione delle feature è sicuramente una attività alla quale dobbiamo sempre pensare, ma con una attenzione a non strafare.

È facile pensare che una certa variabile possa avere un impatto positivo delle performance del modello - il modo migliore per testare una ipotesi è proprio quella di sperimentare. Boruta aiuta proprio a questo: all'inserimento di una nuova variabile possiamo usare questa libreria (insieme ad altri approcci) per stimare la rilevanza di tale feature sui risultati.

Qualora non volessimo studiare le feature con un processo di selezione, il consiglio è quello di andare ad evitare gli ostacoli menzionati e di valutare come le performance del modello cambino all'inserimento graduale di più variabili.