2014-10-31 56 views
3

對於這個數據集:

dat = structure(list(x = c(5L, 5L, 5L, 5L, 10L, 10L, 10L, 10L, 15L, 
15L, 15L, 15L, 17L, 17L, 17L, 17L, 20L, 20L, 20L, 20L, 20L, 20L, 
20L, 20L, 22L, 22L, 22L, 22L, 24L, 24L, 24L, 24L, 25L, 25L, 25L, 
25L, 27L, 27L, 27L, 27L, 30L, 30L, 30L, 30L, 35L, 35L, 35L, 35L), 
y = c(2.2, 2.2, 1.95, 1.9, 4.1, 3.95, 3.75, 3.4, 5.15, 4.6, 
4.75, 5.15, 3.7, 4.1, 3.9, 3.5, 7, 6.7, 6.7, 6.95, 4.95, 6, 6.45, 
6.4, 7, 4.45, 6.15, 6.4, 7, 6.6, 6.7, 7, 4.5, 4.7, 5.75, 4.35, 
5.4, 5.15, 5.7, 5.7, 0, 0, 0.5, 0, 0, 0, 0, 0)), .Names = c("x", "y"), 
row.names = c(6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 
15L, 16L, 17L, 34L, 35L, 36L, 37L, 18L, 19L, 20L, 21L, 38L, 39L, 
40L, 41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 22L, 23L, 24L, 
25L, 50L, 51L, 52L, 53L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L), 
class = "data.frame") 

其中 「x」 是溫度和 「y」 是一個生物過程NLS - 會聚誤差

我想要的響應變量適合這種功能

beta.reg<-function(x, Yopt,Tmin,Topt,Tmax, b1) { 
Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x)/(Tmax-Topt))^b1 
} 

mod <- nls(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat, 
     start=c(Yopt=6, Tmin=0.1, Topt=24, Tmax=30, b1=1), 
     control=nls.control(maxiter=800)) 

不過,我在此消息的錯誤:

Error en numericDeriv(form[[3L]], names(ind), env) : Missing value or an infinity produced when evaluating the model

我試過同樣的功能與其他類似的數據集,並正確地配合......

rnorm<-(10) 
y <- c(20,60,70,49,10) 
rnorm<-(10) 
y <- c(20,60,70,49,10) 
dat<-data.frame(x = rep(c(15,20,25,30,35), times=5), 
       rep = as.factor(rep(1:5, each=5)), 
       y = c(y+rnorm(5), y+rnorm(5),y+rnorm(5),y+rnorm(5),y+rnorm(5))) 

有人能幫助我嗎?

會議信息:

R version 3.1.1 (2014-07-10) 
Platform: x86_64-pc-linux-gnu (64-bit) 

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] nlme_3.1-118  latticeExtra_0.6-26 RColorBrewer_1.0-5 lattice_0.20-29  

loaded via a namespace (and not attached): 
[1] grid_3.1.1 tools_3.1.1 
+0

這是在R嗎?如果是這樣,那麼你應該添加[tag:R]標籤。 – 2014-11-01 00:35:29

回答

4

這裏有這麼多的問題,我懷疑它能夠充分地在SO後覆蓋,但這應該讓你開始。

首先,它看起來像你想Tmax < max(dat$x),例如,< 35.這會導致一個問題,因爲那麼Tmax - x < 0x一些值,當你試着去養一個負數的功率(在公式的第二項),你會得到NA的。這是錯誤信息的原因。

其次,非線性模型的收斂依賴於模型公式,也是數據,從而使過程與一組數據的收斂而不是另一個是完全不相關的事實。

第三,非線性建模平方殘差之和最小化迭代作爲參數的函數。如果RSS表面有本地最小值,並且您的start接近1,則算法會找到它。但只有全球最低是真正的解決方案。你的問題有很多很多局部最小值。

四,nls(...)默認使用高斯牛頓方法。高斯牛頓以移位參數(參數被添加到預測變量或從預測變量中減去而出名)是不穩定的,因此在你的情況下爲TminTmax。幸運的是,minpak.lm包實現了Levenberg Marquardt方法,該方法在這些條件下更加穩定。該包中的nlsLM(...)函數使用與nls(...)相同的調用順序,並返回nls類型的對象,因此該類對象的所有方法也可以正常工作。使用它。

第五,在非線性迴歸一個基本的假設(事實上所有最小二乘迴歸)是殘差是正態分佈的。所以你必須使用Q-Q圖驗證任何解決方案。

第六,你的模型有一個反常的特徵。當Tmin -> -Inf模型中的第一項接近1。事實證明,這會產生比任何其他小於min(dat$x)的值更低的RSS,因此算法都傾向於將Tmin驅動爲較大的負值。你可以很容易地看到如下:

library(minpack.lm) 
mod <- nlsLM(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat, 
      start=c(Yopt=6,Tmin=0,Topt=24,Tmax=50, b1=1), 
      control=nls.lm.control(maxiter=1024,maxfev=1024)) 
coef(summary(mod)) 
#   Estimate Std. Error  t value  Pr(>|t|) 
# Yopt 6.347019 0.2919686 21.73870235 8.055342e-25 
# Tmin -155.530098 2204.0011003 -0.07056716 9.440694e-01 
# Topt 21.157545 0.6702713 31.56564484 2.240134e-31 
# Tmax 35.000000 11.4838614 3.04775537 3.933164e-03 
# b1  3.321326 9.1844548 0.36162468 7.194035e-01 
sum(residuals(mod)^2) 
# [1] 50.24696 

par(mfrow=c(1,2)) 
plot(y~x,dat) 
with(as.list(coef(mod)),curve(beta.reg(x, Yopt,Tmin,Topt,Tmax, b1),add=TRUE)) 
qqnorm(residuals(mod)) 

這看起來像一個相當不錯的配合但它不是:在QQ圖表明殘差不正常的遠程。 Tminb1的估計值很差,而Tmin的值在物理上沒有意義,這是數據問題,而不是合適的。

第七,事實證明,上面的適合實際上是一個本地最低。我們可以通過在Tmin,Tmaxb1(省略YoptTopt以節省時間,並且因爲這些參數很好地估計而不考慮起點)來進行網格搜索來看到這一點。

init <- c(Yopt=6, Topt=24) 
grid <- expand.grid(Tmin= seq(0,4,len=100), 
        Tmax= seq(35,100,len=10), 
        b1 = seq(1,10,len=10)) 
mod.lst <- apply(grid,1,function(gr){ 
    nlsLM(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat, 
     start=c(init,gr),control=nls.control(maxiter=800)) }) 
rss <- sapply(mod.lst,function(m)sum(residuals(m)^2)) 
mod <- mod.lst[[which.min(rss)]] # fit with lowest RSS 
coef(summary(mod)) 
#  Estimate Std. Error  t value  Pr(>|t|) 
# Yopt 6.389238 0.2534551 25.208557840 2.177168e-27 
# Topt 22.636505 0.5605621 40.381798589 7.918438e-36 
# Tmin 35.000002 104.6221159 0.334537316 7.396005e-01 
# Tmax 36.234602 133.4987344 0.271422809 7.873647e-01 
# b1 -41.512912 7552.0298633 -0.005496921 9.956395e-01 
sum(residuals(mod)^2) 
# [1] 34.24019 

plot(y~x,dat) 
with(as.list(coef(mod)),curve(beta.reg(x, Yopt,Tmin,Topt,Tmax, b1),add=TRUE)) 
qqnorm(residuals(mod)) 

數學上,這是一個明顯優於契合:RSS較低,殘差更接近正態分佈。同樣,參數估計不準確且物理意義不大的事實是數據(也可能是模型公式)的問題,而不是擬合過程。

以上所有情況都表明您的模型存在問題。在數學上,它的一個問題是該函數在(Tmin,Tmax)之外的x未定義。由於數據輸出爲x=35,所以擬合算法決不會產生Tmax < 35(如果它收斂)。處理這個問題的方法會稍微改變你的模型函數,在該範圍之外將其剪切爲0。 (我不知道這是否合法,基於你的問題的物理性質,儘管...)。

beta.reg<-function(x, Yopt,Tmin,Topt,Tmax, b1) { 
    ifelse(x>Tmax,0, 
    ifelse(x<Tmin,0, 
     Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x)/(Tmax-Topt))^b1 
)) 
} 

運行上述具有這種功能的產率的代碼:

coef(summary(mod)) 
#   Estimate Std. Error  t value  Pr(>|t|) 
# Yopt 6.1470413 0.21976766 27.970636 3.202940e-29 
# Tmin -52.8172658 184.16899439 -0.286787 7.756528e-01 
# Topt 23.0777898 0.63750721 36.200045 7.638121e-34 
# Tmax 30.0039413 0.02529877 1185.984187 1.038918e-98 
# b1  0.5966129 0.32439982 1.839128 7.280793e-02 

sum(residuals(mod)^2) 
# [1] 28.10144 

par(mfrow=c(1,2)) 
plot(y~x,dat) 
with(as.list(coef(mod)),curve(beta.reg(x, Yopt,Tmin,Topt,Tmax, b1),add=TRUE)) 
qqnorm(residuals(mod)) 
qqline(residuals(mod)) 

事實上網格搜索產率完全相同的結果獨立起點。請注意,RSS低於早期模型的任何結果,並且b1估計得更好(並且非常有效,與使用較早模型函數的估計不同)。殘差仍然不正常,但在這種情況下,我想檢查數據中的異常值。

+0

很棒@jlhoward!我也認爲數據集有許多問題,但它是生物學......我會考慮你的答覆的每一點:第一 - 顯然,如果我測試溫度> 30°C將有大約0的反應。我想過排除35°C點,具有'Tmax Juanchi 2014-11-03 18:57:56

+0

您的上一個模型似乎具有最好的生物學意義,而不考慮'Tmin'。我認爲,用這個模型和數據集來估計'Tmin'是很困難的。你認爲用x的一個子集 Juanchi 2014-11-03 19:08:32

+0

在我這樣做之前,我會看看'x〜17'的數據。這些重複有些奇怪:很難解釋爲什麼你的回答與'x〜10'相同,再加上這些點解釋了殘差中大多數正常偏差。你可以考慮排除這些重複和重新安裝。 – jlhoward 2014-11-03 19:41:28

1

向@jlhoward的另一個可能的解決方案添加...

我發現這個nls2包:

library("nls2") 

從原始數據集Exludying x~17,35

newdat <- subset(dat, x!=17 & x!=35) 

應用功能,以減少數據集:

beta.reg<-with(newdat, 
      y ~ Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x)/Tmax-Topt))^b1 
      ) 

創建一套首發:

st1 <- expand.grid(Yopt = seq(4, 8, len = 4), 
        Tmin = seq(0, 4, len = 4), 
        Topt = seq(15, 25, len = 4), 
        Tmax= seq(28, 38, len = 4), 
        b1 = seq(0, 4, len = 4)) 

擬合模型:

mod <- nls2(beta.reg, start = st1, algorithm = "brute-force") 

提取係數:

round(coef(summary(mod)),3) 

#  Estimate Std. Error t value Pr(>|t|) 
# Yopt 6.667  0.394 16.925 0.000 
# Tmin 0.000  12.023 0.000 1.000 
# Topt 21.667  0.746 29.032 0.000 
# Tmax 31.333  1.924 16.289 0.000 
# b1  1.333  1.010 1.320 0.197 

診斷:

sum(residuals(mod)^2) 

# [1] 50.18246 

最後,調整後的功能和QQ正常的情節:

par(mfrow=c(1,2)) 
with(newdat,plot(y~x,xlim=c(0,35))) 
points(fitted(mod)~I(newdat$x), pch=19) 
with(as.list(coef(mod)), 
curve(
    Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x)/(Tmax-Topt))^b1, 
    add=TRUE, col="red")) 

qqnorm(residuals(mod)) 
qqline(residuals(mod)) 

+0

對於記錄,'nls2(...)'(正如您使用的那樣)不會最小化RSS,它將在每個4^5 = 1024個網格點計算RSS並報告具有最低RSS的點。這就是爲什麼你得到'Tmin = 0'; 'Tmin'值越低,RSS值越低,但這是網格中最低的值。 – jlhoward 2014-11-04 16:30:45

+0

這是真的。通過這種方式,我試圖將「Tmin」的估計限制在某種生物學意義上,犧牲了RSS。這是否與您上一個型號的限制相同? 'beta.reg <-function(x,Yopt,Tmin,Topt,Tmax,b1)ifelse(x> Tmax,0, ifelse(x Juanchi 2014-11-04 17:28:20

+0

不。上面的模型僅限制函數在'x'超出'(Tmin,Tmax)'範圍時返回0。它根本不會限制'Tmin'或'Tmax'。你所做的是給定所選參數空間,找到最小RSS(或多或少,這是一個非常粗糙的網格)。這在RSS意義上是「最合適的」,但是當你這樣做時,你應該知道fit的統計數據(參數的se值等)是完全沒有意義的。 – jlhoward 2014-11-04 20:44:57