Regressione lineare

La regressione lineare: quante volte la usate? E in quante forme? La radice del termine: il regredi latino, il tornare indietro, ripercorrere. Cerchiamo di produrre funzioni lineari, semplici rette nel piano cartesiano, che possano approssimare bene la disposizione di famiglie di valori puntiformi. E’ formalmente corretto parlare di regressione lineare quando ci riferiamo alla ricerca di una retta che minimizzi gli scarti generati nel confronto con le coordinate dei punti che essa tenta di rappresentare.

Prendiamo un gruppo di valori a caso che costituiscano le coordinate di punti su un piano cartesiano – i consueti due assi x e y: coppie di valori a rappresentarne le coordinate. Potremmo impiegare per le x i valori (1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003) e per le y i valori (30.23 37.26 28.96 33.75 41.68 33.72 31.62 26.97 24.5 25.64 30.24 27.31 17.91 24.76 37.99 31.69 31.94 35.97); si faccia caso alla notazione anglosassone, i punti equivalgono alle nostre virgole. Piazziamo il tutto su un foglio di calcolo e vediamo cosa restituisce per via grafica.

Interpolazione lineare prezzi risorsaQuello che abbiamo messo assieme sul foglio di calcolo è una famiglia di valori, coppie di coordinate (x,y), che rappresentano dei punti. La linea rossa nel mezzo è la migliore regressione lineare offerta dal foglio di calcolo in OpenOffice, con la relativa formula del tipo y = m*x + c. Ovviamente una retta con il suo bel coefficiente angolare m e la sua intercetta sull’asse delle ordinate. Si tratta della correlazione che riesce a rappresentare meglio la famiglia di punti: cioè che minimizza lo scarto esistente tra il valore che propone ed il valore effettivo delle coordinate dei punti da cui deriva. Come fa il programma del foglio di calcolo a dedurla? Usa una legge matematica generica adattabile a qualsivoglia numero di punti del piano – anche grande – che si può esprimere, tra le varie possibilità esistenti, nella maniera seguente (la restituzione grafica della formula è opera del programma Math):

Formula generica interpolazione lineare n punti del piano cartesianoQueste due espressioni rappresentano, per n coppie di valori (x,y) dati, il coefficiente angolare m e l’intercetta sull’asse delle ordinate c della funzione f(x) = m*x + c; la retta del piano cartesiano che meglio approssima tutti i punti dati che vuole rappresentare. A stento si potrebbe parlare di matematica, visto il livello delle operazioni impiegate. Proviamo con un esempio semplice: i tre punti di coordinata (1,2) (2,3) (3,4), potreste indovinarla anche ad occhio. I denominatori delle espressioni di cui sopra valgono entrambi 3 * (1 + 4 + 9) – (1 + 2 + 3) ^2 = 6. Ergo possiamo trovare m, che vale [(2 + 3 + 4) * (1 + 4 + 9) – (1 + 2 + 3) * (2 + 6 + 12)] / 6 = [9 * 14 – 6*20] / 6 = 1. Il valore di c risulta [3*(2 + 6 + 12) – (1 + 2 + 3)*(2 + 3 + 4)] / 6 = [3*20 – 6*9] / 6 = 1. Tanta fatica per disegnare una retta avente pendenza unitaria – vale 1, cioè 100 %, una inclinazione di 45° – ed intercetta all’asse delle ordinate anch’essa unitaria. Una cosa stupida, almeno fin quando non ci troviamo la scia di valori ipotizzata nel primo grafico: tante coppie a caso con tanti valori dotati di decimali. Vi voglio vedere a farvi a mano la regressione lineare di quella roba. Ci diventate vecchi.

E’ in casi simili che cerchiamo di servirci di un calcolatore, magari impiegando un foglio di calcolo. Può essere che il programma non vi soddisfi, perché magari si pianta con tanti valori o perché restituisce coefficienti arrotondati in maniera troppo rozza; e vorreste stabilire direttamente quanti decimali tirarvi dietro nei singoli passaggi. La soluzione che viene in mente a me è quella di usare la shell Bash su una macchina Linux. Io uso questa roba per abitudine; è qualcosa di semplice, funzionale ed affidabile. Possiamo quindi provare a scrivere nella shell:


#!/bin/bash

echo via!

SX=0 #sommatoria ascisse
SY=0 #sommatoria ordinate
SXQ=0 #sommatoria quadrati ascisse
SYQ=0 #sommatoria quadrati ordinate
SXY=0 #sommatoria prodotti ascisse ordinate
DOT=15 #numero di decimali richiesti nei calcoli

#caricamento array ascisse ed ordinate
x=(1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003)
y=(30.23 37.26 28.96 33.75 41.68 33.72 31.62 26.97 24.5 25.64 30.24 27.31 17.91 24.76 37.99 31.69 31.94 35.97)

#conteggio del numero di elementi caricati nell'array delle ascisse
n=${#x[@]}
echo "$n elementi"

i=0

while [ $i -lt $n ]
do
SX=$(echo "scale=$DOT; ${x[$i]}+$SX" | bc)
SY=$(echo "scale=$DOT; ${y[$i]}+$SY" | bc)
SXQ=$(echo "scale=$DOT; ${x[$i]}^2+$SXQ" | bc)
SYQ=$(echo "scale=$DOT; ${y[$i]}^2+$SYQ" | bc)
SXY=$(echo "scale=$DOT; ${x[$i]}*${y[$i]}+$SXY" | bc)
((i=i+1))
done

#stampo i parziali
echo "x = $SX, y= $SY, x quadrato = $SXQ, y quadrato = $SYQ, prodotto x y = $SXY"

#calcolo equazione retta di regressione
denom=$(echo "scale=$DOT; $n*$SXQ-($SX^2)" | bc)
echo "denominatore: $denom"
numerM=$(echo "scale=$DOT; $n*$SXY-$SX*$SY" | bc)
echo "numeratore per coefficiente angolare: $numerM"
numerC=$(echo "scale=$DOT; $SY*$SXQ-$SX*$SXY" | bc)
echo "numeratore per intercetta asse ordinate $numerC"
M=$(echo "scale=$DOT; $numerM/$denom" | bc)
C=$(echo "scale=$DOT; $numerC/$denom" | bc)

end="Equazione retta: y = $M x + $C e saluti"
echo $end
echo $end > risultato_regressione
sleep 7

In pratica lo script – eventualmente salvato in un file di testo con permessi d’esecuzione – provvede a calcolare i parametri di una regressione lineare basandosi sui valori di (x,y) immessi con i due array per le coordinate. La libreria bc è necessaria per consentire alla shell di gestire calcoli su numeri reali dotati di componente frazionaria. Nel caso di esempio, chiediamo alla macchina di eseguire il calcolo sui medesimi 18 valori fatti masticare al foglio di calcolo; operando sempre a 15 decimali significativi. Ne otteniamo una equazione per la regressione lineare del tipo y = -0.179195046439628 x + 388.078964568283453. In effetti in buon accordo con i valori proposti da OpenOffice almeno per le prime 12 cifre dopo la virgola; per spingersi oltre bisognerebbe poter controllare meglio il comportamento del programma, ma non è detto che sia così rilevante.

Si noti che la soluzione su shell è leggermente più impegnativa, ma consente di fare cose che sarebbero altrimenti improponibili: tipo mandare giù gli orpelli grafici e saturare il processore e la memoria con i soli calcoli, oppure ancora operare su cinquanta cifre significative o cose simili. E’ anche possibile far digerire ad uno script una regressione basata su decine di migliaia di valori, per quanto si tratti di una operazione molesta per il nostro hardware. Tentare operazioni simili su dei fogli di calcolo fa sorgere qualche rischio di crash per il programma o per il sistema, anche per chi utilizza un carrarmato sovietico come Lxde o simili. Onestamente devo dire che con il tempo sto rivalutando l’agilità e la potenza degli emulatori di terminale. Non sempre la grafica pesante a cui siamo abituati rappresenta un reale vantaggio.

Altro problema: la rappresentatività delle regressioni lineari. Non è detto che siano efficaci, noi umani ne abusiamo facilmente. Sono semplici, una volta bastava utilizzare un righello per realizzarle tramite bisezione: con risultati talora terribilmente imprecisi. Se c’è una cosa davvero sbagliata che possiamo fare però, questa è un’altra: tentare di predire il futuro estrapolando rozze regressioni lineari. Una correlazione lineare dovrebbe essere utilizzata nel suo effettivo campo di esistenza, e cioè dentro allo spazio del piano cartesiano popolato dai valori da cui deriva. Purtroppo non tutti la pensano in questo modo. Ma la colpa non è né dei fogli di calcolo né degli script per Bash: è tutto un problema di istinti insiti nella nostra mente, e nessun computer potrà mai cambiare questo stato di cose. Se non vedete i puntini lì attorno, diffidate della regressione: forse vi stanno vendendo favole.

Annunci
Questa voce è stata pubblicata in varie e contrassegnata con , , , , , , , , , , , , . Contrassegna il permalink.

3 risposte a Regressione lineare

  1. ijk_ijk ha detto:

    Bel post ed utile. Molto meglio di Wikipedia almeno per me.

  2. ijk_ijk ha detto:

    A proposito di shell unix, ricordo un mio collega che negli anni 80 faceva i sistemi del totocalcio in questo modo su un mainframe. Ci si scervellava ore e noi pagavamo le quote dopo lunghe votazioni su come impostare i sistemi; ovviamente non vincemmo mai nulla.

    • fausto ha detto:

      Il totocalcio calcolato su shell è un’idea notevole, anche se non del tutto fuori posto: in definitiva i sistemi Unix / Linux sono nati per giocare! Mi spiace che non ne abbiate cavato nulla….

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...