Nel panorama aziendale odierno, i dati sono la valuta più preziosa. Ma avere dati non basta: è fondamentale saperli analizzare, interpretare e trasformare in decisioni strategiche. Qui entra in gioco la potenza delle matrici e la flessibilità di Python, un binomio vincente per ogni professionista che mira all’eccellenza gestionale.
Questo articolo ti guiderà in un percorso pratico attraverso 8 esercizi progressivi, pensati per applicare concetti avanzati di analisi matriciale direttamente a scenari aziendali reali. Dalla semplice aggregazione delle vendite alla complessa previsione della domanda multidimensionale, passando per l’ottimizzazione logistica e l’analisi della customer journey, scoprirai come le matrici non siano solo un concetto matematico, ma uno strumento decisionale indispensabile.
Preparati a sbloccare il potenziale nascosto nei tuoi dati e a portare la tua business intelligence a un livello superiore.
Esercizi Python sulle Matrici con Applicazioni Gestionali
Esercizio 1: Calcolo del Totale Vendite per Prodotto e Filiale
Contesto
Un’azienda con 3 filiali vende 5 prodotti diversi. Creare una matrice per registrare le vendite e calcolare i totali.
Python
# Matrice vendite: righe = filiali, colonne = prodotti
vendite = [
[120, 85, 90, 75, 110], # Filiale 1
[95, 110, 80, 120, 90], # Filiale 2
[105, 90, 115, 85, 100] # Filiale 3
]
# 1. Calcolo totale per prodotto (somma colonne)
totali_prodotti = [0] * len(vendite[0])
for filiale in vendite:
for i in range(len(filiale)):
totali_prodotti[i] += filiale[i]
print("Totali per prodotto:", totali_prodotti)
# 2. Calcolo totale per filiale (somma righe)
totali_filiali = [sum(filiale) for filiale in vendite]
print("Totali per filiale:", totali_filiali)
Output:
Totali per prodotto: [320, 285, 285, 280, 300]
Totali per filiale: [480, 495, 495]
Teoria
Le matrici sono liste di liste in Python. Le righe rappresentano le filiali, le colonne i prodotti. La somma delle colonne (prodotti) richiede di iterare per ogni colonna attraverso tutte le righe, mentre la somma delle righe (filiali) è più semplice con la funzione [math]\text{sum()}[/math].
Approfondimento
- Tecnico: Introduce il concetto base di matrice come “lista di liste” in Python. Dimostra due approcci comuni per la somma: iterazione esplicita per le colonne (più complessa data la struttura row-major delle liste annidate) e [math]\text{sum()}[/math] con list comprehension per le righe (più Pythonic). È un ottimo punto di partenza per chi non ha familiarità con le matrici in Python.
- Applicativo: Fondamentale per il reporting base. Un manager può rapidamente identificare i prodotti più venduti a livello aziendale o le filiali più performanti. Permette di prendere decisioni rapide sull’allocazione delle risorse o sull’identificazione di aree problematiche.
—
👉Python: esercizi svolti sulle matrici
Esercizio 2: Analisi della Produttività dei Dipendenti
Contesto
Calcolare la produttività media dei dipendenti in diversi reparti su più settimane.
Python
# Matrice produttività: righe = reparti, colonne = settimane
produttivita = [
[8.5, 9.0, 8.7, 8.9], # Reparto A
[7.8, 8.2, 8.0, 7.9], # Reparto B
[9.2, 9.1, 9.3, 9.0] # Reparto C
]
# Calcolo media per reparto (riga)
print("Medie per reparto:")
for i, reparto in enumerate(produttivita):
media = sum(reparto) / len(reparto)
print(f"Reparto {chr(65+i)}: {media:.2f}")
# Calcolo media per settimana (colonna)
print("\nMedie per settimana:")
for j in range(len(produttivita[0])):
media = sum(produttivita[i][j] for i in range(len(produttivita))) / len(produttivita)
print(f"Settimana {j+1}: {media:.2f}")
Output:
Medie per reparto:
Reparto A: 8.78
Reparto B: 7.97
Reparto C: 9.15
Medie per settimana:
Settimana 1: 8.50
Settimana 2: 8.77
Settimana 3: 8.67
Settimana 4: 8.60
Teoria
L’enumerazione ([math]\text{enumerate}[/math]) permette di accedere sia all’indice che al valore durante l’iterazione. Le comprensioni di lista semplificano il calcolo delle medie per colonna. Notare come [math]\text{chr(65+i)}[/math] converta numeri in lettere ([math]65 = \text{‘A’}[/math] in ASCII).
Approfondimento
- Tecnico: Prosegue con le matrici base, introducendo [math]\text{enumerate}[/math] per accedere a indici e valori, e la comprensione di lista per calcoli aggregati su colonne. Il [math]\text{chr(65+i)}[/math] è un tocco elegante per generare etichette alfabetiche.
- Applicativo: Cruciale per il monitoraggio delle performance. Aiuta i responsabili di reparto a valutare l’efficienza nel tempo, a identificare reparti o periodi di bassa produttività e a implementare interventi mirati (formazione, ottimizzazione processi).
—
Esercizio 3: Matrice di Correlazione tra Metriche Aziendali
Contesto
Calcolare la correlazione tra diverse metriche aziendali (vendite, clienti, spese).
Python
import numpy as np
# Dati: righe = mesi, colonne = [vendite, clienti, spese] (in migliaia)
dati = np.array([
[120, 350, 45],
[135, 370, 50],
[140, 390, 55],
[160, 410, 60],
[175, 430, 65]
])
# Calcolo matrice di correlazione
correlazione = np.corrcoef(dati, rowvar=False)
print("Matrice di correlazione:")
print(" Vendite Clienti Spese")
etichette = ["Vendite", "Clienti", "Spese"]
for i, row in enumerate(correlazione):
print(f"{etichette[i]:<8}", " ".join(f"{val:.2f}" for val in row))
Output:
Matrice di correlazione:
Vendite Clienti Spese
Vendite 1.00 0.99 0.99
Clienti 0.99 1.00 1.00
Spese 0.99 1.00 1.00
Teoria
La correlazione misura la relazione lineare tra variabili (da [math]-1[/math] a [math]1[/math]). [math]\text{rowvar=False}[/math] indica che le variabili sono nelle colonne. NumPy ottimizza questi calcoli matriciali.
Approfondimento
- Tecnico: Introduzione di NumPy, libreria fondamentale per l’algebra lineare in Python. Il concetto di correlazione e l’uso di [math]\text{np.corrcoef}[/math] con [math]\text{rowvar=False}[/math] sono spiegati chiaramente. La formattazione dell’output migliora la leggibilità.
- Applicativo: Essenziale per l’analisi finanziaria e strategica. Permette di capire le relazioni tra variabili chiave (es. l’aumento delle vendite è correlato all’aumento dei clienti o delle spese di marketing?). Queste intuizioni guidano le strategie di crescita e l’ottimizzazione dei costi.
—
Esercizio 4: Ottimizzazione del Mix Produttivo
Contesto
Determinare il mix ottimale di prodotti considerando vincoli di risorse.
Python
from scipy.optimize import linprog
import numpy as np
# Matrice dei coefficienti tecnici: risorse x prodotti
# [Ore macchina, Materia prima, Manodopera] per unità di prodotto
risorse = [
[2, 3, 1], # Prodotto A
[4, 2, 3], # Prodotto B
[3, 1, 2] # Prodotto C
]
# Vincoli: disponibilità massima [200 ore, 180 kg, 150 ore]
disponibilita = [200, 180, 150]
# Profitti unitari
profitti = [30, 40, 35]
# Formulazione problema di ottimizzazione
# Massimizzare profitto: minimizzare il negativo
c = [-p for p in profitti]
# Vincoli A*x <= b
A = np.array(risorse).T # Trasposta per adattare alla formulazione
b = disponibilita
# Risoluzione
risultato = linprog(c, A_ub=A, b_ub=b, bounds=(0, None))
print("Soluzione ottimale:")
for i, qta in enumerate(risultato.x):
print(f"Prodotto {chr(65+i)}: {qta:.2f} unità")
print(f"Profitto totale: {-risultato.fun:.2f}")
Output:
Soluzione ottimale:
Prodotto A: 48.57 unità
Prodotto B: 0.00 unità
Prodotto C: 34.29 unità
Profitto totale: 2657.14
Teoria
La programmazione lineare risolve problemi di ottimizzazione con vincoli. La matrice dei coefficienti descrive il consumo di risorse per unità di prodotto. La funzione [math]\text{linprog}[/math] di SciPy minimizza, quindi invertiamo i profitti. I vincoli sono espressi nella forma [math]\displaystyle A \cdot x \le b[/math].
Approfondimento
- Tecnico: Primo esempio di ottimizzazione con SciPy. Introduce la programmazione lineare (PL) come strumento decisionale. La comprensione della trasformazione [math]\text{c = [-p for p in profitti]}[/math] per adattarsi alla minimizzazione di [math]\text{linprog}[/math] e la trasposizione di [math]\text{A (.T)}[/math] sono dettagli tecnici importanti e ben gestiti.
- Applicativo: Direttamente applicabile alla gestione della produzione e della supply chain. Le aziende possono determinare la quantità ottimale di ciascun prodotto da produrre per massimizzare il profitto, rispettando i vincoli di risorse (ore macchina, materie prime, manodopera). Questo porta a un’allocazione efficiente delle risorse e a una maggiore redditività.
—
Esercizio 5: Analisi della Customer Journey con Catene di Markov
Contesto
Modellare la transizione dei clienti tra diversi stati (nuovi, attivi, inattivi).
Python
# Matrice di transizione: P[i][j] = probabilità di passare da stato i a j
P = [
[0.1, 0.7, 0.2], # Nuovi clienti
[0.0, 0.8, 0.2], # Clienti attivi
[0.1, 0.3, 0.6] # Clienti inattivi
]
# Stato iniziale: [Nuovi, Attivi, Inattivi]
stato = [1000, 2000, 3000]
# Simulazione per 5 periodi
for periodo in range(1, 6):
nuovo_stato = [0] * 3
for i in range(3): # Stato di partenza
for j in range(3): # Stato di arrivo
nuovo_stato[j] += stato[i] * P[i][j]
stato = [round(x) for x in nuovo_stato]
print(f"Periodo {periodo}: Nuovi={stato[0]}, Attivi={stato[1]}, Inattivi={stato[2]}")
Output:
Periodo 1: Nuovi=400, Attivi=3200, Inattivi=2400
Periodo 2: Nuovi=280, Attivi=3560, Inattivi=2160
Periodo 3: Nuovi=244, Attivi=3692, Inattivi=2064
Periodo 4: Nuovi=231, Attivi=3744, Inattivi=2026
Periodo 5: Nuovi=226, Attivi=3765, Inattivi=2011
Teoria
Le catene di Markov modellano sistemi che transitano tra stati con probabilità fisse. La moltiplicazione matrice-vettore, calcolata come [math]\displaystyle \text{nuovo\_stato}[j] = \sum_{i} \text{stato}[i] \cdot P[i][j][/math], propaga la distribuzione nel tempo. Il codice mostra il calcolo elemento per elemento dove [math]P[i][j][/math] è la probabilità di passare dallo stato [math]i[/math] allo stato [math]j[/math].
Approfondimento
- Tecnico: Introduce le catene di Markov, un potente strumento per modellare processi stocastici. Il calcolo iterativo della transizione dello stato (moltiplicazione matrice-vettore manuale) è didatticamente efficace, mostrando il funzionamento sottostante. L’uso di [math]\text{round()}[/math] è pratico per la visualizzazione.
- Applicativo: Invalutabile per il CRM e il marketing strategico. Permette di prevedere il comportamento futuro dei clienti, come le transizioni tra stati (es. da “nuovo” a “attivo”, da “attivo” a “inattivo”). Le aziende possono così implementare strategie proattive per la fidelizzazione, la riattivazione o l’acquisizione, ottimizzando gli investimenti di marketing.
—
Esercizio 6: Scomposizione SVD per Analisi del Portafoglio Clienti
Contesto
Ridurre la dimensionalità dei dati clienti per identificare pattern latenti.
Python
from sklearn.decomposition import TruncatedSVD
# Matrice clienti x caratteristiche (acquisti per categoria)
clienti = [
[5, 3, 0, 1, 2, 0], # Cliente 1
[4, 0, 0, 1, 0, 5], # Cliente 2
[1, 1, 1, 0, 1, 0], # Cliente 3
[1, 0, 0, 4, 0, 4], # Cliente 4
[0, 1, 5, 0, 0, 0] # Cliente 5
]
# SVD con riduzione a 2 componenti
svd = TruncatedSVD(n_components=2)
componenti = svd.fit_transform(clienti)
print("Componenti principali:")
for i, (c1, c2) in enumerate(componenti):
print(f"Cliente {i+1}: PC1={c1:.2f}, PC2={c2:.2f}")
print("\nVarianza spiegata:", svd.explained_variance_ratio_)
Output:
Componenti principali:
Cliente 1: PC1=4.48, PC2=3.60
Cliente 2: PC1=6.08, PC2=-1.19
Cliente 3: PC1=1.01, PC2=1.63
Cliente 4: PC1=4.58, PC2=-2.54
Cliente 5: PC1=0.37, PC2=3.05
Varianza spiegata: [0.29893338 0.34746307]
Teoria
La SVD (Singular Value Decomposition) decompone una matrice in componenti ortogonali che catturano la massima varianza. In gestione, aiuta a identificare gruppi di clienti o prodotti con comportamenti simili.
Approfondimento
- Tecnico: Introduzione alla riduzione della dimensionalità con [math]\text{TruncatedSVD}[/math] di Scikit-learn. Spiega il concetto di SVD e come produce componenti principali che catturano la massima varianza. È un primo passo verso tecniche più avanzate di apprendimento automatico.
- Applicativo: Essenziale per la segmentazione clienti e l’analisi di mercato. Identificando i “pattern latenti” nel comportamento d’acquisto, le aziende possono raggruppare i clienti in segmenti significativi, personalizzare le offerte, ottimizzare le strategie di prodotto e migliorare la comprensione del mercato.
Ogni esercizio affronta un aspetto diverso dell’analisi matriciale con applicazioni pratiche in contesti aziendali, dalla semplice aggregazione dati all’analisi multivariata avanzata.
Esercizi Python Avanzati sulle Matrici (Livello Hero)
Ecco due esercizi avanzati sulle matrici con applicazioni gestionali complesse, che richiedono l’integrazione di più concetti e tecniche.
Esercizio 7: Ottimizzazione del Routing Logistico con Algoritmo Ungherese
Contesto
Un’azienda di logistica deve assegnare ottimalmente 5 spedizioni a 5 camion minimizzando i costi totali, considerando costi diversi per ogni combinazione camion-spedizione.
Python
import numpy as np
from scipy.optimize import linear_sum_assignment
# Matrice dei costi: righe = camion, colonne = spedizioni
costi = np.array([
[22, 14, 120, 21, 4], # Camion 1
[19, 12, 12, 18, 22], # Camion 2
[90, 16, 15, 22, 24], # Camion 3
[24, 81, 21, 25, 23], # Camion 4
[27, 15, 23, 90, 19] # Camion 5
])
# Applicazione dell'algoritmo ungherese
righe_ind, colonne_ind = linear_sum_assignment(costi)
# Calcolo costo totale
costo_totale = costi[righe_ind, colonne_ind].sum()
# Visualizzazione risultati
print("Assegnazione ottimale:")
for camion, spedizione in zip(righe_ind, colonne_ind):
print(f"Camion {camion+1} → Spedizione {spedizione+1} (Costo: {costi[camion, spedizione]})")
print(f"\nCosto totale minimo: {costo_totale}")
Output:
Assegnazione ottimale:
Camion 1 → Spedizione 5 (Costo: 4)
Camion 2 → Spedizione 4 (Costo: 18)
Camion 3 → Spedizione 3 (Costo: 15)
Camion 4 → Spedizione 1 (Costo: 24)
Camion 5 → Spedizione 2 (Costo: 15)
Costo totale minimo: 76
Spiegazione
L’algoritmo ungherese risolve problemi di assegnazione ottimale in tempo polinomiale ([math]O(n^3)[/math]). La funzione [math]\text{linear\_sum\_assignment}[/math] trova l’accoppiamento perfetto che minimizza la somma dei costi. La complessità deriva dalla gestione di vincoli incrociati (ogni camion deve avere una spedizione unica). In contesti reali, la matrice dei costi potrebbe essere generata dinamicamente considerando distanze, tempi e costi variabili.
Approfondimento
- Tecnico: Utilizzo di [math]\text{linear\_sum\_assignment}[/math] di SciPy, che implementa l’algoritmo Ungherese. Questo algoritmo risolve il problema di assegnazione minimo (o massimo) in tempo polinomiale. Dimostra una soluzione elegante a un problema combinatorio complesso.
- Applicativo: Cruciale per l’ottimizzazione della logistica e delle operazioni. Le aziende di trasporto, e-commerce o con flotte di veicoli possono minimizzare i costi di consegna o massimizzare l’efficienza delle assegnazioni, riducendo le spese operative e migliorando i tempi di servizio.
—
Spiegazione Approfondita: L’Algoritmo Ungherese
L’Algoritmo Ungherese è uno strumento potente e affascinante nel campo dell’ottimizzazione, specificamente progettato per risolvere il problema di assegnazione (Assignment Problem). Immagina di dover assegnare un insieme di “lavori” a un insieme di “risorse”, dove ogni combinazione “lavoro-risorsa” ha un costo associato, e l’obiettivo è trovare l’assegnazione che minimizzi il costo totale, garantendo che ogni lavoro sia assegnato a una e una sola risorsa, e viceversa.
Il Problema di Assegnazione: Un Esempio Pratico
Riprendiamo l’Esercizio 7:
Un’azienda di logistica ha 5 camion e 5 spedizioni da consegnare. Ogni camion ha un costo diverso per ogni specifica spedizione (a causa di distanza, tipo di carico, disponibilità del conducente, ecc.). L’obiettivo è assegnare ogni camion a una e una sola spedizione (e ogni spedizione a un solo camion) in modo che il costo totale sia il più basso possibile.
Se ci pensi, potresti provare tutte le combinazioni possibili ([math]5! = 120[/math] combinazioni), ma con più elementi (es. 20 camion e 20 spedizioni), il numero di combinazioni esplode ([math]\displaystyle 20! \approx 2.4 \times 10^{18}[/math]), rendendo impraticabile la forza bruta. L’algoritmo ungherese risolve questo problema in modo efficiente.
Come Funziona l’Algoritmo Ungherese (L’Idea di Base)
L’algoritmo si basa su un principio ingegnoso: ridurre la matrice dei costi mantenendo le differenze relative tra i costi, fino a quando non è possibile identificare un’assegnazione ottimale contenente solo “costi zero”.
Ecco i passaggi chiave semplificati:
- Sottrazione sulle Righe: Per ogni riga della matrice dei costi, trova l’elemento più piccolo e sottrailo da tutti gli elementi di quella riga. Questo garantisce che ogni riga abbia almeno uno zero. Lo facciamo perché se a tutti i costi di un camion (riga) sottraiamo la stessa quantità, l’ordine di preferenza per quel camion non cambia e quindi nemmeno l’assegnazione ottimale.
- Sottrazione sulle Colonne: Ripeti lo stesso processo per le colonne. Per ogni colonna della matrice modificata, trova l’elemento più piccolo e sottrailo da tutti gli elementi di quella colonna. Ora, idealmente, hai zeri in ogni riga e ogni colonna.
- Copertura degli Zeri: Disegna il numero minimo di linee (orizzontali o verticali) necessarie per coprire tutti gli zeri nella matrice.
- Se il numero di linee è uguale al numero di righe/colonne (dimensione della matrice, es. 5 per una matrice 5×5), allora hai trovato l’assegnazione ottimale! Gli zeri non coperti da nessuna linea (o coperti da una sola linea, ma in posizione non ambigua) indicano l’accoppiamento ottimale.
- Se il numero di linee è inferiore al numero di righe/colonne, significa che non abbiamo ancora abbastanza zeri “liberi” per fare un’assegnazione completa. Dobbiamo fare un’altra iterazione.
- Creazione di Nuovi Zeri (Se Necessario): Trova il più piccolo elemento non coperto da nessuna linea. Sottrai questo valore da tutti gli elementi non coperti e aggiungilo a tutti gli elementi che sono coperti da due linee (all’intersezione di una riga e una colonna coperte). Gli elementi coperti da una sola linea rimangono invariati. Questo passaggio crea nuovi zeri o sposta gli zeri esistenti, avvicinandoti a una soluzione.
- Ripeti: Torna al passaggio 3 e continua finché il numero di linee non è uguale alla dimensione della matrice.
Perché Funziona? (Teoria Semplificata)
L’algoritmo ungherese si basa su un teorema fondamentale della teoria dei grafi e dell’ottimizzazione combinatoria (il Teorema di König). Il punto chiave è che sottrarre una costante da tutte le voci di una riga o colonna non cambia le assegnazioni ottimali. Le differenze relative tra i costi, che sono ciò che determina l’ottimalità, rimangono invariate. L’obiettivo è trasformare i costi in modo che l’assegnazione ottima corrisponda a una selezione di zeri.
Complessità e Vantaggi
- Complessità: L’algoritmo ha una complessità polinomiale, tipicamente [math]\displaystyle O(n^3)[/math] dove [math]n[/math] è la dimensione della matrice (es. 5×5). Questo lo rende estremamente efficiente per problemi di assegnazione di dimensioni anche considerevoli, a differenza della forza bruta.
- Vantaggi:
- Garantisce di trovare la soluzione ottimale globale.
- È robusto e ampiamente utilizzato in vari settori.
- Relativamente semplice da implementare per problemi di dimensioni limitate.
Applicazioni Gestionali
L’algoritmo ungherese non è limitato solo alla logistica. Le sue applicazioni sono vaste:
- Pianificazione del Personale: Assegnare dipendenti a progetti, turni o macchinari in base alle loro competenze e costi.
- Gestione Progetti: Assegnare task a membri del team per minimizzare il tempo totale di completamento.
- Produzione: Assegnare lavori a macchine per minimizzare i tempi di inattività o i costi energetici.
- Network Routing: Ottimizzare il percorso di pacchetti in una rete.
In sintesi, l’Algoritmo Ungherese è uno strumento matematico elegante che fornisce una soluzione efficiente e garantita a un problema comune e critico in molteplici contesti gestionali, permettendo alle aziende di operare con maggiore efficienza e ridurre i costi.
—
Esercizio 8: Forecast della Domanda con Decomposizione di Matrici Tensoriali
Problema Gestionale
In un’azienda che gestisce multiple linee di prodotti, distribuiti in diverse regioni geografiche, è cruciale prevedere la domanda futura per:
- Ottimizzare la catena di approvvigionamento
- Ridurre i costi di magazzino e logistica
- Pianificare promozioni e marketing
- Evitare stock-out (esaurimento scorte) o eccesso di inventario
Sfida
I dati di vendita hanno tre dimensioni fondamentali:
- Prodotti (es. 5 diverse categorie)
- Regioni (es. 4 aree geografiche)
- Tempo (es. 8 trimestri storici)
Metodi tradizionali (come ARIMA o regressioni) non catturano bene le interazioni complesse tra queste dimensioni. Serve un approccio multidimensionale.
Strumento Tecnico: Decomposizione PARAFAC
Cosa è la Decomposizione PARAFAC?
- Estensione della SVD (Singular Value Decomposition) a tensori (matrici multidimensionali).
- Scompone un tensore in fattori latenti per ogni dimensione.
Formula generale per un tensore [math]X[/math] (di dimensione [math]\displaystyle I \times J \times K[/math]):
[math]\displaystyle X \approx \sum_{r=1}^{R} a_r \otimes b_r \otimes c_r[/math]
dove:
- [math]\displaystyle a_r[/math] = fattore per la dimensione 1 (es. prodotti)
- [math]\displaystyle b_r[/math] = fattore per la dimensione 2 (es. regioni)
- [math]\displaystyle c_r[/math] = fattore per la dimensione 3 (es. tempo)
- [math]\displaystyle R[/math] = numero di componenti latenti (“rank”)
Vantaggi rispetto alle Matrici
| Approccio Matriciale (SVD) | Approccio Tensoriale (PARAFAC) |
|---|---|
| Appiattisce i dati in 2D (perde struttura) | Mantiene la multidimensionalità |
| Difficile modellare interazioni complesse | Cattura relazioni tra tutte le dimensioni |
| Limitato a due variabili alla volta | Adatto a dati con [math]\ge3[/math] dimensioni |
Python
import numpy as np
from tensorly.decomposition import parafac
import matplotlib.pyplot as plt
# 1. Creazione del tensore 3D: Prodotti × Regioni × Trimestri
np.random.seed(42)
tensore = np.random.rand(5, 4, 8) * 100 # 5 prodotti, 4 regioni, 8 trimestri storici
# Aggiunta pattern strutturali
tensore[0,:,:] += np.linspace(0, 50, 8) # Prodotto 1 con trend crescente
tensore[:,1,:] *= 1.5 # Regione 2 con domanda più alta
tensore[2,2,:] = 80 + np.sin(np.arange(8)) * 20 # Prodotto 3 in regione 3 con stagionalità
# 2. Decomposizione PARAFAC con 3 componenti
fattori = parafac(tensore, rank=3)
# 3. Estrapolazione per 2 trimestri futuri (10 totali)
periodi_totali = 10
componenti = [f for f in fattori.factors] # Copia dei fattori
componenti[2] = np.vstack([fattori.factors[2], fattori.factors[2][-2:] * 1.05]) # Estensione fattore tempo
previsione = np.einsum('ir,jr,kr->ijk', *componenti) # Ricostruzione tensore
# 4. Preparazione dati per il plot (prodotto 0, regione 1)
prodotto_idx, regione_idx = 0, 1
# Array temporale completo (10 periodi)
periodi = np.arange(periodi_totali)
# Dati storici (primi 8 periodi) + NaN per i futuri
dati_storici = np.full(periodi_totali, np.nan)
dati_storici[:8] = tensore[prodotto_idx, regione_idx, :]
# 5. Plot con visualizzazione completa
plt.figure(figsize=(12, 6))
# Dati storici (cerchi blu)
plt.plot(periodi[:8], dati_storici[:8], 'bo-', label='Dati Storici', markersize=8)
# Previsioni (linea rossa tratteggiata per tutto il periodo)
plt.plot(periodi, previsione[prodotto_idx, regione_idx, :], 'r--', label='Previsione PARAFAC')
# Evidenziazione zona di previsione
plt.axvspan(7.5, 9.5, color='yellow', alpha=0.1, label='Zona Previsione')
plt.title(f'Domanda Prodotto {prodotto_idx+1} in Regione {regione_idx+1}\nDati Storici + Previsione', fontsize=14)
plt.xlabel('Trimestre', fontsize=12)
plt.ylabel('Domanda (unità)', fontsize=12)
plt.legend(fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(periodi) # Mostra tutti i periodi sull'asse x
# Aggiunta testo esplicativo
plt.text(7.2, np.nanmin(dati_storici[:8])*0.9, 'Dati Storici', color='blue', ha='right')
plt.text(7.8, previsione[prodotto_idx, regione_idx, -1]*1.05, 'Previsione', color='red')
plt.tight_layout()
plt.show()
Spiegazione
La decomposizione PARAFAC fattorizza tensori in una somma di componenti rank-1. Ogni fattore cattura pattern latenti nelle diverse dimensioni. L’estrapolazione dei fattori permette di generare previsioni. Il metodo è particolarmente utile quando si hanno dati multidimensionali con correlazioni complesse.
Approfondimento
- Tecnico: Questo è l’esercizio “Hero”. Introduce i tensori e la decomposizione PARAFAC con [math]\text{tensorly}[/math], andando oltre le matrici 2D. La spiegazione della formula e il confronto con l’approccio matriciale sono eccellenti. La parte di estrapolazione ([math]\text{np.vstack}[/math]) e ricostruzione ([math]\text{np.einsum}[/math]) sono tecnicamente avanzate e mostrano un’applicazione reale del forecast. L’integrazione con Matplotlib per la visualizzazione è molto efficace.
- Applicativo: Un game-changer per la pianificazione della domanda e la gestione dell’inventario in contesti complessi. Le aziende che operano con molteplici prodotti, in diverse regioni e con dinamiche temporali complesse possono ottenere previsioni molto più accurate. Questo porta a una supply chain ottimizzata, minimizzando scorte e stock-out, e massimizzando la soddisfazione del cliente e la redditività.
—
Teoria Avanzata e Prossimi Passi
Per chi desidera approfondire ulteriormente, ecco alcuni concetti e direzioni future:
- Algebra Tensoriale vs. Algebra Matriciale: Comprendere le differenze fondamentali e quando usare un approccio rispetto all’altro.
- Problemi di Rank e Unicità della Decomposizione: Aspetti teorici cruciali per l’applicazione robusta delle decomposizioni tensoriali.
- Regolarizzazioni: Tecniche per gestire dati rumorosi, sparsi o incompleti nelle matrici e nei tensori.
- Integrazione con Modelli Temporali: Combinare le tecniche matriciali e tensoriali con modelli di serie storiche (es. ARIMA, LSTM) per migliorare ulteriormente le previsioni.
Le applicazioni gestionali di queste tecniche sono in continua espansione:
- Ottimizzazione Flotta: L’esercizio 7 può essere esteso per considerare vincoli temporali, capacità variabili dei camion, finestre di consegna e scenari multi-deposito.
- Previsioni Avanzate: L’esercizio 8 può essere arricchito con dati esterni (indicatori economici), vincoli di capacità produttiva, promozioni pianificate e l’elasticità prezzo-domanda.
Entrambi gli esercizi avanzati richiedono:
- Forti competenze matematiche
- Capacità di modellazione astratta
- Ottimizzazione del codice per grandi dataset
- Interpretazione business dei risultati matematici




