Esercizio - Creare un modello di Machine Learning

Completato

Per creare un modello di Machine Learning sono necessari due set di dati: uno per il training e uno per i test. Nella realtà spesso si ha un solo set di dati, quindi occorre dividerlo in due parti. In questo esercizio si eseguirà una divisione 80-20 sul DataFrame preparato nel lab precedente in modo da poterlo usare per il training di un modello di Machine Learning. Il DataFrame verrà anche separato in colonne delle caratteristiche e colonne delle etichette. Il primo contiene le colonne usate come input per il modello, ad esempio l'origine e la destinazione del volo e l'orario di partenza previsto, mentre il secondo contiene la colonna che il modello tenterà di prevedere, in questo caso la colonna ARR_DEL15 che indica se un volo arriverà puntuale.

  1. Tornare al notebook di Azure creato nella sezione precedente. Se il notebook è stato chiuso, è possibile accedere di nuovo al portale di Microsoft Azure Notebooks, aprire il notebook e usare Cell ->Run All (Cella > Esegui tutto) per eseguire di nuovo tutte le celle del notebook dopo averlo aperto.

  2. In una nuova cella alla fine del notebook immettere ed eseguire le istruzioni seguenti:

    from sklearn.model_selection import train_test_split
    train_x, test_x, train_y, test_y = train_test_split(df.drop('ARR_DEL15', axis=1), df['ARR_DEL15'], test_size=0.2, random_state=42)
    

    La prima istruzione importa la funzione helper train_test_split di sckit-learn. La seconda riga usa la funzione per dividere il DataFrame in un training set contenente l'80% dei dati originali e un set di test contenente il rimanente 20%. Il parametro random_state inizializza il generatore di numeri casuali usato per eseguire la divisione, mentre il primo e secondo parametro sono DataFrame contenenti le colonne delle caratteristiche e la colonna delle etichette.

  3. train_test_split restituisce quattro DataFrame. Usare il comando seguente per visualizzare il numero di righe e colonne nel DataFrame contenente le colonne delle caratteristiche usate per il training:

    train_x.shape
    
  4. Ora usare questo comando per visualizzare il numero di righe e colonne nel DataFrame contenente le colonne delle caratteristiche usate per i test:

    test_x.shape
    

    Quali sono le differenze tra i due output e perché sono diversi?

Cosa si vedrebbe se si chiamasse shape sugli altri due DataFrame, train_y e test_y? Si può provare a scoprirlo.

Esistono molti tipi di modelli di Machine Learning. Uno dei più comuni è il modello di regressione che usa uno di una serie di algoritmi di regressione per produrre un valore numerico, ad esempio l'età di una persona o la probabilità che una transazione con carta di credito sia fraudolenta. Si eseguirà il training di un modello di classificazione che tenta di risolvere un set di input in uno di un set di output noti. Un esempio classico di modello di classificazione è quello che esamina i messaggi di posta elettronica e li classifica come "posta indesiderata" o "posta non desiderata". Il modello sarà un modello di classificazione binario che stima se un volo arriverà in orario o in ritardo ("binario" perché sono presenti solo due output possibili).

Uno dei vantaggi dell'uso di sckit-learn è costituito dal fatto che non è necessario creare questi modelli o implementarne gli algoritmi manualmente. Sckit-learn include una vasta gamma di classi per implementare modelli di Machine Learning comuni. Una di queste è RandomForestClassifier che adatta più alberi delle decisioni ai dati e usa la media per migliorare l'accuratezza complessiva e limitare l'overfitting.

  1. Eseguire il codice seguente in una nuova cella per creare un oggetto RandomForestClassifier ed eseguirne il training chiamando il metodo fit.

    from sklearn.ensemble import RandomForestClassifier
    
    model = RandomForestClassifier(random_state=13)
    model.fit(train_x, train_y)
    

    Nell'output sono visualizzati i parametri usati nel classificatore, tra cui n_estimators che specifica il numero di alberi in ogni foresta di alberi delle decisioni e max_depth che specifica la profondità massima degli alberi delle decisioni. I valori visualizzati sono quelli predefiniti, ma è possibile sostituirli durante la creazione dell'oggetto RandomForestClassifier.

    Training the model.

    Training del modello

  2. Ora chiamare il metodo predict per testare il modello usando i valori inclusi in test_x, seguito dal metodo score per determinare l'accuratezza media del modello:

    predicted = model.predict(test_x)
    model.score(test_x, test_y)
    

    Verificare che l'output visualizzato sia il seguente:

    Testing the model.

    Test del modello

L'accuratezza media è dell'86%, che a prima vista sembra una buona percentuale. Tuttavia, l'accuratezza media non sempre è un indicatore affidabile dell'accuratezza di un modello di classificazione. È possibile eseguire un'analisi più approfondita per determinare la reale accuratezza del modello, ovvero quanto sia in grado di determinare se un volo arriverà puntuale.

Per misurare l'accuratezza di un modello di classificazione esistono diversi modi. Una delle misure complessive migliori per un modello di classificazione binario è la curva ROC (Area Under Receiver Operating Characteristic), talvolta definita "ROC AUC", che essenzialmente quantifica con quale frequenza il modello produrrà una previsione corretta indipendentemente dal risultato. In questa unità si calcolerà un punteggio ROC AUC per il modello creato in precedenza e si apprenderanno alcuni dei motivi per cui questo punteggio è inferiore rispetto all'output di accuratezza media restituito dal metodo score. Si apprenderanno anche altri modi per misurare l'accuratezza del modello.

  1. Prima di calcolare la curva ROC AUC è necessario generare le probabilità di previsione per il set di test. Queste probabilità sono stime per ognuna delle classi, o delle risposte, che il modello è in grado di prevedere. Ad esempio, [0.88199435, 0.11800565] indica che esiste l'89% di possibilità che un volo arriverà puntuale (ARR_DEL15 = 0) e il 12% di possibilità che non arriverà puntuale (ARR_DEL15 = 1). La somma delle due probabilità equivale al 100%.

    Eseguire il codice seguente per generare un set di probabilità di previsione dai dati di test:

    from sklearn.metrics import roc_auc_score
    probabilities = model.predict_proba(test_x)
    
  2. Ora usare l'istruzione seguente per generare un punteggio ROC AUC dalle probabilità usando il metodo roc_auc_score di sckit-learn:

    roc_auc_score(test_y, probabilities[:, 1])
    

    Verificare che l'output indichi un punteggio del 67%:

    Generating an AUC score.

    Generazione di un punteggio AUC

    Perché il punteggio AUC è inferiore all'accuratezza media calcolata nell'esercizio precedente?

    L'output del metodo score riflette il numero di elementi nel set di test che il modello ha previsto correttamente. Questo punteggio viene alterato dal fatto che nel set di dati con il quale il modello è stato sottoposto a training e testato le righe che rappresentano arrivi puntuali sono molte di più rispetto a quelle che rappresentano arrivi in ritardo. A causa di questo squilibrio nei dati, le probabilità di una previsione corretta sono superiori se si prevede che un volo sarà puntuale rispetto a quando si prevede che un volo sarà in ritardo.

    La curva ROC AUC tiene conto di questo aspetto e offre un'indicazione più accurata di quanto sia probabile che una previsione di arrivo puntuale o in ritardo sarà corretta.

  3. Per altre informazioni sul comportamento del modello è possibile generare una matrice di confusione, anche nota come matrice di errore. La matrice di confusione quantifica il numero di volte in cui ogni risposta è stata classificata correttamente o non correttamente. In particolare, quantifica il numero di falsi positivi, falsi negativi, veri positivi e veri negativi. Questo è importante perché se un modello di classificazione binario sottoposto a training per riconoscere cani e gatti viene testato con un set di dati costituito per il 95% dal valore "cane", potrebbe raggiungere il 95% semplicemente ipotizzando "cane" ogni volta. Ma se non riesce a identificare affatto i gatti, servirebbe a poco.

    Usare il codice seguente per produrre una matrice di confusione per il modello:

    from sklearn.metrics import confusion_matrix
    confusion_matrix(test_y, predicted)
    

    La prima riga nell'output rappresenta i voli arrivati puntuali. La prima colonna nella riga indica il numero di voli per i quali è stata prodotta una previsione di puntualità corretta, mentre la seconda colonna rivela il numero di voli con una previsione di ritardo, ma che non sono arrivati in ritardo. Quindi, il modello sembra essere in grado di prevedere che un volo sarà puntuale.

    Generating a confusion matrix.

    Generazione di una matrice di confusione

    Si osservi tuttavia la seconda riga che rappresenta i voli in ritardo. La prima colonna indica il numero di voli in ritardo per i quali è stata prodotta una previsione di puntualità non corretta. La seconda colonna indica il numero di voli per i quali è stata prodotta una previsione di ritardo corretta. Il modello ha chiaramente una maggiore capacità di prevedere che un volo arriverà in orario rispetto alla capacità di prevedere che un volo sarà in ritardo. Una matrice di confusione deve avere numeri elevati negli angoli superiore sinistro e inferiore destro e numeri bassi (preferibilmente zero) negli angoli superiore destro e inferiore sinistro.

  4. Altre misure di accuratezza per un modello di classificazione includono la precisione e il richiamo. Si supponga che al modello siano stati presentati tre arrivi puntuali e tre arrivi in ritardo e che esso abbia previsto correttamente due degli arrivi puntuali, ma che abbia previsto erroneamente che due degli arrivi in ritardo sarebbero stati puntuali. In questo caso la precisione sarebbe del 50% (due dei quattro voli classificati come puntuali effettivamente lo sono stati), mentre il richiamo sarebbe del 67% (due dei tre arrivi puntuali sono stati identificati correttamente). Per altre informazioni sulla precisione e il richiamo, vedere https://en.wikipedia.org/wiki/Precision_and_recall

    Sckit-learn contiene un pratico metodo denominato precision_score per il calcolo della precisione. Per quantificare la precisione del modello, eseguire le istruzioni seguenti:

    from sklearn.metrics import precision_score
    
    train_predictions = model.predict(train_x)
    precision_score(train_y, train_predictions)
    

    Esaminare l'output. Cos'è la precisione del modello?

    Measuring precision.

    Misurazione della precisione

  5. Sckit-learn contiene anche un metodo denominato recall_score per il calcolo del richiamo. Per misurare il richiamo del modello, eseguire le istruzioni seguenti:

    from sklearn.metrics import recall_score
    
    recall_score(train_y, train_predictions)
    

    Cos'è il richiamo del modello?

    Measuring recall.

    Misurazione del richiamo

  6. Usare il comando File ->Salva ed esegui checkpoint per salvare il notebook.

Nel mondo reale un data scientist esperto proverà a rendere il modello ancora più accurato. Tra le altre cose, proverà diversi algoritmi e adotterà le misure necessarie per ottimizzare l'algoritmo scelto al fine di trovare la combinazione di parametri ottimale. Un altro probabile passaggio sarà l'espansione del set di dati a milioni di righe anziché poche migliaia, nonché il tentativo di ridurre lo squilibrio tra gli arrivi in ritardo e quelli puntuali. Per gli scopi di questa esercitazione, tuttavia, il modello va bene così com'è.