Programma
Come data scientist, di solito non ci occupiamo di deployment e manutenzione: costruiamo i modelli statistici e gli ingegneri fanno il resto.
Tuttavia, le cose stanno iniziando a cambiare!
Con la crescente richiesta di data scientist in grado di colmare il divario tra creazione del modello e produzione, familiarizzare con strumenti di automazione e CI/CD (Continuous Integration/Continuous Deployment) può darti un vantaggio strategico.
In questo tutorial impareremo a conoscere due popolari strumenti di automazione: Make (automazione locale) e GitHub Actions (automazione in cloud). L’obiettivo principale sarà capire come integrarli nei nostri progetti dati.

GitHub Action e Make. Immagine di Abid Ali Awan.
Se vuoi approfondire l’automazione nel contesto della data science, dai un’occhiata a questo corso su Fully Automated MLOps.
Introduzione a MakeFile
Un Makefile è una sorta di blueprint per costruire e gestire progetti software. È un file che contiene istruzioni per automatizzare attività, semplificare processi di build complessi e garantire coerenza.
Per eseguire i comandi all’interno del Makefile usiamo lo strumento da riga di comando make. Questo tool può essere avviato come un programma Python passando argomenti oppure eseguito da solo.
Componenti principali
Un Makefile di solito è composto da un elenco di target, dipendenze, azioni e variabili:
- Target: sono i risultati desiderati, come "build", "test" o "clean". Immaginali come gli obiettivi da raggiungere tramite il Makefile.
- Dipendenze: sono i file necessari per generare il target. Pensale come gli ingredienti richiesti per ciascuna ricetta (target).
- Azioni: sono le istruzioni o gli script che indicano al sistema come costruire il target. Possono includere comandi come
python test.py. - Variabili: i Makefile offrono variabili globali che funzionano come argomenti passati alle azioni. Usando l’esempio di azione sopra, potremmo avere
python test.py $variable_1 $variable_2.
In breve, il template di un MakeFile potrebbe essere così:
Variable = some_value
Target: Dependencies
Actions (commands to build the target) $Variable
Usando gli esempi sopra, il MakeFile potrebbe apparire così:
# Define variables
variable_1 = 5
variable_2 = 10
# Target to run a test with variables
test: test_data.txt # Dependency on test data file
python test.py $variable_1 $variable_2
Installare il tool CLI Make
Possiamo installare lo strumento Make CLI su tutti i sistemi operativi.
Linux
Su Linux, usa il seguente comando nel terminale:
$ sudo apt install make
MacOS
Su macOS, possiamo usare Homebrew per installare make:
$ brew install make
Windows
Windows è un po’ diverso. Il tool Make può essere usato in vari modi. Le opzioni più popolari sono WSL (Ubuntu Linux), w64devkit e GnuWin32.
Scarichiamo e installiamo GnuWin32 dalla pagina SourceForge.
Per usarlo come strumento da riga di comando nel terminale, dobbiamo aggiungere il percorso della cartella alla variabile d’ambiente di Windows. Ecco i passaggi che possiamo seguire:
- Cerca "environment variables" nel menu Start: verrai reindirizzato alla finestra Proprietà del sistema.
- Nella finestra Proprietà del sistema, fai clic sul pulsante Variabili d’ambiente.
- Nella sezione variabili di sistema, trova la variabile "Path" e modificala: si aprirà un’altra finestra dove potrai aggiungere il nuovo percorso della directory di Make.

Per verificare se Make è stato installato correttamente, possiamo digitare make -h in PowerShell.

Usare MakeFile in un progetto di Data Science
In questa sezione impareremo a usare Makefile e gli strumenti CLI di Make in un progetto di data science.
Useremo il dataset World Happiness Report 2023 per coprire elaborazione dei dati, analisi e salvataggio di riepiloghi e visualizzazioni.
Configurazione
Iniziamo andando nella directory del progetto e creando una cartella chiamata Makefile-Action. Poi creiamo il file data_processing.py all’interno di quella cartella e avviamo l’editor VSCode.
$ cd GitHub
$ mkdir Makefile-Action
$ cd .\Makefile-Action\
$ code data_processing.py
Elaborazione dei dati
Cominciamo a elaborare i dati con Python. Nel blocco di codice sotto, eseguiamo i seguenti passaggi (nota: è un esempio—in uno scenario reale probabilmente dovremmo fare di più):
- Caricare il dataset grezzo dalla posizione fornita dall’utente.
- Rinominare tutte le colonne per migliorarne la leggibilità.
- Compilare i valori mancanti.
- Salvare il dataset pulito.
File: data_processing.py
import sys
import pandas as pd
# Check if the data location argument is provided
if len(sys.argv) != 2:
print("Usage: python data_processing.py <data_location>")
sys.exit(1)
# Load the raw dataset (step 1)
df = pd.read_csv(sys.argv[1])
# Rename columns to more descriptive names (step 2)
df.columns = [
"Country",
"Happiness Score",
"Happiness Score Error",
"Upper Whisker",
"Lower Whisker",
"GDP per Capita",
"Social Support",
"Healthy Life Expectancy",
"Freedom to Make Life Choices",
"Generosity",
"Perceptions of Corruption",
"Dystopia Happiness Score",
"GDP per Capita",
"Social Support",
"Healthy Life Expectancy",
"Freedom to Make Life Choices",
"Generosity",
"Perceptions of Corruption",
"Dystopia Residual",
]
# Handle missing values by replacing them with the mean (step 3)
df.fillna(df.mean(numeric_only=True), inplace=True)
# Check for missing values after cleaning
print("Missing values after cleaning:")
print(df.isnull().sum())
print(df.head())
# Save the cleaned and normalized dataset to a new CSV file (step 4)
df.to_csv("processed_data\WHR2023_cleaned.csv", index=False)
Analisi dei dati
Ora proseguiamo con l’analisi dei dati e salviamo tutto il codice in un file chiamato data_analysis.py. Possiamo creare questo file con il seguente comando da terminale:
$ code data_analysis.py
Possiamo anche usare il comando echo per creare il file Python e aprirlo in un diverso editor di codice.
$ echo "" > data_analysis.py
Nel blocco di codice seguente, eseguiamo:
- Caricamento del dataset pulito usando l’input fornito dall’utente.
- Generazione del riepilogo dei dati, delle informazioni e delle prime 5 righe del DataFrame, salvandole in un file TXT.
- Creazione delle visualizzazioni per:
- Distribuzione degli indici di felicità
- Top 20 paesi per indice di felicità
- Indice di felicità rispetto al PIL pro capite
- Indice di felicità rispetto al supporto sociale
- Heatmap delle correlazioni
- Salvataggio di tutte le visualizzazioni nella cartella “figures”.
File: data_analysis.py
import io
import sys
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
# Check if the data location argument is provided
if len(sys.argv) != 2:
print("Usage: python data_analysis.py <data_location>")
sys.exit(1)
# Load the clean dataset (step 1)
df = pd.read_csv(sys.argv[1])
# Data summary (step 2)
print("Data Summary:")
summary = df.describe()
data_head = df.head()
print(summary)
print(data_head)
# Collecting data information
buffer = io.StringIO()
df.info(buf=buffer)
info = buffer.getvalue()
## Write metrics to file
with open("processed_data/summary.txt", "w") as outfile:
f"\n## Data Summary\n\n{summary}\n\n## Data Info\n\n{info}\n\n## Dataframe\n\n{data_head}"
print("Data summary saved in processed_data folder!")
# Distribution of Happiness Score (step 3)
plt.figure(figsize=(10, 6))
sns.displot(df["Happiness Score"])
plt.title("Distribution of Happiness Score")
plt.xlabel("Happiness Score")
plt.ylabel("Frequency")
plt.savefig("figures/happiness_score_distribution.png")
# Top 20 countries by Happiness Score
top_20_countries = df.nlargest(20, "Happiness Score")
plt.figure(figsize=(10, 6))
sns.barplot(x="Country", y="Happiness Score", data=top_20_countries)
plt.title("Top 20 Countries by Happiness Score")
plt.xlabel("Country")
plt.ylabel("Happiness Score")
plt.xticks(rotation=90)
plt.savefig("figures/top_20_countries_by_happiness_score.png")
# Scatter plot of Happiness Score vs GDP per Capita
plt.figure(figsize=(10, 6))
sns.scatterplot(x="GDP per Capita", y="Happiness Score", data=df)
plt.title("Happiness Score vs GDP per Capita")
plt.xlabel("GDP per Capita")
plt.ylabel("Happiness Score")
plt.savefig("figures/happiness_score_vs_gdp_per_capita.png")
# Visualize the relationship between Happiness Score and Social Support
plt.figure(figsize=(10, 6))
plt.scatter(x="Social Support", y="Happiness Score", data=df)
plt.xlabel("Social Support")
plt.ylabel("Happiness Score")
plt.title("Relationship between Social Support and Happiness Score")
plt.savefig("figures/social_support_happiness_relationship.png")
# Heatmap of correlations between variables
corr_matrix = df.drop("Country", axis=1).corr()
plt.figure(figsize=(12, 10))
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm", square=True)
plt.title("Correlation Heatmap")
plt.savefig("figures/correlation_heatmap.png")
print("Visualizations saved to figures folder!")
Creare il Makefile
Prima di creare un Makefile, dobbiamo predisporre un file requirements.txt per installare tutti i pacchetti Python necessari su una nuova macchina. Ecco come apparirà il file requirements.txt:
pandas
numpy
seaborn
matplotlib
black
Il nostro Makefile è composto da variabili, dipendenze, target e azioni: vedremo tutti i mattoni fondamentali. Creiamo un file chiamato Makefile e iniziamo ad aggiungere le azioni per i target:
- install: aggiorna la versione di pip e installa tutti i pacchetti Python necessari usando il file requirements.txt.
- format: formatta tutti i file Python usando lo strumento Black.
- process: esegue il file Python `data_processing.py` con un percorso dei dati grezzi come variabile e dipendenza.
- analyze: esegue il file Python `data_analysis.py` con un percorso dei dati processati come variabile e dipendenza.
- clean: rimuove tutti i file e le figure generati durante l’esecuzione dei file Python.
- all: esegue in sequenza tutti i target validi.
File: Makefile
RAW_DATA_PATH = "raw_data/WHR2023.csv"
PROCESSED_DATA = "processed_data/WHR2023_cleaned.csv"
install:
pip install --upgrade pip &&\
pip install -r requirements.txt
format:
black *.py --line-length 88
process: ./raw_data/WHR2023.csv
python data_processing.py $(RAW_DATA_PATH)
analyze: ./processed_data/WHR2023_cleaned.csv
python data_analysis.py $(PROCESSED_DATA)
clean:
rm -f processed_data/* **/*.png
all: install format process analyze
Per eseguire un target, useremo lo strumento make e forniremo il nome del target nel terminale.
$ make format
Lo script Black è stato eseguito correttamente.

Proviamo a eseguire lo script Python per l’elaborazione dei dati.
È importante notare che, prima di eseguire il target process, controlla le dipendenze del target. Nel nostro caso verifica che esista il file di dati grezzi. Se non c’è, il comando non partirà.
$ make process
Come vedi, è semplicissimo.

Puoi persino sovrascrivere la variabile esistente passando un argomento aggiuntivo al comando make.
Nel nostro caso, abbiamo cambiato il percorso dei dati grezzi.
$ make process RAW_DATA_PATH="WHR2022.csv"
Lo script Python è stato eseguito con un argomento di input diverso.

Per automatizzare l’intero workflow, useremo all come target, che eseguirà in ordine i target install, format, process e analyze.
$ make all
Il comando make ha installato i pacchetti Python, formattato il codice, elaborato i dati e salvato riepilogo e visualizzazioni.


Ecco come dovrebbe apparire la directory del progetto dopo aver eseguito il comando make all:

Introduzione a GitHub Actions
Se Make eccelle nell’automazione locale all’interno dell’ambiente di sviluppo, GitHub Actions offre un’alternativa in cloud.
GitHub Actions si usa in genere per il CI/CD, che consente agli sviluppatori di compilare, buildare, testare e distribuire l’applicazione in produzione direttamente da GitHub.
Per esempio, possiamo creare un workflow personalizzato che si attiva in base a eventi specifici come push o pull request. Quel workflow eseguirà script shell e script Python, oppure potremo usare azioni predefinite. Il workflow personalizzato è un file YML, e di solito è piuttosto semplice da capire e da cui iniziare a scrivere run e azioni personalizzate.
Componenti principali
Vediamo i componenti fondamentali di GitHub Actions:
- Workflow definiti tramite file YML, che specificano i passaggi da eseguire e le condizioni di esecuzione.
- Eventi sono attività specifiche che attivano l’esecuzione di un workflow, come push, pull_request, schedule e altri.
- Runner sono le macchine che eseguono i workflow quando vengono attivati. GitHub fornisce runner hosted gratuiti per Linux, Windows e macOS.
- Job sono insiemi di step eseguiti sullo stesso runner. Per impostazione predefinita, i job vengono eseguiti in parallelo, ma possono essere configurati in sequenza.
- Step sono attività che eseguono comandi o azioni, in modo simile alle azioni in un Makefile.
- Action sono applicazioni personalizzate per la piattaforma GitHub Actions che svolgono compiti complessi ma frequenti. Esistono molte action tra cui scegliere, per lo più supportate dalla community open source.
Primi passi con GitHub Actions
In questa sezione impareremo a usare GitHub Actions e proveremo a replicare i comandi usati in precedenza nel Makefile.
Per trasferire il nostro codice su GitHub, dobbiamo convertire la cartella del progetto in un repository Git usando:
$ git init
Poi creiamo un nuovo repository su GitHub e copiamo l’URL.

Nel terminale, digitiamo i comandi sotto per:
- Aggiungere il link al repository remoto.
- Effettuare il pull dei file dal repository remoto.
- Aggiungere e fare commit di tutti i file con un messaggio di commit.
- Fare push dal
masterlocale al branchmainremoto.
$ git remote add github https://github.com/kingabzpro/Makefile-Actions.git
$ git pull github main
$ git add .
$ git commit -m "adding all the files"
$ git push github master:main
Nota a margine: se ti serve un rapido ripasso su GitHub o Git, guarda questo tutorial per principianti su GitHub e Git. Ti aiuterà a versionare il tuo progetto di data science e a condividerlo con il team usando lo strumento Git da CLI.
Proseguendo la lezione, vediamo che tutti i file sono stati trasferiti correttamente nel repository remoto.

Ora creeremo un workflow di GitHub Action. Per prima cosa andiamo nella scheda Actions del nostro repository kingabzpro/Makefile-Actions. Poi clicchiamo sul testo blu “set up a workflow yourself”.

Verremo reindirizzati al file YML, dove scriveremo tutto il codice per impostare l’ambiente ed eseguire i comandi. Faremo:
- Fornire il nome del workflow.
- Impostare gli eventi di trigger per eseguire il workflow quando viene fatto push sul branch
maino quando c’è una pull request sul branchmain. - Impostare un job con l’ultima macchina Ubuntu Linux.
- Usare l’action checkout v3 nella sezione step. Aiuta il nostro workflow ad accedere ai repository.
- Installare i pacchetti Python necessari, formattare il codice ed eseguire entrambi gli script Python con variabili.
name: Data Processing and Analysis
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Packages
run: |
pip install --upgrade pip
pip install -r requirements.txt
- name: Format
run: black *.py --line-length 88
- name: Data Processing
env:
RAW_DATA_DIR: "./raw_data/WHR2023.csv"
run: python data_processing.py $RAW_DATA_DIR
- name: Data Analysis
env:
CLEAN_DATA_DIR: "./processed_data/WHR2023_cleaned.csv"
run: python data_analysis.py $CLEAN_DATA_DIR
Dopo aver fatto commit del file del workflow con il messaggio, partirà automaticamente l’esecuzione del workflow.

Per completare tutti i passaggi serviranno almeno 20 secondi.
Per controllare i log, prima clicchiamo sull’esecuzione del workflow, poi sul pulsante Build e quindi su ciascun job per accedere ai log.

Se ti è piaciuto, amerai questa Guida per principianti al CI/CD per il Machine Learning, che copre le basi per costruire e automatizzare un workflow di machine learning.
Combinare GitHub Actions con MakeFile
Per semplificare e standardizzare i workflow di GitHub Action, gli sviluppatori usano comandi Make all’interno del file del workflow. In questa sezione impareremo a semplificare il nostro codice del workflow usando il comando Make e a usare l’action Continuous Machine Learning (CML).
Prima di iniziare, dobbiamo fare il pull del file del workflow dal repository remoto.
$ git pull
Usare CML
Continuous Machine Learning (CML) è una libreria open-source di iterative.ai che ci permette di implementare la continuous integration all’interno del nostro progetto di data science.
In questo progetto useremo la GitHub Action iterative/setup-cml che sfrutta funzioni CML nel workflow per generare il report dell’analisi usando figure e statistiche.
Il report verrà creato e allegato al nostro commit su GitHub per permettere al team di rivederlo e approvarlo prima del merge.
Modificheremo il Makefile aggiungendo un altro target “summary”. Nota che:
- Il target è uno script multi-linea che trasferisce i dati testuali da summary.txt a report.md.
- Poi, uno alla volta, aggiunge le intestazioni per ciascuna figura e il codice Markdown per mostrare le figure nel file report.md.
- Infine, useremo lo strumento
cmlper creare un report analitico e visualizzarlo nei commenti del commit.
Immagina di aggiungere così tante righe nel file del workflow GitHub: sarebbe difficile da leggere e modificare. Invece useremo make summary.
File: Makefile
summary: ./processed_data/summary.txt
echo "# Data Summary" > report.md
cat ./processed_data/summary.txt >> report.md
echo '\n# Data Analysis' >> report.md
echo '\n## Correlation Heatmap' >> report.md
echo '' >> report.md
echo '\n## Happiness Score Distribution' >> report.md
echo '' >> report.md
echo '\n## Happiness Score vs GDP per Capita' >> report.md
echo '' >> report.md
echo '\n## Social Support vs Happiness Relationship' >> report.md
echo '' >> report.md
echo '\n## Top 20 Countries by Happiness Score' >> report.md
echo '' >> report.md
cml comment create report.md

Modificare il file di GitHub Action
Ora modificheremo il nostro file main.yml, che si trova nella directory .github/workflows.
Sostituiamo tutti i comandi e gli script Python con il comando make e forniamo le autorizzazioni per permettere alla CML Action di creare il report dati nel commento del commit. Inoltre, assicuriamoci di non dimenticare di aggiungere l’Action iterative/setup-cml@v3 alla nostra run.
name: Data Processing and Analysis
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions: write-all
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: iterative/setup-cml@v3
- name: Install Packages
run: make install
- name: Format
run: make format
- name: Data Processing
env:
RAW_DATA_DIR: "./raw_data/WHR2023.csv"
run: make process RAW_DATA_PATH=$RAW_DATA_DIR
- name: Data Analysis
env:
CLEAN_DATA_DIR: "./processed_data/WHR2023_cleaned.csv"
run: make analyze PROCESSED_DATA=$CLEAN_DATA_DIR
- name: Data Summary
env:
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: make summary
Eseguire il workflow
Per eseguire il workflow, dobbiamo solo fare commit di tutte le modifiche e sincronizzarle con il branch remoto main.
$ git commit -am "makefile and github action combo"
$ git push github master:main

L’esecuzione del workflow ha richiesto 32 secondi: il nostro report è pronto per la revisione. Per visualizzarlo, andiamo nel riepilogo della build, scorriamo fino alla scheda Data Summary e poi clicchiamo su il link al commento (il link che vedi alla riga 20 nell’immagine sotto):

Come possiamo vedere, il riepilogo dei dati e le visualizzazioni sono allegate al nostro commit.

Il progetto è disponibile su kingabzpro/Makefile-Actions e puoi usarlo come guida quando ti blocchi. Il repository è pubblico, quindi fai un fork e prova tu stesso la magia!
Ti piacerebbe ottenere una certificazione GitHub? Dai un’occhiata alla nostra guida completa sulle diverse certificazioni GitHub!
Conclusione
In questo tutorial ci siamo concentrati su Makefile e GitHub Actions per automatizzare la generazione di report analitici sui dati.
Abbiamo anche visto come creare ed eseguire il workflow e usare lo strumento Make all’interno del workflow GitHub per ottimizzare e semplificare il processo di automazione. Invece di scrivere molte righe di codice, possiamo usare make summary per generare un report di analisi dei dati che verrà allegato al nostro commit.
Se vuoi padroneggiare l’arte del CI/CD per la data science, prova questo corso su CI/CD for Machine Learning. Copre i fondamenti del CI/CD, GitHub Actions, il versionamento dei dati e l’automazione dell’ottimizzazione degli iperparametri e della valutazione dei modelli.
In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.


