master-thesis/src/chapter_2.md

7.3 KiB

Collezione dei dati e analisi preliminare

Selezione dei progetti

L'individuazione dei progetti da analizzare è avvenuta mediate l'ausilio dell'\ac{API} messa a disposizione da GitHub. In particolare è stata eseguita una query per ottenere una lista di repository che fanno uso di librerie e framework di \ac{ML} come TensorFlow, Pytorch e scikit-learn. In questo modo è stato possibile ottenere una lista di 26758 repository che è stata successivamente filtrata per individuare solo i progetti d'interesse per la seguente analisi.

L'operazione di filtraggio è avvenuta attraverso due fasi; una prima automatica e una seconda manuale. La prima fase ha avuto l'obiettivo di selezionare unicamente i repository popolari. Nella maggior parte dei casi viene utilizzato il numero di stelle come indice della popolarità di un progetto [@borges2016understandingfactorsthat], ma per questo lavoro si è preferito dare maggiore rilevanza ad altri aspetti, come il numero di fork, il numero di contributors e il numero di issues chiuse. Questa scelta è stata dettata dall'esigenza di selezionare non solo repository popolari, ma anche caratterizzati da una forte partecipazione della community.

I progetti che hanno superato questa prima selezione dovevano:

  • essere lavori originali, per cui sono stati esclusi tutti i fork.
  • avere almeno cento issues chiuse.
  • avere almeno dieci contributors.
  • avere almeno venticinque fork.

Alla fine di questa prima selezione il numero di repository si è ridotto a sessantasei e sono stati analizzati manualmente per rimuovere listati associati a libri e/o tutorial, progetti non in lingua inglese e librerie. Alla fine di questa seconda fase il numero di progetti è sceso a trenta.

Fetch di issues e commit

Una volta individuati i progetti da analizzare si è reso necessario recuperare l'intera storia dei progetti e le issues ad essi associate. Per entrambe le operazioni è stato utilizzato il tool perceval[@duenas2018percevalsoftwareproject]. Nel caso delle issues, essendo queste informazioni non direttamente contenute all'interno del repository git, è stato necessario utilizzare nuovamente l'\ac{API} di GitHub. Poiché le chiamate associate ad un singolo token sono limitate nel tempo si è scelto di configurare perseval in modo tale da introdurre in automatico uno ritardo ogni qualvolta veniva raggiunto il limite. Inoltre il codice è stato dispiegato su un \ac{VPS} in modo da poter eseguire il fetch senza che fosse necessario mantenere attiva una macchina fisica.

Con il processo precedentemente illustrato è stato possibile recuperare:

  • 34180 commit.
  • 15267 tra issues e pull request.

Classificazione dei dati

Classificazione delle issues

Al fine di poter eseguire un confronto tra i fix di \ac{ML} e quelli generici è stato necessario classificare sia le issues che i commit. Per quanto riguarda i primi si è scelto di attuare una classificazione basata sul testo, in particolare considerando il titolo e il corpo della issue, ma escludendo i commenti di risposta in modo da non rendere i dati troppo rumorosi. Il numero elevato di elementi non rende praticabile una classificazione manuale per cui si è optato per una classificazione automatica. A tal fine sono stati implementati ed analizzati due classificatori, uno supervisionato e uno non supervisionato.

I due modelli considerati sono:

  • un classificatore statico basato su una lista di vocaboli tipici del \ac{ML}.
  • un modello naïve Bayes [@2021naivebayesclassifier; @harrington2012machinelearningaction].

La classificazione mediate il classificatore statico non necessita di un labeling manuale dei dati, ma richiede la definizione dei vocaboli tipici del \ac{ML}. Questa lista non è stata costruita da zero, ma è basata su lavori precedenti[@humbatova-2019-taxonomyrealfaults]. In questo modo tutte le issues che utilizzavano almeno un vocabolo tipico del \acl{ML} sono state classificate come issues di \ac{ML}.

Nel caso del modello naïve Bayes, essendo questo un algoritmo di apprendimento supervisionato, si è resa necessaria una classificazione manuale delle issues. A tal scopo è stato eseguito un campionamento stratificato in base al progetto di provenienza di 376 issues che sono state divise tra due lettori e labellate. Durante il labeling si scelto di classificare ulteriormente le issue di \ac{ML} al fine di individuare anche la fase in cui il problema si è palesato. La definizioni delle varie fasi è avvenuta partendo da un lavoro di Microsoft[@amershi-2019-softwareengineeringmachine].

Le fasi considerate sono:

  • Model Requirements
  • Data Collection
  • Data Labeling
  • Data cleaning1
  • Feature Engineering
  • Model Training
  • Model Evaluation
  • Model Deployment
  • Model Monitoring

A partire dal dataset labellato è stato possibile costruire un training e un test set, mediante i quali è stato possibile allenare e valutare le performance del modello bayesiano. Mentre le performance del primo modello sono state valutate sull'intero dataset.

\begin{figure}[!ht] \subfloat[Numero di issues rispetto al tipo\label{fig:labeling-type}]{% \includegraphics[width=0.45\textwidth]{src/figures/count-type.pdf} } \hfill \subfloat[Numero di issues rispetto alla fase\label{fig:labeling-phases}]{% \includegraphics[width=0.45\textwidth]{src/figures/count-phases.pdf} } \caption{Risultati della classificazione manuale} \label{fig:labeling} \end{figure}

Al fine di poter confrontare i due modelli sono state utilizzate le metriche di precision e recall. Com'è possibile notare dai valori riportati in @tbl:confronto-modelli-classificazione-issues, il modello basato sulla lista di vocaboli è leggermente più preciso del modello bayesiano, ma presenta una recall decisamente più bassa. Dalla @fig:labeling-type si evince la natura minoritaria delle issues di \ac{ML} rispetto alle issues generiche, per questo motivo si è scelto di preferire il modello naïve Bayes in modo da perdere quante meno istanze possibili anche a costo di sacrificare leggermente la precisione.

Classificatore statico naïve Bayes
precision 0.46 0.41
recall 0.74 0.94

: Confronto dei due modelli per la classificazione delle issues. {#tbl:confronto-modelli-classificazione-issues}

Classificazione dei commit

Prima di poter classificare i commit si è reso necessaria un'ulteriore fase di filtraggio in modo da poter separare i commit di issue fixing da quelli generici. Sono stati considerati come commit di fix tutti quei commit al cui interno veniva fatto riferimento a delle issues attraverso la notazione "#". Questa operazione ha ridotto il dataset dei commit a 3321 unità.

A questo punto è stato possibile separare i fix di \acl{ML} e quelli generici. La classificazione è avvenuta attraverso la lista delle issues citate all'interno del commit message e sono stati considerati come commit di \ac{ML} tutti quei commit che facevano riferimento ad almeno una issue di \ac{ML}.


  1. Nella fase di Data Cleaning non rientrano soltanto le operazioni strettamente di pulizia come ad esempio rimozione di record rumorosi o incompleti, ma tutte le trasformazioni eseguite sui dati, quindi anche operazioni di standardizzazione, flip di immagini ecc. ↩︎