高い減衰値で負になるy値に指数関数的減衰関数を適合させようとしていますが、nls
関数を正しく構成できません。
目的
減衰関数の傾きに興味があります(いくつかの情報源によると)。この勾配をどのように取得するかは重要ではありませんが、モデルはできる限りデータに適合している必要があります(つまり、適合が良好であれば、問題の線形化は許容可能です。「線形化」を参照してください)。しかし、このトピックに関するこれまでの研究では、次の指数関数的減衰関数を使用しています(Stedmon et al。によるクローズドアクセスの記事、方程式3)。
ここS
で、私が関心を持っている勾配は、K
負の値とa
初期値x
(つまり切片)を許可するための補正係数です。
私はこれをRで行う必要があります。発色団溶存有機物 (CDOM)の生の測定値を研究者が興味のある値に変換する関数を書いているからです。
データの例
データの性質上、PasteBinを使用する必要がありました。例えば、データはこちらから入手できます。
書くdt <-
とあなたのRコンソールにコードFOMペーストビンをコピーします。すなわち
dt <- structure(list(x = ...
データは次のようになります。
library(ggplot2)
ggplot(dt, aes(x = x, y = y)) + geom_point()
場合、負のy値が発生します。
を使用して解決策を見つけようとしています nls
を使用nls
して最初に試行すると、特異性が生じます。これは、パラメータの開始値を目で確認しただけであっても、驚くことではありません。
nls(y ~ a * exp(-S * x) + K, data = dt, start = list(a = 0.5, S = 0.1, K = -0.1))
# Error in nlsModel(formula, mf, start, wts) :
# singular gradient matrix at initial parameter estimates
この答えに従って、nls
関数を助けるために、より適切な開始パラメータを作成することができます。
K0 <- min(dt$y)/2
mod0 <- lm(log(y - K0) ~ x, data = dt) # produces NaNs due to the negative values
start <- list(a = exp(coef(mod0)[1]), S = coef(mod0)[2], K = K0)
nls(y ~ a * exp(-S * x) + K, data = dt, start = start)
# Error in nls(y ~ a * exp(-S * x) + K, data = dt, start = start) :
# number of iterations exceeded maximum of 50
関数は、デフォルトの反復回数では解を見つけることができないようです。反復回数を増やしましょう:
nls(y ~ a * exp(-S * x) + K, data = dt, start = start, nls.control(maxiter = 1000))
# Error in nls(y ~ a * exp(-S * x) + K, data = dt, start = start, nls.control(maxiter = 1000)) :
# step factor 0.000488281 reduced below 'minFactor' of 0.000976562
その他のエラー。それをチャック!関数に強制的に解を与えましょう:
mod <- nls(y ~ a * exp(-S * x) + K, data = dt, start = start, nls.control(maxiter = 1000, warnOnly = TRUE))
mod.dat <- data.frame(x = dt$x, y = predict(mod, list(wavelength = dt$x)))
ggplot(dt, aes(x = x, y = y)) + geom_point() +
geom_line(data = mod.dat, aes(x = x, y = y), color = "red")
まあ、これは間違いなく良い解決策ではありませんでした...
問題の線形化
多くの人が成功し、その指数関数的減衰関数を線形化してきた(ソース:1、2、3)。この場合、yの値が負または0でないことを確認する必要があります。コンピューターの浮動小数点の制限内で、 yの最小値をできるだけ0に近づけましょう。
K <- abs(min(dt$y))
dt$y <- dt$y + K*(1+10^-15)
fit <- lm(log(y) ~ x, data=dt)
ggplot(dt, aes(x = x, y = y)) + geom_point() +
geom_line(aes(x=x, y=exp(fit$fitted.values)), color = "red")
はるかに良いですが、モデルは低いx値で完全にy値をトレースしません。
nls
関数は依然として指数関数的減衰に適合できないことに注意してください。
K0 <- min(dt$y)/2
mod0 <- lm(log(y - K0) ~ x, data = dt) # produces NaNs due to the negative values
start <- list(a = exp(coef(mod0)[1]), S = coef(mod0)[2], K = K0)
nls(y ~ a * exp(-S * x) + K, data = dt, start = start)
# Error in nlsModel(formula, mf, start, wts) :
# singular gradient matrix at initial parameter estimates
負の値は重要ですか?
吸収係数が負になることはできないため、負の値は明らかに測定誤差です。では、yの値を寛大に正にするとどうなるでしょうか。気になるスロープです。追加してもスロープに影響がなければ、解決するはずです。
dt$y <- dt$y + 0.1
fit <- lm(log(y) ~ x, data=dt)
ggplot(dt, aes(x = x, y = y)) + geom_point() + geom_line(aes(x=x, y=exp(fit$fitted.values)), color = "red")
まあ、これはうまくいきませんでした...高いx値は明らかに可能な限りゼロに近いはずです。
質問
私は明らかにここで何か間違ったことをしています。Rを使用して負のy値を持つデータに適合された指数関数減衰関数の勾配を推定する最も正確な方法は何ですか?
nls
開始値を使用して私のために収束しました。または、自動開始機能を使用することもできます。それも私にとって収束します。nls(y~SSasymp(x, Asym, r0, lrc), data = dt)