Подгонка данных с помощью нескольких функций

#r #curve-fitting #nls

#r #подгонка кривой #nls

Вопрос:

Я пытаюсь подогнать свои данные с помощью нескольких функций подгонки, состоящих из нескольких переменных. Ниже приведен пример для двух переменных. Бывают случаи, когда для определенной переменной подгонка не является хорошей, и я получаю ошибку сингулярного градиента. Я хотел бы проигнорировать эти случаи и продолжить в любом случае, и, кроме того, для остальных переменных выберите лучшее решение между двумя функциями подгонки, сравнив отклонение. Как и в этом примере, как для type1, так и для type2 сумма остатков меньше с первой функцией sum(resid(myfitfun1)^2) < sum(resid(myfitfun2)^2) , поэтому возьмите первую функцию для обеих переменных.

 myfun1<-function(x,a,b){1/(1 exp(-(x/a) b))}
myfun2<-function(x,a,b){1 b*exp(-(x)/a)} 
   
mydata <- data.frame(v=c("type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1",
"type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1",
 "type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1","type1",
 "type1","type1","type1","type1","type1","type1","type1","type1","type2","type2","type2","type2",
                     "type2","type2"), 
 m=c(1.116975672,1.38641493,1.423833959,1.482008121,1.513588607,1.527179033,
                     1.543512539,1.555874185,1.607579807,1.721182154,1.729059048,1.748226681,
                     1.774814055,1.815147988,1.835638421,1.854582642,1.861972,1.887704144,
                     1.915360975,1.948689331,1.97516491,1.985962227,2.011310496,2.043716548,
                     2.068918438,2.091184665,2.120366813,2.126865141,2.148241318,2.15871161,
                     2.193529738,2.256197915,2.302364722,2.316381935,2.31909683,2.325213451,
                     2.336299128,2.410419652,2.473160411,2.478302702,2.5238233,2.651124474,
                     2.70470831,2.927536062,-0.1736072,0.1235610,0.5848941,0.9016486,0.9744832,
                     1.2767238), 
 n=c(0.022727273,0.045454545,0.068181818,0.090909091,0.113636364,0.136363636,
                     0.159090909,0.181818182,0.204545455,0.227272727,0.25,0.272727273,0.295454545,
                     0.318181818,0.340909091,0.363636364,0.386363636,0.409090909,0.431818182,
                     0.454545455,0.477272727,0.5,0.522727273,0.545454545,0.568181818,0.590909091,
                     0.613636364,0.636363636,0.659090909,0.681818182,0.704545455,0.727272727,0.75,
                     0.772727273,0.795454545,0.818181818,0.840909091,0.863636364,0.886363636,
                     0.909090909,0.931818182,0.954545455,0.977272727,1,0.1666667,0.3333333,0.5000000,
                     0.6666667,0.8333333,1))
myfitfun1 <- nls(n~myfun1(m,a,b),mydata,start=list(a=1,b=1))
myfitfun2 <- nls(n~myfun2(m,a,b),mydata,start=list(a=1,b=1))
  

Я хотел бы запрограммировать его таким образом, чтобы он автоматически выполнял лучшую подгонку между двумя функциями для различных type и игнорировал в случае ошибки. Любая помощь приветствуется.

Ответ №1:

Вы могли бы поместить обе функции в функцию и работать с tryCatch . В первых tryCatch случаях просто бросьте NA , чтобы устранить ошибку. В другом tryCatch задайте значение Inf при возникновении ошибки, чтобы обеспечить «лучшую» подгонку для безотказной функции. В обычных случаях выбирается минимум. С `attr<-` мы можем присвоить MSE в качестве атрибута для вывода подгонки.

 fun <- function(data) {
  myfitfun1 <- tryCatch(
    nls(n ~ myfun1(m, a, b), data, start=list(a=1, b=1)),
    error=function(e) NA)
  myfitfun2 <- tryCatch(
    nls(n ~ myfun2(m, a, b), data, start=list(a=1, b=1)),
    error=function(e) NA)
  L <- list(myfitfun1, myfitfun2)
  res <- sapply(L, function(x) {
    tryCatch(sum(resid(x)^2), error=function(e) Inf)
    })
  `attr<-`(L[[which.min(res)]], "MSE", min(res))
}

fun(mydata)
# Nonlinear regression model
# model: n ~ myfun1(m, a, b)
# data: data
# a      b 
# 0.3465 5.6461 
# residual sum-of-squares: 2.323
# 
# Number of iterations to convergence: 26 
# Achieved convergence tolerance: 7.675e-06
  

Чтобы получить MSE атрибут, используйте:

 attr(fun(mydata), "MSE")
# [1] 2.322945
  

Комментарии:

1. Я настоятельно рекомендую привести a,b,m,n аргументы в ваш fun . В противном случае могут произойти неожиданные «захваты» неправильных наборов данных.

2. @CarlWitthoft Конечно, это точка, data аргумента должно быть достаточно, верно? Однако цель вопроса и, следовательно, моего ответа состояла в том, чтобы дать OP представление о том, как справляться с этими случаями ошибок, и на самом деле это не было предназначено для того, чтобы быть полностью рабочим решением для поглощения.

3. Достаточно справедливо 🙂