Regressione quando ogni punto ha la sua incertezza sia in


12

Feci misurazioni di due variabili ed . Entrambi hanno conosciuto le incertezze e . Voglio trovare la relazione tra e . Come posso farlo?x y σ x σ y x ynxyσxσyxy

EDIT : ogni ha un diverso associato ad esso e lo stesso con .σ x , i y ixiσx,iyi


Esempio R riproducibile:

## pick some real x and y values 
true_x <- 1:100
true_y <- 2*true_x+1

## pick the uncertainty on them
sigma_x <- runif(length(true_x), 1, 10) # 10
sigma_y <- runif(length(true_y), 1, 15) # 15

## perturb both x and y with noise 
noisy_x <- rnorm(length(true_x), true_x, sigma_x)
noisy_y <- rnorm(length(true_y), true_y, sigma_y)

## make a plot 
plot(NA, xlab="x", ylab="y",
    xlim=range(noisy_x-sigma_x, noisy_x+sigma_x), 
    ylim=range(noisy_y-sigma_y, noisy_y+sigma_y))
arrows(noisy_x, noisy_y-sigma_y, 
       noisy_x, noisy_y+sigma_y, 
       length=0, angle=90, code=3, col="darkgray")
arrows(noisy_x-sigma_x, noisy_y,
       noisy_x+sigma_x, noisy_y,
       length=0, angle=90, code=3, col="darkgray")
points(noisy_y ~ noisy_x)

## fit a line 
mdl <- lm(noisy_y ~ noisy_x)
abline(mdl)

## show confidence interval around line 
newXs <- seq(-100, 200, 1)
prd <- predict(mdl, newdata=data.frame(noisy_x=newXs), 
    interval=c('confidence'), level=0.99, type='response')
lines(newXs, prd[,2], col='black', lty=3)
lines(newXs, prd[,3], col='black', lty=3)

regressione lineare senza considerare gli errori nelle variabili

Il problema con questo esempio è che penso che presupponga che non ci siano incertezze in . Come posso risolvere questo problema?x


Vero, si lmadatta a un modello di regressione lineare, cioè: un modello dell'attesa di rispetto a , in cui chiaramente è casuale e è considerato noto. Per affrontare l'incertezza in avrai bisogno di un modello diverso. P ( Y | X ) Y X XYP(Y|X)YXX
coniugato

1
Per il tuo caso piuttosto speciale (univariato con un rapporto noto di livelli di rumore per X e Y), la regressione Deming farà il trucco, ad esempio la Demingfunzione nel pacchetto R MethComp .
coniugato

1
@conjugateprior Grazie, questo sembra promettente. Mi chiedo: la regressione di Deming funziona ancora se ho una varianza diversa (ma ancora nota) su ogni singolo xey? cioè se le x sono lunghe e ho usato righelli con diverse precisioni per ottenere ogni x
rhombidodecahedron

Penso che forse il modo di risolverlo quando ci sono diverse varianze per ogni misurazione sta usando il metodo di York. Qualcuno capisce se esiste un'implementazione R di questo metodo?
rhombidodecahedron

1
@rhombidodecahedron Vedi che "con errori misurati" si adatta alla mia risposta lì: stats.stackexchange.com/questions/174533/… (che è stato preso dalla documentazione di deming del pacchetto).
Roland

Risposte:


9

Lascia che la vera linea , data da un angolo e un valore , sia l'insiemeθ γLθγ

(x,y):cos(θ)x+sin(θ)y=γ.

La distanza segnata tra qualsiasi punto e questa linea è(x,y)

d(x,y;L)=cos(θ)x+sin(θ)yγ.

Lasciando che la varianza di sia e quella di sia , l'indipendenza di e implica che la varianza di questa distanza èσ 2 i y i τ 2 i x i y ixiσi2yiτi2xiyi

Var(d(xi,yi;L))=cos2(θ)σi2+sin2(θ)τi2.

Troviamo quindi e per i quali la somma ponderata della varianza inversa delle distanze al quadrato è il più piccola possibile: sarà la soluzione di massima verosimiglianza se assumiamo che gli errori abbiano distribuzioni normali bivariate. Ciò richiede una soluzione numerica, ma è semplice trovare un con alcuni passaggi di Newton-Raphson che iniziano con un valore suggerito da un normale adattamento dei minimi quadrati.γθγ

Le simulazioni suggeriscono che questa soluzione è buona anche con piccole quantità di dati e valori relativamente grandi di e . Naturalmente, è possibile ottenere errori standard per i parametri nei modi consueti. Se sei interessato all'errore standard della posizione della linea, così come alla pendenza, potresti voler prima centrare entrambe le variabili su : ciò dovrebbe eliminare quasi tutta la correlazione tra le stime dei due parametri.τ i 0σiτi0


Il metodo funziona così bene con l'esempio della domanda che la linea adattata è quasi distinguibile dalla linea reale nella trama: si trovano all'interno di una unità o più l'una dall'altra ovunque. Invece, in questo esempio viene disegnato da una distribuzione esponenziale e sono disegnati da una distribuzione esponenziale con il doppio della scala (in modo che la maggior parte dell'errore tende a verificarsi nella coordinata ). Ci sono solo punti, un numero piccolo. I punti reali sono equamente distanziati lungo la linea con spaziatura unità. Questo è un test abbastanza severo, perché i potenziali errori sono evidenti rispetto alla gamma dei punti.σ i x n = 8τiσixn=8

figura

La linea vera è mostrata in blu punteggiato. Lungo di essa i punti originali sono tracciati come cerchi vuoti. Le frecce grigie le collegano ai punti osservati, tracciati come dischi neri solidi. La soluzione viene disegnata come una linea rossa continua. Nonostante la presenza di grandi deviazioni tra i valori osservati e quelli effettivi, la soluzione è notevolmente vicina alla linea corretta all'interno di questa regione.

#
# Generate data.
#
theta <- c(1, -2, 3) # The line is theta %*% c(x,y,-1) == 0
theta[-3] <- theta[-3]/sqrt(crossprod(theta[-3]))
n <- 8
set.seed(17)
sigma <- rexp(n, 1/2)
tau <- rexp(n, 1)
u <- 1:n
xy.0 <- t(outer(c(-theta[2], theta[1]), 0:(n-1)) + c(theta[3]/theta[1], 0))
xy <- xy.0 + cbind(rnorm(n, sd=sigma), rnorm(n, sd=tau))
#
# Fit a line.
#
x <- xy[, 1]
y <- xy[, 2]
f <- function(phi) { # Negative log likelihood, up to an additive constant
  a <- phi[1]
  gamma <- phi[2]
  sum((x*cos(a) + y*sin(a) - gamma)^2 / ((sigma*cos(a))^2 + (tau*sin(a))^2))/2
}
fit <- lm(y ~ x) # Yields starting estimates
slope <- coef(fit)[2]
theta.0 <- atan2(1, -slope)
gamma.0 <- coef(fit)[1] / sqrt(1 + slope^2)
sol <- nlm(f,c(theta.0, gamma.0))
#
# Plot the data and the fit.
#
theta.hat <- sol$estimate[1] %% (2*pi)
gamma.hat <- sol$estimate[2]
plot(rbind(xy.0, xy), type="n", xlab="x", ylab="y")
invisible(sapply(1:n, function(i) 
  arrows(xy.0[i,1], xy.0[i,2], xy[i,1], xy[i,2], 
         length=0.15, angle=20, col="Gray")))
points(xy.0)
points(xy, pch=16)
abline(c(theta[3] / theta[2], -theta[1]/theta[2]), col="Blue", lwd=2, lty=3)
abline(c(gamma.hat / sin(theta.hat), -1/tan(theta.hat)), col="Red", lwd=2)

+1. A quanto ho capito, questo risponde anche a questa vecchia Q: stats.stackexchange.com/questions/178727 ? Dovremmo chiuderlo come duplicato allora.
ameba dice Ripristina Monica il

Inoltre, secondo il mio commento alla risposta in quel thread, sembra che anche la demingfunzione possa gestire errori variabili. Probabilmente dovrebbe dare una vestibilità molto simile alla tua.
ameba dice Ripristina Monica il

Mi chiedo se il flusso della discussione abbia più senso se cambi i posti dei 2 paragrafi sopra e sotto la figura?
gung - Ripristina Monica

3
Mi è stato ricordato stamattina (da un elettore) che questa domanda era stata posta e risposto in molti modi, con codice funzionante, diversi anni fa sul sito di Mathematica SE .
whuber

Questa soluzione ha un nome? e forse una risorsa per ulteriori letture (oltre al sito Mathematica SE intendo)?
JustGettin è partito il

0

York (2004) ha affrontato la massima ottimizzazione della probabilità per il caso di incertezze in xey. Ecco il codice R per la sua funzione.

"YorkFit", scritto da Rick Wehr, 2011, tradotto in R da Rachel Chang

Routine universale per trovare la migliore linea retta adatta ai dati con errori variabili e correlati, inclusi errori e bontà delle stime di adattamento, seguendo l'Eq. (13) di York 2004, American Journal of Physics, che a sua volta era basato su York 1969, Earth and Planetary Sciences Letters

YorkFit <- funzione (X, Y, Xstd, Ystd, Ri = 0, b0 = 0, printCoefs = 0, makeLine = 0, eps = 1e-7)

X, Y, Xstd, Ystd: onde contenenti punti X, punti Y e le loro deviazioni standard

ATTENZIONE: Xstd e Ystd non possono essere zero poiché questo causerà Xw o Yw come NaN. Utilizzare invece un valore molto piccolo.

Ri: coefficienti di correlazione per errori X e Y - lunghezza 1 o lunghezza di X e Y

b0: ipotesi iniziale approssimativa per la pendenza (può essere ottenuta da un adattamento dei minimi quadrati standard senza errori)

printCoefs: impostare uguale a 1 per visualizzare i risultati nella finestra di comando

makeLine: impostare uguale a 1 per generare un'onda Y per la linea di adattamento

Restituisce una matrice con l'intercetta e la pendenza più le loro incertezze

Se non viene fornita alcuna ipotesi iniziale per b0, utilizzare OLS se (b0 == 0) {b0 = lm (Y ~ X) $ coefficienti [2]}

tol = abs(b0)*eps #the fit will stop iterating when the slope converges to within this value

a, b: intercettazione finale e pendenza a.err, b.err: incertezze stimate in intercetta e pendenza

# WAVE DEFINITIONS #

Xw = 1/(Xstd^2) #X weights
Yw = 1/(Ystd^2) #Y weights


# ITERATIVE CALCULATION OF SLOPE AND INTERCEPT #

b = b0
b.diff = tol + 1
while(b.diff>tol)
{
    b.old = b
    alpha.i = sqrt(Xw*Yw)
    Wi = (Xw*Yw)/((b^2)*Yw + Xw - 2*b*Ri*alpha.i)
    WiX = Wi*X
    WiY = Wi*Y
    sumWiX = sum(WiX, na.rm = TRUE)
    sumWiY = sum(WiY, na.rm = TRUE)
    sumWi = sum(Wi, na.rm = TRUE)
    Xbar = sumWiX/sumWi
    Ybar = sumWiY/sumWi
    Ui = X - Xbar
    Vi = Y - Ybar

    Bi = Wi*((Ui/Yw) + (b*Vi/Xw) - (b*Ui+Vi)*Ri/alpha.i)
    wTOPint = Bi*Wi*Vi
    wBOTint = Bi*Wi*Ui
    sumTOP = sum(wTOPint, na.rm=TRUE)
    sumBOT = sum(wBOTint, na.rm=TRUE)
    b = sumTOP/sumBOT

    b.diff = abs(b-b.old)
  }     

   a = Ybar - b*Xbar
   wYorkFitCoefs = c(a,b)

# ERROR CALCULATION #

Xadj = Xbar + Bi
WiXadj = Wi*Xadj
sumWiXadj = sum(WiXadj, na.rm=TRUE)
Xadjbar = sumWiXadj/sumWi
Uadj = Xadj - Xadjbar
wErrorTerm = Wi*Uadj*Uadj
errorSum = sum(wErrorTerm, na.rm=TRUE)
b.err = sqrt(1/errorSum)
a.err = sqrt((1/sumWi) + (Xadjbar^2)*(b.err^2))
wYorkFitErrors = c(a.err,b.err)

# GOODNESS OF FIT CALCULATION #
lgth = length(X)
wSint = Wi*(Y - b*X - a)^2
sumSint = sum(wSint, na.rm=TRUE)
wYorkGOF = c(sumSint/(lgth-2),sqrt(2/(lgth-2))) #GOF (should equal 1 if assumptions are valid), #standard error in GOF

# OPTIONAL OUTPUTS #

if(printCoefs==1)
 {
    print(paste("intercept = ", a, " +/- ", a.err, sep=""))
    print(paste("slope = ", b, " +/- ", b.err, sep=""))
  }
if(makeLine==1)
 {
    wYorkFitLine = a + b*X
  }
 ans=rbind(c(a,a.err),c(b, b.err)); dimnames(ans)=list(c("Int","Slope"),c("Value","Sigma"))
return(ans)
 }

Inoltre, il pacchetto R "IsoplotR" include la funzione york (), fornendo qui gli stessi risultati del codice YorkFit.
Steven Wofsy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.