尝试通过数据拟合nls模型时,出现“奇异梯度”或“低于minFactor的阶跃因子”错误

时间:2019-04-14 08:44:09

标签: r function predict nls

在实验室中,我们测量了具有10 kOhm电阻和10nF电容器的低通滤波器的频率,输入和输出信号的两倍振幅以及输入和输出信号之间的时间差。从那里我们计算出相位差。
我现在计算了电压传递函数(G.exp)的实验值,并希望通过我的数据点拟合非线性模型,以优化我的参数。
一切正常,直到我调用函数:

fit <- nls(G.exp ~ a*Vierpol(w.exp, C), 
    trace=TRUE, start=list(a=1, C=100e-9))

首先,我尝试通过设置step factor below minFactor来增加minFactor以解决control=nls.control(minFactor=1/8192)的问题,但这导致步长和minFactor减小。
然后,我尝试更改a和C的起始值,这导致出现错误消息singular gradient

#ELK - Lowpass Filter

rm(list=ls())
setwd("C:/working/dir/ELK")

######################### Values 
#Read frequency, Double Amplitude from incoming signal and outcoming signal, measured time difference and calculated phase
#from a constructed lowpass filter with 10k Ohm resistor and 10 nF capacitor
#from a csv file
freq <- read.csv("Filters.csv", sep= ";", skip = 0)[,c(1)]#frequency in kHz

AmpUa <- read.csv("Filters.csv", sep= ";", skip = 0)[,c(3)] #2*Amplitude in Volt

AmpUe <- read.csv("Filters.csv", sep= ";", skip = 0)[,c(2)] #2*Amplitude in Volt

phase <- read.csv("Filters.csv", sep= ";", skip = 0)[,c(5)] #Phase (without unit)

time <- read.csv("Filters.csv", sep= ";", skip = 0)[,c(4)] #Time difference of signals in ms



Log <- function(begin=1e-10, end=1e10) {
  d <- 10^c(-99:99)
  d <- d[d>=begin & d<=end]
  dd <- outer(c(1:9), 10^c(-99:99))
  dd <- dd[dd>=begin & dd<=end]
  dlab <- do.call("expression",
                  lapply(seq(along=log10(d)),function(i) substitute(10^E,list(E=log10(d)[i]))))
  list("big"=d, "small"=dd, "big.lab"=dlab)
}

lg <- Log()

######################### Amplitude
#function Vierpol gives back the theoretical value of the Voltage transfer function
Vierpol <- function(w, C) {     # Lowpass
  ZC <- (0+1i)/(-w*C)
  ZR <- 10000
  Ztot <- ZR+ZC
  Gk <- ZR/Ztot
  abs(Gk)
}


f <- freq * 1000 #transfer frequency from KHz to Hz
C <- 10e-9 #capacitor in Faraday
fg <- 1591  #Border frequence of the filter (calculated value)
x <- f/fg   #ratio btw fg and data (wwg)

ch1 <- AmpUe/2      #measured Amplitude
ch2 <- AmpUa/2      #measured

wexp <- 2*pi*f   #experimental angular frequency



Gexp <- ch2/ch1 #experimental value of the voltage transfer function


plot(f, Gexp, las=1, log = "x", xlim=c(10, 1e6), ylim=c(0, 1.1), xlab=expression(italic(f) ~ " [Hz]"), ylab=expression("|G("~italic(f)~")|"), axes=FALSE)

# fit to Gexp = a * Vierpol(wexp, R ,C)
#try to fit the experimental point through a non linear model and optimize the parameters a and C
fit<- nls(Gexp ~ a * Vierpol(wexp, C),                    
          trace=TRUE, start=list(a=1, C=10e-9))   

axis(1, at = lg$big, labels = lg$big.lab)
axis(1, at = lg$small, labels = FALSE, tcl = -0.25)
axis(2)
box()
#print(summary(fit))

fc <- 10^seq(1, 6, 0.01)                            # get the range 10Hz-> 1MHz
Gc <- predict(fit, list(wexp = 2*pi*fc))            # fit function for x
lines(fc, Gc)                                       # draw the line

points(f, Gexp, pch=21, bg="white")

我已经可以绘制实验数据点,但是无法通过这些数据点拟合任何模型。

如何通过实验点拟合nls模型?

错误消息以供参考:

 fit<- nls(Gexp ~ a * Vierpol(wexp, 500, C),                    
+           trace=TRUE, start=list(a=1, C=10e-9), control=nls.control(minFactor=1/1024))
16.19366 :  1e+00 1e-08
7.865624 :  -1.105361e-01  2.118218e-08
7.694877 :  -1.051039e-01 -1.234647e-08
7.564449 :  -1.046308e-01  5.939512e-09
7.511479 :  -1.034139e-01 -4.054490e-09
7.500272 :  -8.842691e-02  5.026213e-09
7.459853 :  -8.841959e-02 -3.283024e-09
7.447777 :  -7.526479e-02  3.808724e-09
7.399803 :  -7.384654e-02 -1.698359e-09
7.351996 :  -7.276184e-02  1.177592e-10
7.350372 :  -1.259269e-01  2.873937e-11
Error in nls(Gexp ~ a * Vierpol(wexp, 500, C), trace = TRUE, start = list(a = 1,  :   step factor reduced 0.000488281 below 'minFactor' 0.000976562



fit<- nls(Gexp ~ a * Vierpol(wexp, C),                    
+           trace=TRUE, start=list(a=9.570e-01, C=1.948e-07))
15.52989 :  9.570e-01 1.948e-07
4.054572 :  2.187341e-01 8.618412e-06
Error in nls(Gexp ~ a * Vierpol(wexp, C), trace = TRUE, start = list(a = 0.957,  :   singulärer Gradient


编辑:
我添加了我的模型的图像。我不明白添加runif来扩大错误范围有什么帮助。

fit<- nls(Gexp ~ a * Vierpol(wexp, C) + runif(Some_val),    
          trace=TRUE, start=list(a=1, C=10e-9))  

我为Some_val尝试了不同的值,如何确定错误范围?
无论如何,我又得到了:

  

nls(Gexp〜a * Vierpol(wexp,C)+ runif(7,8,9)中的错误,trace =   是的,:Schrittweitenfaktor 0.000488281 unter'minFactor'   0.000976562 reduziert另外:有50个或更多警告(使用warnings()查看前50个)

Image of model

0 个答案:

没有答案