La convoluzione è un’operazione matematica che combina due funzioni al fine di produrne una terza. Si può applicare estensivamente anche ad insiemi di numeri interi, ad esempio, e permette di ricombinare il risultato come convoluzione (convolve, nei linguaggi di programmazione) dei numeri forniti in input.
Proviamo a capire meglio: immagina di avere due funzioni, una delle quali è chiamata “funzione di input” e l’altra è detta “funzione di risposta”. La convoluzione di queste due funzioni produce una terza funzione che rappresenta come l’input “interagisce” con la risposta. In termini più pratici, puoi pensare alla convoluzione come a una sorta di “mescolamento” di informazioni da una funzione all’altra.
La convoluzione è molto usata in ambito ingegneristico e per la rielaborazione dei segnali audio, video e immagine. Ad esempio, nel campo dell’elaborazione del segnale, la convoluzione può mostrare come un segnale di input influenzi o cambi rispetto alla risposta del sistema a cui viene applicato. Può sembrare un concetto un po’ astratto, ma è ampiamente utilizzato in molte aree come matematica, fisica, ingegneria e scienze informatiche per comprendere come diverse grandezze interagiscono tra loro.
Un esempio significativo per capire di cosa parliamo è quello della risposta impulsiva dei circuiti RC, mostrati nella GIF successiva.
Convoluzione e integrali (teoria)
L’operatore di convoluzione è spesso utilizzato nell’elaborazione dei segnali, dove modella l’effetto di un sistema lineare tempo-invariante su un segnale arbitrario. Nella teoria della probabilità, la somma di due variabili casuali indipendenti è distribuita secondo la convoluzione delle loro distribuzioni individuali, il che è l’esempio che riporteremo in seguito.
L’integrale è strettamente collegato alla convoluzione, specialmente quando si tratta di convoluzioni continue, in quanto la convoluzione di due funzioni può essere espressa attraverso un’integrale.
Nel contesto della convoluzione, l’integrale viene utilizzato per combinare le informazioni delle due funzioni. Quando si calcola la convoluzione tra due funzioni continue, l’operazione di convoluzione può essere rappresentata come un’integrale definito.
Matematicamente, la convoluzione (f∗g)(t) di due funzioni f(t) e g(t) è definita come:
(f∗g)(t)=∫−∞+∞f(τ)⋅g(t−τ) dτ
Questa formula esprime la convoluzione come un’integrale della funzione f(τ) moltiplicata per la funzione g(t−τ), dove τ è la variabile di integrazione. In sostanza, l’integrale viene utilizzato per sommare il prodotto delle due funzioni in ogni istante temporale (o punto) per ottenere il valore della funzione convoluzione (f∗g)(t) per quel particolare istante tt.
Quindi, l’integrale aiuta a combinare e integrare l’informazione delle due funzioni nel processo di convoluzione, permettendo di comprendere come esse si influenzino reciprocamente lungo l’asse temporale (o spaziale, a seconda del contesto).
Convoluzione… nella pratica (teoria della probabilità)
Un approccio più utilitaristico alla convoluzione di quello precedente è quello (ispirato al canale Youtube 3blue1brown) di considerarla con la tecnica dell’anti-diagonalizzazione, ovvero: poniamo di avere due dati con numeri da 1 a 6, e di voler considerare di base tutte le possibili combinazioni di facce. Possiamo enumerarle in prima istanze, ed esse saranno:
- 1 e 1
- 1 e 2
- 1 e 3
- …
fino a 6 e 6, chiaramente.
È interessante notare che è possibile porre le facce del dado a sulle colonne e quelle del dado b sulle righe al fine di ottenere una matrice 6×6. Qui potete vedere il risultato, in cui per non perdere generalità abbiamo inserito a1 al posto di 1 sul primo dado, b1 al posto di 1 sul secondo dado e così via. La distribuzione degli indici non dovrebbe, in teoria, confondere: basta considerare come sono stati distribuiti sulla prima riga e sulla prima colonna, e prenderli come riferimento per ogni casella.
a1 | a2 | a3 | a4 | a5 | a6 | |
---|---|---|---|---|---|---|
b1 | a1 · b1 | a2 · b1 | a3 · b1 | a4 · b1 | a5 · b1 | a6 · b1 |
b2 | a2 · b1 | a2 · b2 | a3 · b2 | a4 · b2 | a5 · b2 | a6 · b2 |
b3 | a1 · b3 | a2 · b3 | a3 · b3 | a4 · b3 | a5 · b3 | a6 · b3 |
b4 | a1 · b4 | a2 · b4 | a3 · b4 | a4 · b4 | a5 · b4 | a6 · b4 |
b5 | a1 · b5 | a2 · b5 | a3 · b5 | a4 · b5 | a5 · b5 | a6 · b5 |
b6 | a1 · b6 | a2 · b6 | a3 · b6 | a4 · b6 | a5 · b6 | a6 · b6 |
Se andiamo a considerare le anti-diagonali che ho evidenziato di seguito, vederemo che sono esattamente 11 in tutto. Esse rappresentano il meccanismo di ri-combinazione usato dalla convoluzione, che consiste nel sommare le componenti nelle varie combinazioni possibili. Sono combinazioni di lunghezza diversa, questa è la chiave per capire la convoluzione. Poi vengono sommati e a quel punto otterremo:
- a1 · b1
- a2 · b1 + a2 · b1
- a1 · b3 + a2 · b2 + a3 · b1
- a1 · b4 + a2 · b3 + a3 · b2 + a4 · b1
- …
- …
- …
- …
- …
- a5 · b6 + a6 · b5
- a6 · b6
Questo significa che la convoluzione di due variabili con 6 valori darà luogo ad una nuova serie di 11 variabili distinte.
Se ad esempio riduciamo la dimensione dell’istanza ai due vettori (1, 2, 3) e (4, 5, 6), le ricombinazioni saranno di 5 elementi (5 quanti sono le anti-diagonali di una matrice di dimensione 3×3, senza complicarci troppo il calcolo):
(1, 2, 3) * (4, 5, 6) = (1·4, 1·5+2·4, 1·6 + 2·5 + 3·4, 2·6 + 3·5, 3·6) = (4, 13, 28, 27, 18)
Convoluzione in Python
Per Python c’è la libreria numpy e la funzione predefinita convolve, come dicevamo. Essa restituisce la convoluzione discreta e lineare di due sequenze unidimensionali. Se v è più lungo di a, gli array vengono scambiati prima del calcolo.
Convoluzione in C++
Questo codice definisce una funzione convolution
che prende due vettori di interi f
e g
e restituisce il risultato della convoluzione tra di essi. Si scorrono entrambi gli array per eseguire la convoluzione, considerando i valori degli array in posizioni adeguate e accumulando i risultati nella variabile result
. Infine, il risultato della convoluzione viene stampato nel main
.
#include <iostream> #include <vector> std::vector<int> convolution(const std::vector<int>& f, const std::vector<int>& g) { int sizeF = f.size(); int sizeG = g.size(); int sizeResult = sizeF + sizeG - 1; // La dimensione del risultato della convoluzione std::vector<int> result(sizeResult, 0); for (int i = 0; i < sizeResult; ++i) { for (int j = 0; j < sizeG; ++j) { if (i - j >= 0 && i - j < sizeF) { result[i] += f[i - j] * g[j]; } } } return result; } int main() { std::vector<int> f = {1, 2, 3}; std::vector<int> g = {4, 5, 6}; std::vector<int> result = convolution(f, g); std::cout << "Risultato della convoluzione: "; for (int val : result) { std::cout << val << " "; } std::cout << std::endl; return 0; }
👇 Da non perdere 👇
- Mondo Apple 🍎
- Reti 💻
- Sicurezza & Privacy 👁
- Spiegoni artificiali 🎓
- WordPress 🤵
- 💬 Il nostro canale Telegram: iscriviti
- 🔴 Email professionale: come e perchè
- 🟢 Domini .xyz: come e dove registrarne uno
- 🟢 Che vuol dire “pleonastico”, spiegato facile – Wikilost