为何自定义ROC曲线建模时出现NaN警告与初始参数评估错误?
ROC曲线建模优化:NaN警告与初始参数评估失败解决
我尝试用自定义函数对ROC曲线建模,目标是估计8个参数以最小化sse_total,但一直遇到两个问题:
- 运行时出现NaN警告
- 函数无法在初始参数处评估的错误
其中X是非累积虚警率,Y是非累积命中率(仅用于模型估计)。试过调整初始参数、修改函数配置,也查过同类问题的解决方案,但都没解决。原代码如下:
X<-c(0.01666667, 0.00000000, 0.06666667, 0.11666667, 0.36666667, 0.43333333) Y<-c(0.03333333, 0.05000000, 0.06666667, 0.05000000, 0.10000000, 0.70000000) df_dpsd<-data.frame(x=X,y=Y) DPSD_1<-function(par){ R<-par[1] Rn<-par[2] dprime<-par[3] c6<-par[4] c5<-par[5] c4<-par[6] c3<-par[7] c2<-par[8] # c1<-par[9] pred_FAR6<-((1-Rn)*qnorm(c6,0,1)) pred_FAR5<-((1-Rn)*(qnorm(c5,0,1)-qnorm(c6,0,1))) pred_FAR4<-((1-Rn)*(qnorm(c4,0,1)-qnorm(c5,0,1))) pred_FAR3<-((1-Rn)*(qnorm(c3,0,1)-qnorm(c4,0,1))) pred_FAR2<-((1-Rn)*(qnorm(c2,0,1)-qnorm(c3,0,1))) pred_FAR1<-(Rn+(1-Rn)*(1-qnorm(c2,0,1))) pred_HR6<-(R+(1-R)*qnorm(c6,-dprime,1)) pred_HR5<-((1-R)*(qnorm(c5,-dprime,1)-qnorm(c6,-dprime,1))) pred_HR4<-((1-R)*(qnorm(c4,-dprime,1)-qnorm(c5,-dprime,1))) pred_HR3<-((1-R)*(qnorm(c3,-dprime,1)-qnorm(c4,-dprime,1))) pred_HR2<-((1-R)*(qnorm(c2,-dprime,1)-qnorm(c3,-dprime,1))) pred_HR1<-((1-R)*(1-qnorm(c2,-dprime,1))) # SSE sseH6<-(Y[1]-pred_HR6)^2 sseH5<-(Y[2]-pred_HR5)^2 sseH4<-(Y[3]-pred_HR4)^2 sseH3<-(Y[4]-pred_HR3)^2 sseH2<-(Y[5]-pred_HR2)^2 sseH1<-(Y[6]-pred_HR1)^2 sseF6<-(X[1]-pred_FAR6)^2 sseF5<-(X[2]-pred_FAR5)^2 sseF4<-(X[3]-pred_FAR4)^2 sseF3<-(X[4]-pred_FAR3)^2 sseF2<-(X[5]-pred_FAR2)^2 sseF1<-(X[6]-pred_FAR1)^2 sse_total<-( # sseH1+ sseH2+sseH3+sseH4+sseH5+sseH6+ # sseF1+ sseF2+sseF3+sseF4+sseF5+sseF6) return(sse_total) } (result <-optim(par=c(R=.25,Rn=.25,dprime=1,c6=-1.5,c5=-1,c4=-.5,c3=1,c2=1.5), fn=DPSD_1))
问题根源
qnorm()参数错误:qnorm的第一个参数是分位数(概率值),必须在(0,1)区间内,但原代码中c6、c5等初始参数为-1.5、-1这类小于0的值,直接传入会返回NaN,导致计算中断。- 无参数约束:优化过程中参数可能超出合理范围(比如R、Rn应在0-1之间,c系列参数应为0-1的分位数),进一步引发无效计算。
修复方案
- 调整c系列参数的初始值为0-1之间的合理分位数
- 使用
optim的L-BFGS-B方法添加参数上下界约束,确保所有参数在有效范围内 - 避免
qnorm传入0或1这类极端值(用0.001和0.999代替)
修复后的代码:
X<-c(0.01666667, 0.00000000, 0.06666667, 0.11666667, 0.36666667, 0.43333333) Y<-c(0.03333333, 0.05000000, 0.06666667, 0.05000000, 0.10000000, 0.70000000) df_dpsd<-data.frame(x=X,y=Y) DPSD_1<-function(par){ R<-par[1] Rn<-par[2] dprime<-par[3] c6<-par[4] c5<-par[5] c4<-par[6] c3<-par[7] c2<-par[8] # 计算预测值,确保c系列为0-1的分位数 pred_FAR6<-((1-Rn)*qnorm(c6, 0, 1)) pred_FAR5<-((1-Rn)*(qnorm(c5, 0, 1)-qnorm(c6, 0, 1))) pred_FAR4<-((1-Rn)*(qnorm(c4, 0, 1)-qnorm(c5, 0, 1))) pred_FAR3<-((1-Rn)*(qnorm(c3, 0, 1)-qnorm(c4, 0, 1))) pred_FAR2<-((1-Rn)*(qnorm(c2, 0, 1)-qnorm(c3, 0, 1))) pred_FAR1<-(Rn+(1-Rn)*(1-qnorm(c2, 0, 1))) pred_HR6<-(R+(1-R)*qnorm(c6, -dprime, 1)) pred_HR5<-((1-R)*(qnorm(c5, -dprime, 1)-qnorm(c6, -dprime, 1))) pred_HR4<-((1-R)*(qnorm(c4, -dprime, 1)-qnorm(c5, -dprime, 1))) pred_HR3<-((1-R)*(qnorm(c3, -dprime, 1)-qnorm(c4, -dprime, 1))) pred_HR2<-((1-R)*(qnorm(c2, -dprime, 1)-qnorm(c3, -dprime, 1))) pred_HR1<-((1-R)*(1-qnorm(c2, -dprime, 1))) # 计算SSE sseH6<-(Y[1]-pred_HR6)^2 sseH5<-(Y[2]-pred_HR5)^2 sseH4<-(Y[3]-pred_HR4)^2 sseH3<-(Y[4]-pred_HR3)^2 sseH2<-(Y[5]-pred_HR2)^2 sseH1<-(Y[6]-pred_HR1)^2 sseF6<-(X[1]-pred_FAR6)^2 sseF5<-(X[2]-pred_FAR5)^2 sseF4<-(X[3]-pred_FAR4)^2 sseF3<-(X[4]-pred_FAR3)^2 sseF2<-(X[5]-pred_FAR2)^2 sseF1<-(X[6]-pred_FAR1)^2 sse_total <- sseH2+sseH3+sseH4+sseH5+sseH6 + sseF2+sseF3+sseF4+sseF5+sseF6 return(sse_total) } # 带约束的优化:设置参数上下界,使用L-BFGS-B方法 result <- optim( par = c(R=0.25, Rn=0.25, dprime=1, c6=0.05, c5=0.1, c4=0.2, c3=0.8, c2=0.9), fn = DPSD_1, method = "L-BFGS-B", lower = c(R=0, Rn=0, dprime=0, c6=0.001, c5=0.001, c4=0.001, c3=0.001, c2=0.001), upper = c(R=1, Rn=1, dprime=10, c6=0.999, c5=0.999, c4=0.999, c3=0.999, c2=0.999) ) print(result)
修复说明
- c系列初始参数调整为0-1区间内的分位数,对应ROC曲线的不同阈值点
- 参数约束确保:
- R、Rn始终为0-1的概率值
- dprime限制在0到10(符合信号检测理论中d'的常见范围)
- c6-c2避免极端值0或1,防止
qnorm返回无穷大
- 使用
L-BFGS-B方法支持带上下界的优化,避免参数越界引发的计算错误
内容的提问来源于stack exchange,提问作者Caleb Picker
相关产品推荐
相关产品推荐

