  {"id":3046,"date":"2023-08-21T08:44:37","date_gmt":"2023-08-21T07:44:37","guid":{"rendered":"https:\/\/www.gironi.it\/blog\/?p=3046"},"modified":"2026-05-06T14:43:55","modified_gmt":"2026-05-06T13:43:55","slug":"lalgoritmo-di-discesa-del-gradiente-gradient-descent-spiegato-semplice","status":"publish","type":"post","link":"https:\/\/www.gironi.it\/blog\/lalgoritmo-di-discesa-del-gradiente-gradient-descent-spiegato-semplice\/","title":{"rendered":"L&#8217;algoritmo di Discesa del Gradiente spiegato in modo chiaro: dall&#8217;intuizione alla pratica"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Una persona bendata su una montagna<\/h2>\n\n\n\n<p>Immagina di trovarti su un terreno montagnoso, completamente bendato. Il tuo obiettivo: raggiungere il punto pi\u00f9 basso della valle. Non puoi vedere nulla, ma puoi sentire la pendenza del terreno sotto i piedi. Cosa fai? Ti muovi nella direzione in cui il terreno scende, un passo alla volta. Se scende pi\u00f9 ripidamente a sinistra, vai a sinistra. Se scende di pi\u00f9 a destra, vai a destra. Ad ogni passo, senti di nuovo la pendenza e cambi direzione.<\/p>\n\n\n\n<p>Questa strategia, cos\u00ec semplice e naturale, \u00e8 esattamente quella che le reti neurali usano per imparare. Ogni volta che un modello di intelligenza artificiale migliora &mdash; che impari a riconoscere un volto, tradurre una frase, o generare un testo &mdash; lo fa scendendo lungo un paesaggio matematico, un passo alla volta, seguendo la pendenza.<\/p>\n\n\n\n<p>Si chiama <strong>discesa del gradiente<\/strong> (<em>gradient descent<\/em>), ed \u00e8 probabilmente l&#8217;algoritmo pi\u00f9 importante del machine learning moderno.<\/p>\n\n\n\n<figure style=\"margin: 1.5em 0;text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.gironi.it\/blog\/wp-content\/uploads\/2026\/03\/slide-esploratore-bendato.jpg\" alt=\"Infografica: la metafora dell'esploratore bendato che cerca il fondo della valle, con i tre passaggi Sensore, Azione, Ciclo\" style=\"max-width: 100%;border: 1px solid #e0e0e0;border-radius: 6px\" \/><\/figure>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\" id=\"storia\">Da Cauchy alle reti neurali: una breve storia<\/h2>\n\n\n\n<p>L&#8217;idea di seguire la pendenza per trovare un minimo ha radici sorprendentemente antiche. Nel <strong>1847<\/strong>, il matematico francese Augustin-Louis Cauchy pubblica un metodo per risolvere sistemi di equazioni che, nella sostanza, \u00e8 gi\u00e0 la discesa del gradiente: calcolare la direzione di massima crescita di una funzione e muoversi nella direzione opposta. Cauchy non pensava alle reti neurali &mdash; mancava pi\u00f9 di un secolo alla loro comparsa &mdash; ma aveva formalizzato il principio che ancora oggi alimenta l&#8217;intelligenza artificiale.<\/p>\n\n\n\n<p>Per oltre un secolo l&#8217;idea resta confinata alla matematica pura. La svolta arriva nel <strong>1951<\/strong>, quando Herbert Robbins e Sutton Monro propongono una versione <strong>stocastica<\/strong> del metodo: invece di calcolare il gradiente sull&#8217;intero problema, lo si stima su un campione casuale. \u00c8 il seme di quello che oggi chiamiamo <em>Stochastic Gradient Descent<\/em> (SGD) &mdash; ne parleremo nella sezione finale. Pochi anni dopo, nel <strong>1958<\/strong>, Frank Rosenblatt costruisce il <strong>perceptron<\/strong>, il primo modello di apprendimento automatico che usa la discesa del gradiente per imparare dai dati. L&#8217;entusiasmo \u00e8 enorme, ma dura poco: nel 1969 Minsky e Papert dimostrano i limiti del perceptron, e l&#8217;interesse per le reti neurali crolla. \u00c8 il cosiddetto <em>inverno dell&#8217;intelligenza artificiale<\/em>.<\/p>\n\n\n\n<p>La rinascita arriva nel <strong>1986<\/strong>, quando David Rumelhart, Geoffrey Hinton e Ronald Williams pubblicano l&#8217;algoritmo di <strong>backpropagation<\/strong>: un modo efficiente per calcolare il gradiente in reti neurali con molti strati. \u00c8 la chiave che sblocca il deep learning. Da quel momento, la discesa del gradiente non \u00e8 pi\u00f9 un esercizio teorico ma lo strumento pratico con cui si addestrano le reti neurali. L&#8217;ultimo tassello di questa storia lo pongono Diederik Kingma e Jimmy Ba nel <strong>2014<\/strong>, con l&#8217;ottimizzatore <strong>Adam<\/strong> &mdash; che ritroveremo nella sezione finale di questo articolo. Quasi due secoli separano Cauchy da Adam, eppure il principio \u00e8 rimasto lo stesso: senti la pendenza, fai un passo nella direzione opposta.<\/p>\n\n\n\n<div style=\"border: 1px solid #ccc;padding: 1.2em 1.5em;margin: 1.5em 0;border-radius: 6px\">\n<h3 style=\"margin-top: 0\">Di cosa parleremo<\/h3>\n<ul>\n<li><a href=\"#storia\">Da Cauchy alle reti neurali: una breve storia<\/a><\/li>\n<li><a href=\"#matematica\">La matematica, spiegata geometricamente<\/a><\/li>\n<li><a href=\"#learning-rate\">Il learning rate e la convergenza<\/a><\/li>\n<li><a href=\"#problemi\">Cosa pu\u00f2 andare storto: l&#8217;intuizione geometrica<\/a><\/li>\n<li><a href=\"#scala\">Da una parabola a ChatGPT<\/a><\/li>\n<li><a href=\"#evoluzioni\">Le evoluzioni: scarpe migliori per il nostro esploratore<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"matematica\">La matematica, spiegata geometricamente<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">La funzione di costo: misurare quanto sbaglia il modello<\/h3>\n\n\n\n<p>Prima di scendere, dobbiamo sapere <strong>cosa<\/strong> stiamo minimizzando. La persona bendata cerca il punto pi\u00f9 basso della valle &mdash; ma nel machine learning, cos&#8217;\u00e8 esattamente quella valle?<\/p>\n\n\n\n<p>Facciamo un esempio concreto. Supponiamo di voler prevedere il prezzo di una casa conoscendo solo la sua superficie. Abbiamo cinque case di cui conosciamo superficie e prezzo reale, e il nostro modello \u00e8 il pi\u00f9 semplice possibile: una retta che passa per l&#8217;origine, <strong>prezzo = m &times; superficie<\/strong>, dove <em>m<\/em> \u00e8 l&#8217;unico parametro da regolare.<\/p>\n\n\n\n<p>Per ogni valore di <em>m<\/em>, il modello fa una previsione. Se <em>m<\/em> \u00e8 troppo basso, le previsioni sottostimano i prezzi reali; se \u00e8 troppo alto, li sovrastimano. Abbiamo bisogno di un numero che ci dica <em>quanto<\/em> il modello sta sbagliando: \u00e8 la <strong>funzione di costo<\/strong> (o <em>loss function<\/em>, come dicono gli anglosassoni).<\/p>\n\n\n\n<p>La funzione di costo pi\u00f9 usata \u00e8 l&#8217;<strong>errore quadratico medio<\/strong> (MSE, <em>Mean Squared Error<\/em>): per ogni casa, calcoliamo la differenza tra il prezzo previsto e quello reale, la eleviamo al quadrato, e facciamo la media di tutti questi errori. In formula:<\/p>\n\n\n\n<p><strong>MSE(m) = (1\/n) &sum;<sub>i<\/sub> (prezzo<sub>i<\/sub> &minus; m &times; superficie<sub>i<\/sub>)&sup2;<\/strong><\/p>\n\n\n\n<p>Se plottiamo MSE(m) al variare di <em>m<\/em>, otteniamo una curva a forma di parabola: la stessa parabola che useremo tra poco come esempio della discesa del gradiente. Non \u00e8 una coincidenza &mdash; <strong>la parabola \u00e8 la funzione di costo<\/strong>, e il suo punto pi\u00f9 basso \u00e8 il valore di <em>m<\/em> che rende il modello migliore possibile.<\/p>\n\n\n\n<p>Gli esempi che seguono sono disponibili sia in R che in Python &mdash; ognuno segua il linguaggio con cui ha pi\u00f9 familiarit\u00e0.<\/p>\n\n\n\n<p>Calcoliamo in R la funzione di costo per il nostro esempio delle case:<\/p>\n\n\n\n<pre><code class=\"language-r\"># Funzione di costo: prevedere il prezzo di una casa\nsuperficie &lt;- c(50, 70, 90, 120, 150)\nprezzo &lt;- c(150, 200, 260, 340, 400)  # migliaia di euro\n\n# Modello: prezzo = m * superficie\n# Funzione di costo MSE al variare di m\nm_valori &lt;- seq(1, 4, by = 0.01)\nmse &lt;- sapply(m_valori, function(m) mean((prezzo - m * superficie)^2))\n\nplot(m_valori, mse, type = \"l\", lwd = 2, col = \"steelblue\",\n     xlab = \"m (pendenza)\", ylab = \"MSE\",\n     main = \"Funzione di costo al variare di m\")\nm_ottimo &lt;- m_valori[which.min(mse)]\nabline(v = m_ottimo, col = \"red\", lty = 2)\ncat(\"Il valore di m che minimizza l'errore:\", round(m_ottimo, 2), \"\\n\")<\/code><\/pre>\n\n\n\n<p>Verifichiamo in Python:<\/p>\n\n\n\n<pre><code class=\"language-python\">import numpy as np\nimport matplotlib.pyplot as plt\n\n# Funzione di costo: prevedere il prezzo di una casa\nsuperficie = np.array([50, 70, 90, 120, 150])\nprezzo = np.array([150, 200, 260, 340, 400])  # migliaia di euro\n\n# Modello: prezzo = m * superficie\n# Funzione di costo MSE al variare di m\nm_valori = np.linspace(1, 4, 301)  # equivalente a seq(1, 4, by=0.01) in R\nmse = np.array([np.mean((prezzo - m * superficie)**2) for m in m_valori])\n\nplt.plot(m_valori, mse, lw=2, color=\"steelblue\")\nplt.xlabel(\"m (pendenza)\")\nplt.ylabel(\"MSE\")\nplt.title(\"Funzione di costo al variare di m\")\nm_ottimo = m_valori[np.argmin(mse)]\nplt.axvline(m_ottimo, color=\"red\", linestyle=\"--\")\nplt.show()\nprint(f\"Il valore di m che minimizza l'errore: {m_ottimo:.2f}\")<\/code><\/pre>\n\n\n\n<p>Ora sappiamo cosa minimizzare: la funzione di costo. Il gradiente ci dice <em>come<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Derivata: la pendenza sotto i piedi<\/h3>\n\n\n\n<p>Quando hai una funzione di una sola variabile &mdash; pensala come un sentiero che sale e scende &mdash; la <strong>derivata<\/strong> in un punto ti dice quanto \u00e8 ripido il sentiero in quel punto. Se la derivata \u00e8 positiva, stai salendo. Se \u00e8 negativa, stai scendendo. Se \u00e8 zero, sei su un tratto piatto: forse una cima, forse un avvallamento.<\/p>\n\n\n\n<p>Esempio concreto: la funzione f(x) = x&sup2; descrive una parabola. La sua derivata \u00e8 f'(x) = 2x. Se sei nel punto x = 3, la derivata vale 6: stai salendo ripidamente. Se sei in x = -1, la derivata vale -2: stai scendendo. In x = 0, la derivata \u00e8 zero: sei nel punto pi\u00f9 basso.<\/p>\n\n\n\n<figure style=\"margin: 1.5em 0;text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.gironi.it\/blog\/wp-content\/uploads\/2026\/03\/slide-derivata-pendenza.jpg\" alt=\"Grafico della parabola f(x)=x\u00b2 con tre punti annotati: A (x=3, derivata=6, pendenza ripida), B (x=-1, derivata=-2, pendenza dolce), C (x=0, derivata=0, minimo)\" style=\"max-width: 100%;border: 1px solid #e0e0e0;border-radius: 6px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Il gradiente: una bussola multidimensionale<\/h3>\n\n\n\n<p>Nella realt\u00e0, le funzioni che ci interessano non dipendono da una sola variabile. Un modello di machine learning pu\u00f2 avere centinaia, migliaia, o miliardi di parametri. Il paesaggio non \u00e8 pi\u00f9 un sentiero, ma una superficie in uno spazio a molte dimensioni &mdash; impossibile da visualizzare, ma perfettamente gestibile dalla matematica.<\/p>\n\n\n\n<p>Il <strong>gradiente<\/strong> \u00e8 il vettore che raccoglie tutte le derivate parziali della funzione rispetto a ciascun parametro. Se la funzione dipende da due variabili (x, y), il gradiente \u00e8:<\/p>\n\n\n\n<p><strong>&nabla;f = (&#8706;f\/&#8706;x, &#8706;f\/&#8706;y)<\/strong><\/p>\n\n\n\n<p>Se dipende da mille variabili, il gradiente \u00e8 un vettore con mille componenti. In ogni caso, il gradiente punta nella direzione di massima salita. Per trovare il minimo, basta andare nella direzione opposta: <strong>meno il gradiente<\/strong>.<\/p>\n\n\n\n<p>Ecco la formula fondamentale della discesa del gradiente:<\/p>\n\n\n\n<p><strong>&theta;<sub>nuovo<\/sub> = &theta;<sub>vecchio<\/sub> &minus; &alpha; &middot; &nabla;f(&theta;)<\/strong><\/p>\n\n\n\n<p>Smontiamola pezzo per pezzo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>&theta;<\/strong> rappresenta i parametri del modello &mdash; le &#8220;manopole&#8221; che l&#8217;algoritmo regola per migliorare<\/li>\n<li><strong>&nabla;f(&theta;)<\/strong> \u00e8 il gradiente: indica la direzione di massima salita nel punto attuale<\/li>\n<li><strong>&alpha;<\/strong> (alpha) \u00e8 il <em>learning rate<\/em>: la dimensione del passo che facciamo ad ogni iterazione<\/li>\n<li>Il segno <strong>meno<\/strong> ci fa andare nella direzione opposta al gradiente, cio\u00e8 in discesa<\/li>\n<\/ul>\n\n\n\n<p>\u00c8 tutto qui. Calcola dove stai salendo, fai un passo nella direzione opposta, ripeti.<\/p>\n\n\n\n<figure style=\"margin: 1.5em 0;text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.gironi.it\/blog\/wp-content\/uploads\/2026\/03\/slide-anatomia-passo.jpg\" alt=\"Schema visuale della formula del gradient descent: theta (manopole del modello), alpha (learning rate come calibro), nabla f (gradiente come bussola), segno meno (direzione opposta)\" style=\"max-width: 100%;border: 1px solid #e0e0e0;border-radius: 6px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Un esempio numerico in R<\/h3>\n\n\n\n<p>Vediamo la discesa del gradiente in azione sulla funzione f(x) = x&sup2;. Sappiamo che il minimo \u00e8 in x = 0. L&#8217;algoritmo riesce a trovarlo partendo da un punto casuale?<\/p>\n\n\n\n<pre><code class=\"language-r\"># Discesa del gradiente su f(x) = x^2\n# La derivata e' f'(x) = 2x\n\nf &lt;- function(x) x^2         # funzione obiettivo\ngrad_f &lt;- function(x) 2 * x  # derivata (gradiente in 1D)\n\nx &lt;- 10              # punto di partenza\nalpha &lt;- 0.1          # learning rate\nn_iter &lt;- 50          # numero di iterazioni\npercorso &lt;- numeric(n_iter)\n\nfor (i in 1:n_iter) {\n  percorso[i] &lt;- x\n  x &lt;- x - alpha * grad_f(x)  # la regola fondamentale\n}\n\ncat(\"Punto di partenza: 10\\n\")\ncat(\"Dopo 50 iterazioni: x =\", round(x, 8), \"\\n\")\ncat(\"Valore della funzione:\", round(f(x), 10), \"\\n\")\n\n# Visualizzazione del percorso\ncurve(x^2, from = -11, to = 11, lwd = 2, col = \"steelblue\",\n      main = \"Discesa del gradiente su f(x) = x^2\",\n      xlab = \"x\", ylab = \"f(x)\")\npoints(percorso, percorso^2, col = \"red\", pch = 19, cex = 0.7)\nlines(percorso, percorso^2, col = \"red\", lty = 2)<\/code><\/pre>\n\n\n\n<p>Verifichiamo in Python:<\/p>\n\n\n\n<pre><code class=\"language-python\">import numpy as np\nimport matplotlib.pyplot as plt\n\n# Discesa del gradiente su f(x) = x^2\nf = lambda x: x**2           # funzione obiettivo\ngrad_f = lambda x: 2 * x     # derivata (gradiente in 1D)\n\nx = 10.0            # punto di partenza\nalpha = 0.1          # learning rate\nn_iter = 50          # numero di iterazioni\npercorso = np.zeros(n_iter)\n\nfor i in range(n_iter):\n    percorso[i] = x\n    x = x - alpha * grad_f(x)  # la regola fondamentale\n\nprint(f\"Punto di partenza: 10\")\nprint(f\"Dopo 50 iterazioni: x = {x:.8f}\")\nprint(f\"Valore della funzione: {f(x):.10f}\")\n\n# Visualizzazione del percorso\nxs = np.linspace(-11, 11, 200)\nplt.plot(xs, xs**2, lw=2, color=\"steelblue\")\nplt.plot(percorso, percorso**2, \"ro--\", markersize=4)\nplt.title(\"Discesa del gradiente su f(x) = x\u00b2\")\nplt.xlabel(\"x\")\nplt.ylabel(\"f(x)\")\nplt.show()<\/code><\/pre>\n\n\n\n<p>Eseguendo questo codice, si vede l&#8217;algoritmo partire da x = 10 e convergere rapidamente verso x = 0. I primi passi sono grandi (la pendenza \u00e8 ripida), poi si accorciano man mano che ci avviciniamo al fondo della parabola. Dopo 50 iterazioni, x \u00e8 praticamente zero.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"learning-rate\">Il learning rate: passi grandi o passi piccoli?<\/h2>\n\n\n\n<p>Torniamo alla nostra persona bendata. Quant&#8217;\u00e8 grande il passo che fa ad ogni iterazione? Questa \u00e8 esattamente la domanda del <strong>learning rate<\/strong> (&alpha;), e la risposta \u00e8 meno banale di quanto sembri.<\/p>\n\n\n\n<p><strong>Passi troppo piccoli<\/strong> (&alpha; molto basso): la persona si muove con cautela estrema, spostando un piede di pochi centimetri alla volta. Alla fine arriver\u00e0 in fondo alla valle, ma potrebbe impiegare un&#8217;eternit\u00e0. Nel machine learning, questo significa tempi di addestramento lunghissimi e costi computazionali elevati.<\/p>\n\n\n\n<p><strong>Passi troppo grandi<\/strong> (&alpha; troppo alto): la persona fa balzi enormi. Invece di scendere dolcemente nella valle, la scavalca, finisce dall&#8217;altra parte, rimbalza indietro, e continua a oscillare senza mai stabilizzarsi. In casi estremi, i salti diventano sempre pi\u00f9 grandi e la persona finisce pi\u00f9 in alto di dove era partita. Nel machine learning, questo si chiama <em>divergenza<\/em>: il modello peggiora invece di migliorare.<\/p>\n\n\n\n<p><strong>Passi giusti<\/strong>: un buon learning rate permette di scendere velocemente senza oscillare. Nella pratica, trovare il valore giusto richiede sperimentazione. \u00c8 uno degli aspetti pi\u00f9 artigianali del machine learning.<\/p>\n\n\n\n<figure style=\"margin: 1.5em 0;text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.gironi.it\/blog\/wp-content\/uploads\/2026\/03\/slide-learning-rate.jpg\" alt=\"Confronto visuale di tre learning rate sulla parabola: alpha=0.01 troppo lento con passi pigri, alpha=0.1 convergenza efficiente, alpha=0.9 oscillazione caotica\" style=\"max-width: 100%;border: 1px solid #e0e0e0;border-radius: 6px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Convergenza: sapere quando fermarsi<\/h3>\n\n\n\n<p>Come sa la persona bendata di essere arrivata? Sente che il terreno \u00e8 piatto in tutte le direzioni: il gradiente \u00e8 (quasi) zero. In pratica, l&#8217;algoritmo si ferma quando il miglioramento tra un&#8217;iterazione e l&#8217;altra diventa trascurabile, o quando ha raggiunto un numero massimo di iterazioni.<\/p>\n\n\n\n<p>I criteri di arresto pi\u00f9 comuni sono:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>La norma del gradiente scende sotto una soglia minima (il terreno \u00e8 quasi piatto)<\/li>\n<li>La differenza tra f(&theta;) di due iterazioni consecutive \u00e8 minore di una tolleranza fissata<\/li>\n<li>Si \u00e8 raggiunto il numero massimo di iterazioni (budget computazionale esaurito)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">L&#8217;effetto del learning rate: un confronto visuale<\/h3>\n\n\n\n<p>Questo codice R mostra l&#8217;effetto di tre diversi valori di learning rate sulla stessa funzione:<\/p>\n\n\n\n<pre><code class=\"language-r\"># Confronto di tre learning rate sulla funzione f(x) = x^2\ngradient_descent &lt;- function(x0, alpha, n_iter = 30) {\n  x &lt;- x0\n  percorso &lt;- numeric(n_iter)\n  for (i in 1:n_iter) {\n    percorso[i] &lt;- x\n    x &lt;- x - alpha * 2 * x  # theta_new = theta_old - alpha * grad\n  }\n  return(percorso)\n}\n\nx0 &lt;- 8  # stesso punto di partenza per tutti\n\n# Tre learning rate diversi\nlento    &lt;- gradient_descent(x0, alpha = 0.01)   # troppo piccolo\ngiusto   &lt;- gradient_descent(x0, alpha = 0.1)    # buon compromesso\nveloce   &lt;- gradient_descent(x0, alpha = 0.9)    # quasi instabile\n\n# Visualizzazione\npar(mfrow = c(1, 3))\n\n# alpha = 0.01 (troppo lento)\ncurve(x^2, from = -10, to = 10, lwd = 2, col = \"steelblue\",\n      main = expression(paste(alpha, \" = 0.01 (troppo lento)\")))\npoints(lento, lento^2, col = \"red\", pch = 19, cex = 0.6)\nlines(lento, lento^2, col = \"red\", lty = 2)\n\n# alpha = 0.1 (giusto)\ncurve(x^2, from = -10, to = 10, lwd = 2, col = \"steelblue\",\n      main = expression(paste(alpha, \" = 0.1 (buon compromesso)\")))\npoints(giusto, giusto^2, col = \"darkgreen\", pch = 19, cex = 0.6)\nlines(giusto, giusto^2, col = \"darkgreen\", lty = 2)\n\n# alpha = 0.9 (quasi instabile)\ncurve(x^2, from = -10, to = 10, lwd = 2, col = \"steelblue\",\n      main = expression(paste(alpha, \" = 0.9 (quasi instabile)\")))\npoints(veloce, veloce^2, col = \"orange\", pch = 19, cex = 0.6)\nlines(veloce, veloce^2, col = \"orange\", lty = 2)\n\npar(mfrow = c(1, 1))<\/code><\/pre>\n\n\n\n<p>Confrontiamo in Python:<\/p>\n\n\n\n<pre><code class=\"language-python\">import numpy as np\nimport matplotlib.pyplot as plt\n\ndef gradient_descent(x0, alpha, n_iter=30):\n    x = x0\n    percorso = np.zeros(n_iter)\n    for i in range(n_iter):\n        percorso[i] = x\n        x = x - alpha * 2 * x  # theta_new = theta_old - alpha * grad\n    return percorso\n\nx0 = 8.0  # stesso punto di partenza per tutti\nlento  = gradient_descent(x0, alpha=0.01)   # troppo piccolo\ngiusto = gradient_descent(x0, alpha=0.1)    # buon compromesso\nveloce = gradient_descent(x0, alpha=0.9)    # quasi instabile\n\nfig, axes = plt.subplots(1, 3, figsize=(14, 4))\nxs = np.linspace(-10, 10, 200)\nfor ax, dati, colore, titolo in zip(axes,\n        [lento, giusto, veloce],\n        [\"red\", \"darkgreen\", \"orange\"],\n        [\"\\u03b1 = 0.01 (troppo lento)\", \"\\u03b1 = 0.1 (buon compromesso)\",\n         \"\\u03b1 = 0.9 (quasi instabile)\"]):\n    ax.plot(xs, xs**2, lw=2, color=\"steelblue\")\n    ax.plot(dati, dati**2, \"o--\", color=colore, markersize=4)\n    ax.set_title(titolo)\nplt.tight_layout()\nplt.show()<\/code><\/pre>\n\n\n\n<p>Con &alpha; = 0.01 i punti rossi si muovono pigramente: dopo 30 iterazioni siamo ancora lontani dal minimo. Con &alpha; = 0.1 la convergenza \u00e8 rapida e pulita. Con &alpha; = 0.9 l&#8217;algoritmo oscilla vistosamente a ogni passo, rimbalzando da un lato all&#8217;altro della parabola prima di stabilizzarsi &mdash; un learning rate appena pi\u00f9 alto e divergerebbe del tutto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"problemi\">Cosa pu\u00f2 andare storto: l&#8217;intuizione geometrica<\/h2>\n\n\n\n<p>Il paesaggio matematico di un modello reale non \u00e8 una bella parabola simmetrica. \u00c8 un terreno selvaggio, con valli secondarie, creste, altipiani e forme che sfidano l&#8217;immaginazione. Ecco i problemi classici, spiegati con l&#8217;analogia del paesaggio.<\/p>\n\n\n\n<figure style=\"margin: 1.5em 0;text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.gironi.it\/blog\/wp-content\/uploads\/2026\/03\/slide-insidie-topografiche.jpg\" alt=\"Tre insidie della discesa del gradiente visualizzate in 3D: minimo locale (valle secondaria), punto di sella (gradiente zero ma non minimo), valle stretta (zigzag inefficiente)\" style=\"max-width: 100%;border: 1px solid #e0e0e0;border-radius: 6px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Minimi locali: le valli secondarie<\/h3>\n\n\n\n<p>Immagina un terreno con pi\u00f9 avvallamenti: una valle profonda (il minimo globale) e diverse vallette meno profonde (i minimi locali). La persona bendata non ha modo di sapere se la valle in cui si trova \u00e8 quella pi\u00f9 profonda. Sente il terreno piatto sotto i piedi e si ferma, convinta di essere arrivata. Ma potrebbe trovarsi in una valletta poco profonda, mentre il vero minimo \u00e8 da tutt&#8217;altra parte.<\/p>\n\n\n\n<p>Nella pratica, questo \u00e8 un problema meno grave di quanto si pensasse. Le reti neurali moderne hanno cos\u00ec tanti parametri che i minimi locali tendono ad avere valori della funzione obiettivo simili al minimo globale. \u00c8 come un terreno con molte valli, ma tutte pi\u00f9 o meno alla stessa altitudine: finire in una qualsiasi va bene.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Punti di sella: la sella di cavallo<\/h3>\n\n\n\n<p>Un problema pi\u00f9 insidioso sono i <strong>punti di sella<\/strong> (<em>saddle points<\/em>). Immagina di essere seduto su una sella di cavallo: se ti muovi avanti o indietro, scendi; se ti muovi a destra o sinistra, sali. In quel punto il gradiente \u00e8 zero &mdash; il terreno sembra piatto &mdash; ma non sei in un minimo. Sei su un punto che \u00e8 minimo in alcune direzioni e massimo in altre.<\/p>\n\n\n\n<p>In spazi ad alta dimensionalit\u00e0, i punti di sella sono molto pi\u00f9 comuni dei minimi locali. Fortunatamente, le varianti moderne della discesa del gradiente (con un po&#8217; di rumore o di momentum, come vedremo) riescono generalmente a sfuggire ai punti di sella.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Valli strette: lo zigzag<\/h3>\n\n\n\n<p>Immagina una valle molto stretta e allungata, come un canyon. Il gradiente punta quasi perpendicolarmente alle pareti del canyon, non lungo il canyon verso il fondo. La persona bendata finisce per rimbalzare da una parete all&#8217;altra, facendo uno zigzag inefficiente invece di camminare dritta verso il fondo.<\/p>\n\n\n\n<p>Questo accade quando le variabili del problema hanno scale molto diverse: alcune cambiano rapidamente, altre lentamente. \u00c8 un problema comune nella pratica, e una delle motivazioni principali per gli ottimizzatori avanzati come Adam, che vedremo nella sezione finale.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"scala\">Da una parabola a ChatGPT<\/h2>\n\n\n\n<p>Finora abbiamo visto la discesa del gradiente su una parabola: un problema con una sola variabile. \u00c8 il caso pi\u00f9 semplice possibile. Ma il bello di questo algoritmo \u00e8 che funziona esattamente allo stesso modo a qualsiasi scala.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">La scala dei parametri<\/h3>\n\n\n\n<p>Ecco come cresce il numero di parametri man mano che i modelli diventano pi\u00f9 complessi:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Regressione lineare semplice<\/strong>: 2 parametri (pendenza e intercetta). Il paesaggio \u00e8 una superficie 3D facile da visualizzare.<\/li>\n<li><strong>Rete neurale per riconoscere cifre scritte a mano<\/strong>: ~100.000 parametri. Il paesaggio ha 100.000 dimensioni.<\/li>\n<li><strong>ResNet-50<\/strong> (classificazione immagini, 2015): ~25 milioni di parametri.<\/li>\n<li><strong>GPT-3<\/strong> (il predecessore di ChatGPT): 175 miliardi di parametri.<\/li>\n<li><strong>GPT-4<\/strong> e modelli di frontiera (2023-2025): si stima oltre un trilione di parametri.<\/li>\n<\/ul>\n\n\n\n<p>Il principio \u00e8 identico: calcola il gradiente, fai un passo nella direzione opposta, ripeti. Quello che cambia \u00e8 la scala del calcolo. Il gradiente di GPT-4 \u00e8 un vettore con pi\u00f9 di mille miliardi di componenti, calcolato su miliardi di frammenti di testo, usando migliaia di processori in parallelo. Ma la formula \u00e8 la stessa che abbiamo visto sulla parabola.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dove lo vedi in azione (senza saperlo)<\/h3>\n\n\n\n<p>Ogni volta che interagisci con un sistema di intelligenza artificiale, la discesa del gradiente ha lavorato dietro le quinte:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Netflix e Spotify<\/strong> che ti consigliano cosa guardare o ascoltare: i modelli di raccomandazione sono addestrati con gradient descent su miliardi di interazioni utente<\/li>\n<li><strong>Google Translate<\/strong> e i traduttori automatici: reti neurali con centinaia di milioni di parametri, ottimizzate con discesa del gradiente su enormi corpora di testi paralleli<\/li>\n<li><strong>Assistenti vocali<\/strong> (Siri, Alexa): il riconoscimento vocale usa reti neurali profonde, addestrate con lo stesso algoritmo<\/li>\n<li><strong>Guida autonoma<\/strong>: le reti che riconoscono pedoni, semafori e corsie stradali sono addestrate con varianti della discesa del gradiente<\/li>\n<li><strong>ChatGPT, Claude, Gemini<\/strong>: i Large Language Model sono il caso pi\u00f9 estremo &mdash; la discesa del gradiente applicata a miliardi di parametri su trilioni di token di testo<\/li>\n<\/ul>\n\n\n\n<p>Il messaggio chiave \u00e8 questo: <strong>la potenza dell&#8217;AI moderna non sta nella complessit\u00e0 dell&#8217;algoritmo di ottimizzazione, ma nella scala<\/strong>. La discesa del gradiente \u00e8 concettualmente semplice. Quello che ha reso possibile la rivoluzione dell&#8217;intelligenza artificiale \u00e8 la capacit\u00e0 di applicarlo a modelli enormi su quantit\u00e0 enormi di dati, grazie a hardware sempre pi\u00f9 potente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"evoluzioni\">Le evoluzioni: scarpe migliori per il nostro esploratore<\/h2>\n\n\n\n<p>La discesa del gradiente &#8220;vanilla&#8221; &mdash; quella che abbiamo visto finora &mdash; funziona, ma ha i limiti che abbiamo descritto: pu\u00f2 essere lenta, pu\u00f2 oscillare, pu\u00f2 restare bloccata. Nel corso degli anni, i ricercatori hanno sviluppato varianti che risolvono questi problemi. Senza entrare nelle formule, ecco le idee chiave.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Stochastic Gradient Descent (SGD)<\/h3>\n\n\n\n<p>Invece di calcolare il gradiente sull&#8217;intero dataset ad ogni passo (computazionalmente costosissimo), SGD lo calcola su un piccolo campione casuale (<em>mini-batch<\/em>). \u00c8 come se la persona bendata, invece di tastare l&#8217;intero terreno intorno a s\u00e9, tastasse solo qualche punto a caso. La stima della pendenza \u00e8 rumorosa, ma mediamente corretta, e la velocit\u00e0 di calcolo \u00e8 enormemente maggiore. Il rumore, paradossalmente, \u00e8 anche utile: aiuta a sfuggire ai minimi locali e ai punti di sella.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Momentum<\/h3>\n\n\n\n<p>Immagina una palla che rotola gi\u00f9 per la collina invece di una persona che cammina. La palla accumula velocit\u00e0: se la pendenza continua nella stessa direzione, accelera. Se la pendenza cambia direzione, la palla rallenta prima di invertire. Questo \u00e8 il momentum: l&#8217;algoritmo &#8220;ricorda&#8221; la direzione in cui si stava muovendo e ci aggiunge il gradiente attuale. Il risultato \u00e8 che attraversa pi\u00f9 velocemente le zone piatte e oscilla meno nelle valli strette.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adam: il coltellino svizzero<\/h3>\n\n\n\n<p><strong>Adam<\/strong> (<em>Adaptive Moment Estimation<\/em>) combina l&#8217;idea del momentum con un learning rate che si adatta automaticamente per ogni parametro. I parametri che cambiano poco ottengono passi pi\u00f9 grandi; quelli che cambiano molto ottengono passi pi\u00f9 piccoli. \u00c8 come se la persona bendata avesse scarpe intelligenti che regolano la lunghezza del passo in base al terreno sotto ogni piede.<\/p>\n\n\n\n<p>Adam \u00e8 diventato lo standard de facto per addestrare la maggior parte delle reti neurali moderne. \u00c8 robusto, richiede poca regolazione manuale, e funziona bene in una vasta gamma di problemi. Quasi tutti i modelli che usi quotidianamente &mdash; da Spotify a ChatGPT &mdash; sono stati addestrati con Adam o con una sua variante.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ritorno alla montagna<\/h2>\n\n\n\n<p>La persona bendata da cui siamo partiti ora ha scarpe migliori. Ha una palla che accumula velocit\u00e0 invece di gambe che fanno passi rigidi. Ha suole che si adattano automaticamente al terreno. E soprattutto, non cammina su una montagna con due o tre dimensioni: cammina su un paesaggio con miliardi di dimensioni.<\/p>\n\n\n\n<p>Ma il principio \u00e8 esattamente lo stesso. Senti la pendenza. Fai un passo nella direzione in cui scende. Ripeti.<\/p>\n\n\n\n<p>La discesa del gradiente non \u00e8 un algoritmo spettacolare. Non ha la complessit\u00e0 elegante di un algoritmo genetico o il fascino narrativo delle reti adversariali. \u00c8 una procedura meccanica, quasi banale. Ma \u00e8 la procedura meccanica su cui si regge l&#8217;intera rivoluzione dell&#8217;intelligenza artificiale. Dai suggerimenti di Netflix ai modelli che generano immagini, dalla guida autonoma alla traduzione simultanea, tutto si riduce a questo: una funzione da minimizzare, un gradiente da calcolare, un passo da fare.<\/p>\n\n\n\n<p>La prossima volta che un assistente vocale capisce la tua domanda, o che un traduttore automatico indovina una sfumatura, ricorda: dietro le quinte, una versione molto sofisticata della nostra persona bendata ha camminato per miliardi di passi su un paesaggio con miliardi di dimensioni. E ha trovato una valle abbastanza profonda da essere utile.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una persona bendata su una montagna Immagina di trovarti su un terreno montagnoso, completamente bendato. Il tuo obiettivo: raggiungere il punto pi\u00f9 basso della valle. Non puoi vedere nulla, ma puoi sentire la pendenza del terreno sotto i piedi. Cosa fai? Ti muovi nella direzione in cui il terreno scende, un passo alla volta. Se &hellip; <a href=\"https:\/\/www.gironi.it\/blog\/lalgoritmo-di-discesa-del-gradiente-gradient-descent-spiegato-semplice\/\" class=\"more-link\">Leggi tutto<span class=\"screen-reader-text\"> &#8220;L&#8217;algoritmo di Discesa del Gradiente spiegato in modo chiaro: dall&#8217;intuizione alla pratica&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","footnotes":"[{\"content\":\"La funzione obiettivo e la funzione di costo sono termini che si usano spesso in modo intercambiabile, ma hanno anche delle sfumature diverse a seconda del contesto.<br>In generale, la funzione obiettivo \u00e8 una funzione che si vuole ottimizzare, cio\u00e8 massimizzare o minimizzare, in base a un certo criterio. La funzione di costo \u00e8 un tipo di funzione obiettivo che misura il \u201ccosto\u201d o la \u201cperdita\u201d associati a una soluzione o a una previsione. In altre parole, la funzione di costo \u00e8 una funzione obiettivo che si vuole minimizzare.<br>Ad esempio, se si vuole trovare la retta che meglio approssima un insieme di punti, si pu\u00f2 usare la regressione lineare. In questo caso, la funzione obiettivo \u00e8 l\u2019errore quadratico medio tra i punti e la retta, cio\u00e8 la somma dei quadrati delle distanze verticali tra i punti e la retta divisa per il numero dei punti. Questa funzione obiettivo \u00e8 anche una funzione di costo, perch\u00e9 rappresenta il costo di avere una retta non perfetta. L\u2019obiettivo \u00e8 trovare i parametri della retta che minimizzano questo costo.<br>Tuttavia, non tutte le funzioni obiettivo sono funzioni di costo. Alcune funzioni obiettivo possono essere funzioni di utilit\u00e0, di guadagno, di verosimiglianza, ecc. Queste sono funzioni che si vogliono massimizzare, perch\u00e9 rappresentano il beneficio o la probabilit\u00e0 associati a una soluzione o a una previsione. In questo caso, non si parla di costo o di perdita, ma di ottimizzazione.<br>Ad esempio, se si vuole trovare il modello probabilistico che meglio descrive un insieme di dati, si pu\u00f2 usare il metodo della massima verosimiglianza. In questo caso, la funzione obiettivo \u00e8 la probabilit\u00e0 di generare l\u2019insieme di dati dato il modello, cio\u00e8 il prodotto delle probabilit\u00e0 di ogni dato dato il modello. Questa funzione obiettivo non \u00e8 una funzione di costo, ma una funzione di verosimiglianza. L\u2019obiettivo \u00e8 trovare i parametri del modello che massimizzano questa verosimiglianza.\",\"id\":\"ec92aa27-198c-4cb8-9137-d3df169896e0\"}]"},"categories":[629,635],"tags":[637],"class_list":["post-3046","post","type-post","status-publish","format-standard","hentry","category-statistica-it","category-ai-it","tag-discesa-gradiente-it"],"lang":"it","translations":{"it":3046,"en":3266},"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"post-thumbnail":false},"uagb_author_info":{"display_name":"paolo","author_link":"https:\/\/www.gironi.it\/blog\/author\/paolo\/"},"uagb_comment_info":19,"uagb_excerpt":"Una persona bendata su una montagna Immagina di trovarti su un terreno montagnoso, completamente bendato. Il tuo obiettivo: raggiungere il punto pi\u00f9 basso della valle. Non puoi vedere nulla, ma puoi sentire la pendenza del terreno sotto i piedi. Cosa fai? Ti muovi nella direzione in cui il terreno scende, un passo alla volta. Se&hellip;","_links":{"self":[{"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/posts\/3046","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/comments?post=3046"}],"version-history":[{"count":5,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/posts\/3046\/revisions"}],"predecessor-version":[{"id":3557,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/posts\/3046\/revisions\/3557"}],"wp:attachment":[{"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/media?parent=3046"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/categories?post=3046"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gironi.it\/blog\/wp-json\/wp\/v2\/tags?post=3046"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}