Forum

Nome Utente:
Password:
Riconoscimi automaticamente
 Tutti i Forum
 MolecularLab
 Bioinformatica
 [R] nls e selfstart
 Nuova Discussione  Nuovo Sondaggio Nuovo Sondaggio
 Rispondi Aggiungi ai Preferiti Aggiungi ai Preferiti
Cerca nelle discussioni
I seguenti utenti stanno leggendo questo Forum Qui c'è:

Aggiungi Tag Aggiungi i tag

Quanto è utile/interessante questa discussione:

Autore Discussione  

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 22 dicembre 2010 : 13:46:11  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
Ciao a tutti,

eccoci di nuovo a parlare di R.
In questi giorni ho dovuto fare dei fitting, in particolare a partire da un set di valori sperimentali x e y dovevo imporre il modello y = A*exp(-k*x)+q e trovare k. E' la prima volta che faccio fitting non lineari, nel mo lab se non sbaglio usano Origin (mai usato), ma io ho voluto usare R. Leggendo un po' qua un po' là ho usato la funzione nls e dopo varie prove penso di avercela fatta.

Ora la rottura che ho trovato è la seguente: i valori da impostare in start=list(). Praticamente io li ho messi a occhio osservando il plot e facendo un po' di prove finchè nls non andava a buon fine. Così però è una rottura non posso fare degli script automatici, in Origin mi sembrava li stimasse da solo. Ho letto che ci sono funzioni di selfstart (SS) ma non ho ben chiaro come funzionano.

Sapete indicarmi una soluzione?

P.s. avrei potuto provare a linearizzare e usare lm per poi risalire ai coefficienti ma volevo usare il modo diretto.

grazie

chick80
Moderatore

DNA

Città: Edinburgh


11491 Messaggi

Inserito il - 22 dicembre 2010 : 18:34:04  Mostra Profilo  Visita l'Homepage di chick80 Invia a chick80 un Messaggio Privato  Rispondi Quotando
Non ho mai usato selfstart, però ho visto che usare questi starting parameters funziona bene per curve esponenziali

per A: max(y) - min(y)
per k: La x corrispondente al valore che più si avvicina alla media dei valori
per q: min(y)

Ad es:


# Definiamo una funzione esponenziale
expon <- function(x, A, k, q)
    {
    return(A*(exp(-x/k))+q)
    }


# Creiamo una distribuzione di valori con andamento esponenziale
xval <- seq(1, 30, 0.1)
A = 9
k = 5
q = 4.5
yval <- expon(xval, A, k, q)
noise <- rnorm(length(xval), 0, 0.08)
# Aggiungiamo un po' di "disturbo"
yval <- yval + noise

plot(xval, yval, pch=20, cex=0.8)

# Parametri iniziali
startA <- max(yval)-min(yval)
startk <- xval[which.min(abs(yval-mean(yval)))]
startq <- min(yval)
fit <- nls(yval ~ expon(xval, A, k, q), start = c(A=startA, k=startk, q=startq))

fitted.params <- coef(fit)
lines(xval, expon(xval, fitted.params[1], fitted.params[2], fitted.params[3]), col="red", lwd=2)


Domanda più o meno correlata che avevo posto su StackOverflow:
http://stackoverflow.com/questions/2963729/r-catching-errors-in-nls

Sei un nuovo arrivato?
Leggi il regolamento del forum e presentati qui

My photo portfolio (now on G+!)
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 23 dicembre 2010 : 09:35:17  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
Avevo notato anche io che per A e per q si potevano usare quei valori, il prob era k, faccio un po' di prove seguendo il tuo consiglio e vediamo..

ti ringrazio.

Poi se qualcuno ha delle delucidazioni sulle funzioni di selfstart può fare chiarezza ad entrambi!
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 23 dicembre 2010 : 10:39:26  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
Dunque, dato che la mia funzione è un po' diversa ho fatto qualche modifica ai parametri iniziali.
Per uno script che da clipboard si prende i dati il risultato è questo. Per k ho dovuto fare il reciproco e per q ho preso il max altrmenti non andavano con la mia funzione, devo fare altre prove però.

dataset <- read.table("clipboard", sep="\t", na.strings="NA", dec=".", strip.white=TRUE, blank.lines.skip=TRUE)

plot(dataset)

# Function
expon <- function(x, A, k, q) {
    return(A*(exp(-k*x))+q)
}

attach(dataset)
# Start estimates
startA <- max(V2)-min(V2)
startk <- 1/(V1[which.min(abs(V2-mean(V2)))])
startq <- max(V2)

#Fitting
nlsfit <- nls(V2 ~ expon(V1, A, k, q), start = c(A=startA, k=startk, q=startq))

#Draw exponential curve
fitted.params <- coef(nlsfit)
lines(V1, expon(V1, fitted.params[1], fitted.params[2], fitted.params[3]), col="red", lwd=2)


Intanto aspettiamo altri suggerimenti.

Grazie
Torna all'inizio della Pagina

chick80
Moderatore

DNA

Città: Edinburgh


11491 Messaggi

Inserito il - 23 dicembre 2010 : 12:23:37  Mostra Profilo  Visita l'Homepage di chick80 Invia a chick80 un Messaggio Privato  Rispondi Quotando
Puoi ancora migliorare startk moltiplicandolo per ln2.

L'idea è che essendo:

x1/2 = ln2 * k

prendiamo la y1/2 come stima dell'ordinata di x1/2. Sicuramente ci sono metodi migliori di stimarla, ma nls sembra fare un buon lavoro...

Sei un nuovo arrivato?
Leggi il regolamento del forum e presentati qui

My photo portfolio (now on G+!)
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 29 dicembre 2010 : 11:54:39  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
chick stavo ripensando al tuo metodo per approssimare k, ovvero nel caso del tuo esponenziale [A*(exp(-x/k))+q)]:


startk <- xval[which.min(abs(yval-mean(yval)))]


puoi spiegarmi i singoli passaggi che hai fatto?

Inoltre, se non ho capito male vuoi approssimare l'x di dimezzamento (x1/2) con la x della media delle y?

per definizione x1/2 sarebbe l'ascissa del punto in cui y è 1/2 del segnale no?

per quanto riguarda il moltiplicare per ln2 sei partito dalla formula di k, ovvero k=ln(2)/x1/2 ? In questo caso x1/2 = ln(2)/k, diviso non moltiplicato. Questa formula vale anche nel nostro caso, avendo un +q?

Mi sto un po' confondendo comunque,
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 29 dicembre 2010 : 14:36:18  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
ok mi rispondo da solo,

    1) tu avevi in mente la tua funzione (y=Aexp(-x/k)+q), quindi va bene il *.

    2) per quanto riguarda le nostre funzioni con q la formula per x1/2 dovrebbe diventare così:

    x1/2 = k*(ln2+ln(q/A)) per la tua funzione y=A*exp(-x/k)+q

    x1/2 =(ln2+ln(q/A))/k per la mia funzione y=A*exp(-kx)+q

    sono un po' arrigginito in matematica, ma spero di aver fatto bene i conti.

    3) per approssimare x1/2 prendi il punto con y più vicina alla media delle y e ne ricavi la x.
    Ok fatto questo per approssimare k non resta che usare l'equazione del punto 2.

Ci siamo, dopo riscrivo gli script (sia per la mia che per la tua funzione) e li posto, almeno si possono testare e sviluppare.
Torna all'inizio della Pagina

chick80
Moderatore

DNA

Città: Edinburgh


11491 Messaggi

Inserito il - 30 dicembre 2010 : 09:10:25  Mostra Profilo  Visita l'Homepage di chick80 Invia a chick80 un Messaggio Privato  Rispondi Quotando
Sì, il mio ragionamento era essenzialmente quello che hai scritto!

Ovviamente non avrai mai un punto (x/2; y/2), ma è un'approssimazione che in media funziona (salvo per valori di k molto alti o molto bassi dove ogni tanto avrai errore).

Sei un nuovo arrivato?
Leggi il regolamento del forum e presentati qui

My photo portfolio (now on G+!)
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 31 dicembre 2010 : 10:11:14  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
Posto lo script modificato, ricordo che è fatto per i casi di crescita esponenziale, con funzione y=A*exp(-k*x)+q. Se avete un decadimento esponenziale lo script cambia un po', leggete sopra.
Sarebbe utile fare uno script che riconosce in che caso siamo, magari nei prossimi giorni ci penso.
Allego l'output dello script.

Allegato: Rplots.pdf
5,85 KB

E questo è lo script (è fatto per prendere le colonne x,y attraverso la clipboard):
rm(list=ls())

dataset <- read.table("clipboard", sep="\t", na.strings="NA", dec=".", strip.white=TRUE, blank.lines.skip=TRUE)

plot(dataset)

# Function
expon <- function(x, A, k, q) {
    return(A*(exp(-k*x))+q)
}

attach(dataset)
# Start estimates
startA <- max(V2)-min(V2)
startq <- max(V2)

# Per approssimare k si parte approssimando x1/2 prendendo il punto con y più vicina alla media delle y e se ne ricava la x.
# Usando la relazione tra k e x1/2 : x1/2 =(ln2+ln(q/A))/k,
# k viene approssimato facendo (ln2+ln(q/A))/x1/2

startk <- (log(2)+log(startq/startA))/(V1[which.min(abs(V2-mean(V2)))]) 

#Fitting
nlsfit <- nls(V2 ~ expon(V1, A, k, q), start = c(A=startA, k=startk, q=startq))

#Draws exponential curve
fitted.params <- coef(nlsfit)
lines(V1, expon(V1, fitted.params[1], fitted.params[2], fitted.params[3]), col="red", lwd=2)

#Writes parameters on the plot
mtext(line=0.5,paste("A=",fitted.params[1]," k=",fitted.params[2], " q=",fitted.params[3]),adj=1, cex=1)

detach(dataset)
Torna all'inizio della Pagina

chick80
Moderatore

DNA

Città: Edinburgh


11491 Messaggi

Inserito il - 31 dicembre 2010 : 10:25:07  Mostra Profilo  Visita l'Homepage di chick80 Invia a chick80 un Messaggio Privato  Rispondi Quotando
Citazione:
Sarebbe utile fare uno script che riconosce in che caso siamo, magari nei prossimi giorni ci penso


Basta guardare se i valori hanno tendenza a crescere o a diminuire.

Molto brutalmente, se i valori salgono:
coef(lm(yval~xval))[2] > 0


Ovvero: chiami lm per fare una regressione lineare, ne estrai i coefficienti (intercetta e coefficiente angolare della retta) con coef e poi prendi il secondo che è il coefficiente angolare! :)

Sei un nuovo arrivato?
Leggi il regolamento del forum e presentati qui

My photo portfolio (now on G+!)
Torna all'inizio della Pagina

MB
Nuovo Arrivato



58 Messaggi

Inserito il - 31 dicembre 2010 : 11:47:50  Mostra Profilo  Visita l'Homepage di MB Invia a MB un Messaggio Privato  Rispondi Quotando
eh si anche, io avevo pensato di vedere se il punto con x massima ha la y più grande o più piccola del punto con la x minima. Ma c'ho proprio pensato 2 secondi.
Torna all'inizio della Pagina
  Discussione  

Quanto è utile/interessante questa discussione:

 Nuova Discussione  Nuovo Sondaggio Nuovo Sondaggio
 Rispondi Aggiungi ai Preferiti Aggiungi ai Preferiti
Cerca nelle discussioni
Vai a:
MolecularLab.it © 2003-18 MolecularLab.it Torna all'inizio della Pagina