In questo breve articolo, mostriamo con un caso pratico alcune delle possibilità che offrono gli algoritmi di Machine Learning per il controllo di progetti complessi.
La teoria classica del Project Management prevede che all’inizio di ogni progetto sia definita una project charter, all’interno della quale sono stabiliti i KPI (di solito variabili continue) che misureranno il grado di successo del progetto. Questi KPI possono essere i tempi di consegna del progetto, oppure valori di tipo economico (es., il ROI del progetto), finanziario (l’NPV) o ancora di tipo più commerciale (es., il tasso di fidelizzazione di clienti di un nuovo prodotto). Tipicamente, questi KPI devono essere monitorati nel corso del progetto, ma non sempre è possibile misurarli in modo immediato, o peggio ancora dare una previsione accurata del valore a completamento del progetto. Mostriamo in questo articolo le grandi potenzialità che offre il Machine Learning nel gestire questi valori: idealmente, vorremmo che grazie al Machine Learning i Project Manager si concentrassero sull’analisi delle azioni di miglioramento, piuttosto che sul calcolo dei KPI stessi.
Gli esempi sono basati sulla libreria scikit-learn di Python, ma sono facilmente replicabili con altri linguaggi che implementino gli stessi algoritmi.
Una soluzione basata sul Machine Learning Supervisionato
Chiamiamo $y$ un KPI di un progetto, e definiamo $f(\mathbf{X}_N)$ la funzione che lega il KPI ad un vettore di $N$ parametri:
\[ y = f(\mathbf{X}_N) \,.\]
I parametri possono essere sia variabili di tipo continuo che discreto, inoltre potrebbero essere variabili nel tempo.
Tipicamente, la funzione $f(\mathbf{X}_N)$ non è nota, inoltre a noi potrebbe interessare il valore a fine progetto di $y$, quindi per calcolarlo dovremmo avere anche i valori finali di $\mathbf{X}_N$; il numero di parametri $N$ può essere molto grande, pertanto il problema è poco controllabile.
Una possibile soluzione è individuare un subset molto ristretto $n$ di parametri, che chiamiamo $\mathbf{X}_n$, con $n \ll N$, che siano facilmente misurabili e per i quali sia abbastanza semplice prevedere il valore finale nel corso del progetto. Una volta individuati tali parametri potremmo addestrare un algoritmo di Machine Learning a prevedere $y$ a partire da $\mathbf{X}_n$ invece che da $\mathbf{X}_N$. Pertanto con il Machine Learning individuiamo una funzione $\hat{f}(\mathbf{X}_n)$ tale che:
\[ y = f(\mathbf{X}_N) \approx \hat{f}(\mathbf{X}_n) \,.\]
In questo modo avremmo sempre a disposizione il valore attuale di $y$, inoltre, essendo i parametri scelti facilmente prevedibili, potremmo utilizzarli per prevedere anche il valore finale del KPI $y$.
Scelta dei parametri
Chiaramente, affinchè l’algoritmo funzioni, è necessario individuare bene gli $n$ parametri. Abbiamo 3 possibilità:
- Abbiamo una conoscenza abbastanza profonda del progetto, e quindi sappiamo bene quali sono questi $n$ parametri che influenzano maggiormente il valore finale del KPI;
- Abbiamo in mente un insieme di parametri, ma non abbiamo ben chiaro quanto siano significativi sull’influenza del valore finale del KPI. In questo secondo caso, procediamo a selezionare un sottoinsieme di parametri con l’aiuto degli algoritmi di Machine Learning, che ci danno un’analisi "a posteriori" dell’impatto dei parametri sul valore finale del KPI.
- Non conosciamo questi parametri. In questo caso dovremo utilizzare altre tecniche di Machine Learning non supervisionato oppure di calcolo delle correlazioni. Questo caso non è analizzato in questo articolo.
Una volta individuati i parametri possiamo procedere all’addestramento dell’algoritmo. Possiamo scegliere uno dei tanti algoritmi di regressione per la previsione di variabili continue a partire da un gruppo di parametri di ingresso. Per fare l’addestramento dell’algoritmo, possiamo utilizzare lo storico di altri progetti, oppure le fasi di "progettazione" del progetto stesso. Prima di vedere un esempio concreto, rivediamo tutti i passi.
- Individuare il KPI di progetto da monitorare;
- Individuare un subset di parametri da cui il KPI dipende in maniera consistente. Tali parametri devono essere di semplice misura e deve essere facile prevedere il valore finale;
- Addestrare un algoritmo di Machine Learning a calcolare il valore del KPI a partire dai parametri.
Esempio di applicazione: NPV di una rete di telecomunicazioni FTTH
Un progetto di costruzione di una rete in fibra ottica FTTH (Fiber to the Home) è un progetto complesso che prevede di stendere fibra ottica in un’intera città ed entrare in ogni edificio con la fibra per predisporre una possibile attivazione di un cliente. Da un punto di vista finanziario, un progetto del genere è caratterizzato da una forte investimento iniziale per la predisposizione della rete, che genera un ritorno economico "spalmato" su diversi anni mano a mano che i clienti chiedono l’attivazione di una linea.
Un metodo per valutare finanziariamente progetti del genere è il calcolo dell’NPV (Net Present Value). L’NPV prevede di stimare il flusso di cassa su ciascun anno e poi sommare i risultati "attualizzati" di flusso di cassa di ciascun anno. Col termine "attualizzato" si intende che il risultato di ciascun anno viene "scontato" (attualizzato) in funzione del costo annuale del capitale prima di essere sommato al risultato degli altri anni (flussi di cassa più lontani nel tempo sono quindi "scontati di più"). Un NPV negativo indica presumibilmente un progetto non sostenibile. Al link in fondo è disponibile una descrizione più dettagliata del concetto di NPV.
Per una rete FTTH, l’NPV dipende sostanzialmente da 4 fattori:
- l’investimento iniziale per costruire la rete ("investimento capex"), calcolato in funzione dell’investimento medio per unità immobiliare connessa (predisposta all’attivazione);
- il "take up rate annuale", ovvero la percentuale annuale di unità immobiliari connesse (predisposte) che diventano un cliente attivo e pagante;
- il ricavo medio per utente attivo, di solito chiamato ARPU (average revenue per user);
- il costo medio annuale operativo ("costi opex").
Generalmente, ciascuno di questi quattro elementi diventa un KPI di progetto. In questo articolo mostriamo un esempio per il calcolo del primo KPI, ovvero l’investimento medio per unità immobiliare connessa (predisposta), applicando i principi descritti nei primi paragrafi. Ma potremmo ugualmente ripetere l’esercizio per calcolare i ricavi e i costi operativi ed arrivare a costruire un NPV basato sul Machine Learning.
Investimento medio per unità immobiliare
L’investimento medio per unità immobiliare di costruzione della rete FTTH (€/u.i.) è un parametro molto complesso, che dipende da tantissimi fattori. Per fare un esempio, un capitolato d’appalto per un lavoro del genere potrebbe contenere fino a 100 voci, a cui aggiungere i vari costi accessori (tasse occupazione suolo pubblico, servizi di progettazione e direzione lavori, ecc.). In fase di progetto viene fatto un calcolo dell’investimento atteso, ma essendo un lavoro complesso che si dipana su una città intera, è spesso soggetto a "varianti" esecutive, quindi è piuttosto complicato monitorare il valore effettivo in corso d’opera e fare una predizione esatta del valore finale.
Procediamo quindi ad individuare un subset molto ristretto di parametri che pilotano abbastanza bene il valore finale di investimento medio: parametri facilmente misurabili e prevedibili. Ad esempio, potremmo scegliere 3 parametri:
- densità dell’area, ovvero il rapporto tra le unità immobiliari e la lunghezza delle strade presenti nell’area di lavoro, che ci dà un’idea della "densità" abitativa;
- percentuale di strade senza infrastrutture pre-esisenti idonee alla posa della fibra, su cui si dovrà scavare;
- quanti nuovi pozzetti devo posare ogni metro di scavo.
Per semplicità, in questo esempio ci fermiamo a 3 parametri. Questi parametri sono abbastanza semplici da misurare in campo, soprattutto se la rete è tracciata su un sistema GIS (come avviene di solito). È anche piuttosto semplice calcolare il valore di atterraggio finale: il parametro 1 non cambia nel tempo, mentre i parametri 2 e 3 possono cambiare a seguito di varianti progettuali ma sono facilmente tracciabili e prevedibili.
Per legare questi 3 parametri al KPI investimento medio per unità immobiliare, utilizziamo un algoritmo di regressione molto potente già implementato nella libreria di machine learning, ovvero il Gradient Boosting Regressor. Qui la spiegazione dell’algoritmo di Gradient Boosting presentata su questo stesso blog: https://iaml.it/blog/gradient-boosting.
Implementazione
Innanzitutto, implementiamo una funzione che legga il nostro elenco di valori di training. Ipotizziamo che questi siano contenuti in un csv (questi numeri non sono tratti da casi reali ma sono una buona approssimazione). Ogni riga contiene il valore di unitario di investimento €/u.i. di un progetto (una città o un quartiere) e i corrispettivi parametri; questi dati possono derivare dallo "storico" di reti completate su altre città, oppure essere i valori derivanti del progetto preliminare sui vari quartieri della città:
unitario | Densità (param 1) | % scavo (param 2) | metri scavo/pozzetti (param 3) |
---|---|---|---|
337,91 | 7,81 | 0,75 | 22,56 |
360,45 | 8,21 | 0,76 | 22,66 |
341,25 | 7,81 | 0,75 | 20,59 |
323,01 | 7,42 | 0,76 | 25,22 |
139,59 | 5,91 | 0,30 | 19,05 |
176,26 | 7,28 | 0,31 | 19,40 |
168,87 | 7,23 | 0,30 | 20,41 |
210,44 | 5,38 | 0,66 | 23,03 |
398,22 | 8,43 | 0,81 | 16,71 |
296,81 | 7,39 | 0,67 | 20,60 |
379,38 | 8,09 | 0,79 | 14,48 |
346,88 | 7,38 | 0,83 | 21,34 |
434,69 | 9,58 | 0,78 | 17,75 |
... | ... | ... | ... |
... | ... | ... | ... |
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import ensemble
from sklearn.metrics import mean_absolute_error
import numpy
df = pd.read_csv("articolo2.csv", sep=";", encoding="latin1")
# Estrai i valori di Y
y = df['unitario'].to_numpy()
# Rimuovi Y
del df['unitario']
# Crea i parametri di test
X = df.to_numpy()
Definiamo poi la classe Gradient Boosting. Questa classe dipende ad alcuni iperparametri; in questo esempio passiamo dei valori predefiniti, è possibile ottimizzare i valori attraverso vari metodi, ad esempio col metodo "Grid Search" (vedi link in fondo)
model = ensemble.GradientBoostingRegressor(
n_estimators=5000,
learning_rate=0.005,
max_depth=4,
loss='lad',
random_state=0,
)
A questo punto eseguiamo l’addestramento e utilizziamo un sottoinsieme dei valori di traning (10%) per eseguire il test di performance dell’algoritmo (ovvero quanto è bravo a calcolare il valore del KPI a partire da X su dati sconosciuti). La partizione del set di addestramento si ottiene con il parametro test_size
della funzione train_test_split
.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1,
random_state=55, shuffle=True)
model.fit(X_train, y_train)
prediction = model.predict(X_test)
error = mean_absolute_error(y_test, prediction)
print("Test Set Mean Absolute Error: %.4f" % error)
In questo esempio, calcoliamo l’errore assoluto medio (Mean Absolute Error) della predizione sul set di test, che risulta pari a 11 €/u.i., ovvero +/- 3,5% del valore medio di Y.
Se siamo soddisfatti del risultato, abbiamo costruito uno stimatore che ci permette di calcolare il nostro KPI sulla base di un ristretto numero di parametri facilmente misurabili e predicibili. Se il valore non ci soddisfa, dobbiamo approfondire l’analisi. Per esempio, se il nostro stimatore soffre di underfitting, può darsi che dovremo aumentare il numero di parametri (al costo di complicare però il modello). Se soffre di overfitting, può darsi sia meglio diminuire il numero di parametri e semplificare il modello. La classe GradienBoosting
è in grado di dirci la percentuale di importanza di ciascun parametro sul valore della predizione. Nel caso in oggetto tutti e 3 i parametri hanno un impatto significativo.
importance = model.feature_importances_
feauture_indexes_by_importance = importance.argsort()
feature_labels = numpy.array(['m/u.i. (param 1) ',
'% scavo (param 2) ',
'scavo / pozzetti (param 3)'])
for index in feauture_indexes_by_importance:
print("{} - {:.2f}%".format(feature_labels[index], (importance[index] * 100.0)))
scavo / pozzetti (param 3) - 18.47%
% scavo (param 2) - 36.58%
densità (param 1) - 44.95%
Per la ricerca del set di parametri necessari per la predizione, potremmo quindi procedere a selezionare inizialmente un gruppo un po' ampio di parametri "candidati" e fare delle prove sul set di addestramento, andando a verificare l’impatto di ciascun parametro e scegliendo quindi il subset che ha più impatto sul risultato della predizione. Può essere utile ripetere l’esperimento N volte, andando a modificare la suddivisione tra set di addestramento e set di test (questo si può ottenere semplicemente modificando il parametro random_state
del metodo train_test_split
). Idealmente, se i parametri sono sufficientemente generici, dovrebbero avere un impatto sulla predizione abbastanza indipendente dalla suddivisione scelta per training e test.
Conclusione
Chiunque si sia trovato a gestire progetti complessi, conosce la difficoltà nel monitorare e prevedere i diversi KPI di successo del progetto. Il Machine Learning ci offre un grande aiuto per dare solidità ai numeri che ci si trova ogni giorno a gestire; spesso i Project Manager si trovano a dover spendere molto tempo nel calcolare questi parametri, il Machine Learning ci dà la possibilità di concentrarci sull’analisi dei dati e sul definire le azioni di miglioramento, lasciando alla "macchina" il compito di "calcolo" dei numeri.
Davide Mazza – Ingegnere Telecomunicazioni, MBA graduate; mi occupo da 10 anni di gestione di progetti di costruzione di reti in fibra ottica di nuova generazione in tutta Italia (FTTx), prima in Vodafone e poi in Open Fiber.
Copyright
Immagine di copertina: https://www.shutterstock.com/it/g/skypicsstudio.
Per saperne di più:
- Documentazione scikit-learn sul Gradient Boosting
- L’algoritmo di Gradient Boosting
- Grid Search per ottimizzare gli Iperparametri
- Definizione di NPV
- Schema delle reti fisse in fibra ottica
Se questo articolo ti è piaciuto e vuoi tenerti aggiornato sulle nostre attività, ricordati che l'iscrizione all'Italian Association for Machine Learning è gratuita! Puoi seguirci su Facebook, LinkedIn, e Twitter.