Esercizio: best-fit numerico vs analitico (lineare)

Esercizio: best-t numerico vs analitico (lineare)
[email protected]; http://www.df.unipi.it/∼fuso/dida
(Dated: version 3 - FF, 9 novembre 2014)
Si aerma spesso che è generalmente meglio preferire metodi analitici a metodi numerici. Un caso
eclatante è quello del best-t dove, quando possibile, è sempre meglio eseguire un t analitico a una
funzione
lineare piuttosto che adarsi a metodi di minimizzazione numerici, spesso poco controllabili
e non sempre adabili, specialmente nella stima dell'incertezza da attribuire ai parametri di bestt.
Per esercizio (che tutti dovreste fare
da soli!)
proviamo qui a linearizzare e a minimizzare i
dati dell'esperienza sulla legge di Ohm con generatore reale, di cui ci siamo già occupati eseguendo
best-t numerici (con Python).
I.
ESEMPIO E LIMITAZIONE DEI DATI
Riprendiamo i dati acquisiti nell'esperienza sulla legge
di Ohm in presenza di un generatore di d.d.p.
reale,
decidendo di limitarci ad esaminare quei dati per i quali
il generatore può essere approssimato come ideale, cioè
quelli che consentono nel modello di porre trascurabili le
resistenze interne
rint .
In queste condizioni, la funzione
modello è la seguente:
I=
con
V0
V0
,
R
(1)
parametro libero del best-t. Come sappiamo, af-
nché questa funzione possa essere ritenuta ragionevole
occorre che le resistenze
Rj
impiegate (come carico) sia-
# limit the range by killing data points
# if R value is less than R_lim_low
R_lim_low = 0.3
index_kill=[]
for counter in range (0,len(R)):
if R[counter] < R_lim_low:
index_kill.append(counter)
R = numpy.delete(R,index_kill)
I = numpy.delete(I,index_kill)
dR = numpy.delete(dR,index_kill)
dI = numpy.delete(dI,index_kill)
Il mio set di dati è ora pronto per essere ragionevolmente analizzato secondo la funzione modello.
no molto maggiori delle resistenze interne, cioè che nel
circuito passino deboli correnti
Ij .
Poiché la resistenza
interna tipica dei generatori impiegati è
II.
rG ∼ 10 ohm, do-
BEST-FIT NUMERICO
vrebbe essere suciente considerare i soli dati acquisiti
per
Rj & 1
kohm. Qualcuno potrebbe osservare che per
Sappiamo già come eseguire un best-t numerico utiliz-
curve_fit di Python, dunque non mi di-
resistenze di tale ordine di grandezza devono essere mi-
zando la routine
surate correnti di intensità dell'ordine del mA, cioè usare
lungo nella descrizione (in ogni caso lo script si trova nel-
un fondo scala in cui la resistenza interna dello strumento
la mia pagina web sotto il nome
fit_ohm_ohm_law.py).
Rstrum = 100 ohm (nominali,
Nella procedura ho deciso di tenere conto dell'incer-
se si usa il multimetro digitale), per cui l'approssimazio-
tezza sulla misura delle resistenze eseguendo la som-
ne potrebbe essere poco giusticata.
ma in quadratura dell'incertezza
di misura (amperometro) è
Commenteremo a
posteriori su questo punto.
Dato che (i) l'algoritmo di minimizzazione implemen-
debitamente
∆I
dell'incertezza
∆R
propagata.
Il risultato è mostrato in Fig. 1, dove si nota un accordo
tato in Python non consente di limitare i dati conside-
niente male tra dati e funzione di t. I parametri ottenuti
rati, almeno non in modo immediato; (ii) sono pigro e
sono
non voglio riscrivere i dati su un nuovo le di testo, cerco
V0 = (4.85 ± 0.02)
χ2 = 6.8
ndof = 6 .
un modo poco elegante e non molto eciente per istruire Python a considerare solo i dati presi per
Rj > 0.3
kohm (vedete che decido di considerare anche valori che
V
(2)
(3)
(4)
mi aspetto non siano pienamente compatibili con l'assun-
V0 ,
zione fatta). Il modo consiste nello scansionare i valori
Il valore di
dell'array
biamo lasciato come parametro libero di t, è alcune
clo
for
R
che contiene i dati di resistenza con un ci-
(osservate la simpatica sintassi e ricordate l'in-
che, ricordiamo, in questo modello ab-
σ
lontano dall valore misurato a circuito aperto, che era
dent!) in modo da costruire un array di indici, chiamato
V0 = (4.94 ± 0.02) V, ma questo potrebbe essere spiegato
che punta ai valori del set di dati da non
dal punto di vista sico con l'aver trascurato la resisten-
considerare. Infatti tali valori vengono cancellati dagli ar-
za interna dello strumento, ovvero la caduta di potenziale
index_kill,
ray caricati tramite l'istruzione
numpy.delete
(al solito,
attenti alla sintassi!).
In buona sostanza, dopo aver caricato i dati dal le uso
queste righe di script:
da esso prodotta (il t restituisce per
V0
un valore minore
di quanto atteso), e, naturalmente, la resistenza interna
del generatore. Il
χ2
può essere considerato ragionevole
pur se, con soli sei gradi di libertà (i dati disponibili sono
2
ricordare quanto vale la derivata del logaritmo a base
Fit of a subset without internal resistance
102
10!). Le righe di script necessarie sono le seguenti:
# calculate the log10 of the data
# and the associated uncertainties
x = numpy.log10(R)
y = numpy.log10(I)
dy = dI/(I*numpy.log(10))
dx = dR/(R*numpy.log(10))
I [mA]
101
100
10-1
Le grandezze possono poi ovviamente essere gracate
(il risultato sarà presentato in seguito assieme ai best-t).
10-2
State attenti: se volete ottenere un andamento rettilineo,
stavolta dovete usare una rappresentazione su scala
re
linea-
. Infatti, a dierenza della rappresentazione bilogarit-
10-310-1
101
R [kohm]
100
Figura 1.
102
103
parametro libero
V0 ,
zate secondo il logaritmo, qui i dati sono già dei logaritmi, e quindi è necessario impiegare una rappresentazione
Graco dei dati sperimentali con sovrapposta la
funzione di t determinata
mica dove i dati sono quelli originali e le scale sono realiz-
per via numerica
lineare.
usando il solo
come discusso nel testo.
A.
pochi!), non è del tutto giusticato trarre conclusioni su
Fit numerico dei dati linearizzati
I dati così costruiti possono ovviamente essere sottoposti a best-t. Per cominciare e vedere quello che succede,
questo.
proviamo con il best-t numerico, attraverso la routine
curve_fit
III.
LINEARIZZAZIONE E FIT
linearizzata
.
Un modo molto semplice, che siete
invitati a provare, consiste nel rimpiazzare la variabile indipendente
R
con il proprio reciproco
1/R
(ovviamente
propagando l'errore in maniera opportuna). Qui usiamo
però un metodo un po' più ranato e istruttivo. Per linearizzare è infatti suciente applicare un logaritmo (lo
prendiamo a base 10 per praticità) al primo e secondo
membro per ottenere
log(I) = log(V0 ) − log(R)
(5)
ovvero:
(6)
y =a−x,
(7)
dove nell'ultimo passaggio abbiamo introdotto le variabili ttizie
y = log(I)
e
x = log(R).
La funzione sarà
−1,
che possiamo costruire con queste righe di script:
La funzione di t di Eq. 1 si presta ad essere facilmente
che già conosciamo bene.
una retta con coeciente angolare assegnato e pari a
La funzione appena
retta con coeciente angolare assegnato (pari a -1) e intercetta a = log(V ) da
determinare
scritta è praticamente una
0
.
Prima di procedere, facciamo una piccola osservazio-
ne: il logaritmo è un operatore che lavora su numeri, cioè
# define the fit function
def fit_function(x, a):
return (a - x)
Come valore iniziale della procedura di best-t porremo
il logaritmo (a base 10)
di un valore ragionevole per
V0 , per esempio log(5). Per analogia con il
caso precedente,
p come incertezza useremo la somma in
quadratura
(∆xi )2 + (∆yi )2 (qui la propagazione della d.d.p.
l'errore è proprio semplicissima!).
L'uscita dello script
restituisce il parametro di best-t
a
za stimata
∆a
e la sua incertez-
(per comodità posto lo script nella mia
pagina web sotto il nome
fit_ohm_lin_num.py,
ma vi
raccomando di provare a costruirlo da soli per esercizio).
Il parametro sico di interesse è
∆V0 .
V0 ,
con la sua incertezza
Ricordando che avevamo posto
plice ottenere le relazioni
V0 = 10a
e
a = log(V0 ), è sem∆V0 = ∆a10a a/10
(ripassate la propagazione degli errori per le potenze a
esponente reale!).
I risultati di questo best-t, che è quindi è un t
merico
nu-
applicato ai dati linearizzati secondo il logaritmo,
sono
grandezze adimensionate, per cui le scritture che abbia-
V0 = (4.8598 ± 0.0008)
χ2 = 5.2
ndof = 6 .
mo appena mostrato sono brutte e concettualmente poco
corrette: ce ne disinteressiamo, almeno per il momento.
Usando
Python
xj = log(Rj )
e
è
molto
facile
yj = log(Ij ),
costruire
gli
array
e anche attribuire al-
le grandezze di questi array un'incertezza calcolata ate
∆yj = |∆Ij /(log(10)Ij )|
V0
(8)
(9)
(10)
è in accordo con quello determinato
∆xj =
in precedenza sui dati non linearizzati e si nota come
(attenti a
la linearizzazione, che comporta l'uso di una funzione
traverso la propagazione dell'errore (massimo):
|∆Rj /(log(10)Rj )|
Il parametro
V
3
semplicemente
Numerical fit of the linearized subset
1.5
g = Σi=n
i=1
log(I/I0) , with I0 = 1 mA
1.0
0.5
(yi − (a − xi ))2
,
σi2
(11)
dove la somma si estende sul set di dati considerato e
0.0
σi2 = (∆yi )2 + (∆xi )2 .
Per ottenere il minimo della
funzione basta annullarne la derivata rispetto ad
0.5
1.0
0=
1.5
∂g
i=n yi − (a − xi )
.
= 2Σi=1
∂a
σi2
a:
(12)
Con un minimo di algebra si trova facilmente
2.0
2.51.0
0.5 0.0 0.5 1.0 1.5 2.0
log(R/R0) , with R0 = 1 kohm
2.5
i=n
a = Σi=1
3.0
yi + xi
.
n
(13)
Lavorando di propagazione dell'errore (preso in quadra-
Figura 2. Graco dei dati sperimentali linearizzati attraverso
per
via numerica usando il solo parametro libero V0 , come discus-
tura) si trova anche, altrettanto facilmente:
logaritmi con sovrapposta la funzione di t determinata
so nel testo. Notate la scarsa resa estetica del graco (e del
nome degli assi).
r
∆a =
Σi=n
i=1
(∆yi )2 + (∆xi )2
.
n2
(14)
I potenti mezzi di Python, in particolare della libreria
numpy, permettono di calcolare in un battibaleno le somme richieste.
più semplice per il best-t, porti a un aumento dell'accuratezza, cioè una riduzione dell'incertezza associata al parametro di best-t. Il
χ2
risultante dal best-t è
paragonabile (un po' inferiore) al precedente.
Il graco che risulta dalla procedura è mostrato in
Fig. 2.
Si vede come l'accordo tra dati e t sia anco-
ra molto buono, come atteso. Si nota anche, però, come
questo graco sia esteticamente bruttino, soprattutto per
Allo scopo si possono per esempio usare
queste linee di script:
# make the simple calculations needed
# for the linear fit
n = len(x)
a = numpy.sum(x/n+y/n)
delta_a = numpy.sqrt(numpy.sum(dy**2+dx**2)/n**2)
Quindi il parametro
a
e la sua incertezza
le scale impiegate. Inoltre, per il nome degli assi, tenendo
essere sfruttati per ottenere
conto di quanto aermato in precedenza sull'argomento
descritto sopra. I risultati sono
V0
e
∆V0
∆a
possono
secondo quanto già
della funzione logaritmo, ho deciso di usare la forma che
trovate in gura, che è anche poco bella e piuttosto prolissa. In generale, se si hanno dati per i quali è signicativo
impiegare una rappresentazione logaritmica, o bilogaritmica, è sempre meglio dal punto di vista estetico usarla
invece di gracare il logaritmo dei dati.
V0 = (4.8598 ± 0.0008)
χ2 = 5.2
ndof = 6 .
V
(15)
(16)
(17)
Come si può facilmente notare, questi risultati sono in
accordo con quelli del t numerico su dati linearizzati.
Questo ci conforta, in quanto suggerisce una buona adabilità, per gli scopi che ci preggiamo qui, della routine
B.
di best-t con algoritmo numerico; deve pur sempre far
Fit analitico dei dati linearizzati
riettere la dipendenza dal tipo di funzione usata dell'inLa semplicità della funzione di t che stiamo adottando
(Eq. 5) permette di arontare e risolvere in modo
co
χ
parametro libero
analitiun solo
il problema della minimizzazione dei residui quadrati
(o del 2
). Infatti la funzione è una retta con
, l'intercetta
a.
La funzione da minimizzare rispetto al parametro
certezza sul parametro di t, che dovrebbe essere sempre
considerata come una stima quando il set di dati è limitato e le barre di errore non provengono con sicurezza
da incertezza stocastica. Naturalmente il graco non lo
riporto, è indistinguibile da quello di Fig. 2; per comodità, lo script completo si può trovare nella mia pagina
a
è
web sotto il nome
fit_ohm_lin_anal.py.