2012-02-04 13 views
5

Rozważmy nieliniową najmniejszych modelu kwadratów na badania, na przykład w następującej postaci)Wypusty wewnątrz nieliniowej najmniejszych kwadratów R

y ~ theta/(1 + exp(-(alpha + beta * x))) 

(my problemem jest kilka zmiennych, a funkcja zewnętrzna jest logistyczne ale nieco bardziej zaangażowany, ten jest prostszy, ale myślę, że jeśli mogę to zrobić, mój przypadek powinien podążać prawie natychmiast)

Chciałbym zastąpić termin "alpha + beta * x" (naturalny) sześciennym splajnem .

Oto niektóre kodu do tworzenia przykładowe dane z nieliniowej funkcji wewnątrz logistyczne:

set.seed(438572L) 
x <- seq(1,10,by=.25) 
y <- 8.6/(1+exp(-(-3+x/4.4+sqrt(x*1.1)*(1.-sin(1.+x/2.9))))) + rnorm(x, s=0.2) 

Bez potrzeby logistyki wokół niego, gdybym był w LM, mógłbym wymienić liniową termin z spline termin łatwo; więc model liniowy coś takiego:

lm(y ~ x) 

staje

library("splines") 
lm(y ~ ns(x, df = 5)) 

generowania wartości wykonana jest prosty i coraz przewidywane wartości za pomocą (dla przykład) opakowanie skuteczna wydaje się dość prosta.

Rzeczywiście, dopasowanie oryginalnych danych z dopasowaniem spline na podstawie Lm nie jest złe, ale jest powód, dla którego potrzebuję go wewnątrz funkcji logistycznej (lub raczej odpowiednika w moim problemie).

Problem z NFS polega na tym, że muszę podać nazwy dla wszystkich parametrów (jestem całkiem zadowolony z tego, że je nazywam (b1, ..., b5) dla jednego dopasowania splajnu (i powiedzmy c1, ..., c6 dla innej zmiennej - potrzebuję być w stanie zrobić kilka z nich)

Czy istnieje rozsądny sposób na wygenerowanie odpowiedniej formuły dla nls, dzięki czemu mogę zamienić liniowy termin wewnątrz funkcji nieliniowej na splajnu?

Jedyne sposoby mogę postać, która nie może być to zrobić to trochę niezręczne i niezgrabne i nie ładnie uogólniać bez pisania całą masę kodu.

(edit for clarification) Dla tego małego problemu, mogę to zrobić ręcznie - napisać wyrażenie dla wewnętrznego produktu każdej zmiennej w macierzy wygenerowanej przez ns, razy wektor parametrów. Ale potem muszę napisać całą rzecz po kolei dla każdego splajnu w każdej innej zmiennej, i znowu za każdym razem, gdy zmieniam df w dowolnym splajnie, i znowu, jeśli chcę użyć cs zamiast ns. A potem, kiedy chcę spróbować zrobić jakąś prognozę (/ interpolację), otrzymujemy całą masę nowych problemów do rozwiązania. Muszę ciągle to robić, w kółko i potencjalnie dla znacznie większej liczby węzłów i kilku zmiennych, do analizy po analizie - i zastanawiałem się, czy istnieje bardziej schludny, prosty sposób niż wypisywanie każdego pojedynczego terminu, bez konieczności pisania dużej ilości kodu. Widzę dość bystry sposób na zrobienie tego, który wymagał by sporo kodu, aby uzyskać prawo, ale będąc R, podejrzewam, że jest dużo lepszy sposób (lub bardziej prawdopodobny 3 lub 4 lepsze sposoby), to jest po prostu umykając mi. Stąd pytanie.

Myślałem, że widziałem kogoś, kto zrobił coś takiego w przeszłości w całkiem przyjemny sposób, , ale za moje życie nie mogę go teraz znaleźć; Próbowałem kilka razy, aby go zlokalizować.

[Bardziej szczegółowo, chciałabym móc spróbować dopasować dowolną z kilku różnych splajnów w każdej zmiennej - aby wypróbować kilka możliwości - aby sprawdzić, czy mogę znaleźć prosty model, ale wciąż taki, w którym dopasowanie jest adekwatne do celu (hałas jest naprawdę niski, niektóre odchylenia w dopasowaniu są w porządku, aby osiągnąć ładny gładki wynik, ale tylko do pewnego punktu). To bardziej "znaleźć fajną, możliwą do interpretacji, ale odpowiednią funkcję dopasowywania", niż cokolwiek innego, co by wnioskowało o wnioskach i eksploracji danych, tak naprawdę nie jest problemem dla tego problemu.]

Alternatywnie, jeśli byłoby to znacznie łatwiejsze w powiedzeniu gnm lub ASSIST lub jeden z innych pakietów, który byłby użyteczną wiedzą, ale pomocne byłyby wskazówki dotyczące tego, jak postępować z powyższym problemem z zabawkami.

Odpowiedz

9

ns faktycznie generuje macierz predyktorów. Możesz podzielić tę macierz na poszczególne zmienne i przekazać je do nls.

m <- ns(x, df=5) 
df <- data.frame(y, m) # X-variables will be named X1, ... X5 
# starting values should be set as appropriate for your data 
nls(y ~ theta * plogis(alpha + b1*X1 + b2*X2 + b3*X3 + b4*X4 + b5*X5), data=df, 
     start=list(theta=1, alpha=0, b1=1, b2=1, b3=1, b4=1, b5=1)) 

ETA: o to w automatyzacji tego dla różnych wartości df. Konstruuje to formułę za pomocą mimowania tekstu, a następnie używa do.call do wywoływania nls. Zastrzeżenie: nietestowane.

my.nls <- function(x, y, df) 
{ 
    m <- ns(x, df=df) 
    xn <- colnames(m) 
    b <- paste("b", seq_along(xn), sep="") 
    fm <- formula(paste("y ~ theta * plogis(1 + alpha + ", paste(b, xn, sep="*", 
      collapse=" + "), ")", sep="")) 
    start <- c(1, 1, rep(1, length=length(b))) 
    names(start) <- c("theta", "alpha", b) 
    do.call(nls, list(fm, data=data.frame(y, m), start=start)) 
} 
+0

@Glen_b: Ok, edytowałem swoją odpowiedź; zobacz, czy to pomaga. –

2

realizacja Przyszedłem natomiast wyjaśnienie moje własne pytanie mnie zobaczyć, że tam jest mniej przylegający sposób niż widziałem wcześniej.

Nawet przy odrobinie oczywistego usprawnienia, które może wejść, jest to nadal nieco nieeleganckie w stosunku do mojego oka, ale co najmniej znośne wystarczające do wielokrotnego użycia, więc uważam to za odpowiednią odpowiedź. Jestem nadal zainteresowany w lepszy sposób niż ten poniżej.

Sztuczka Hong Ooi polegająca na użyciu data.frame na macierzy wygenerowanej przez ns do automatycznego nazwania kolumn jest trochę urocza i użyłem jej poniżej. Najprawdopodobniej użyję pasty, aby je ogólnie zbudować, ponieważ mam kilka zmiennych do zabawy.

Zakładając danych konfigurację podaną w pytaniu -

lin.expr <- function(p,xn) { 
    pn<-paste(p, 1:length(xn), sep = "") 
    paste(paste(pn,xn,sep=" * "),collapse=" + ") 
    } 


m <- ns(x, df=3) 
mydf <- data.frame(y, m) # X-variables will be named X1, X2, ... 
xn <- names(mydf)[2:dim(mydf)[2]] 

nspb <- lin.expr("b",xn) 

c.form <- paste("y ~ theta * plogis(a + ",nspb,")",sep="") 
stl <- list(theta=2, a=-5,b1=10, b2=10, b3=10) 
nls(c.form, data=mydf, start= stl) 

Mój rzeczywisty wzór będzie miał kilka terminów takich jak nspb. Uznano istotne usprawnienia; Wolałbym nie wybierać własnej odpowiedzi, ale myślę, że ją wybiorę, jeśli za dzień lub dwa nie będzie nic więcej.

edytuj: dodatek Hong Ooi (który został opublikowany, gdy wpisywaliśmy moje i używam podobnych pomysłów, ale dodałem kilka miłych dodatków) prawie to robi; jest to akceptowalna odpowiedź, więc ją sprawdziłem.

Powiązane problemy