R中高基函数数下B样条平滑报错问题求助
我来帮你拆解一下这个问题的原因和对应的解决思路:
问题根源分析
你遇到的两个问题是关联的:
警告信息:
Matrix of basis function values has rank 799 < dim(fdobj$basis)[2] = 800 ignoring null space
当你设置800个B样条基函数时,基函数矩阵出现了秩亏(存在线性相关的列)。这是因为默认的均匀节点设置下,过多的基函数会导致相邻基函数高度重叠,部分基函数可以被其他基函数线性表示,所以矩阵的实际秩比你设定的基函数数少1。正定矩阵错误:
Error in chol.default(temp) : the leading minor of order 445 is not positive definite
在无惩罚(j=0)的平滑中,算法需要对基函数交叉乘积矩阵做Cholesky分解,而秩亏的矩阵必然不是正定矩阵,因此分解失败报错。而当你添加惩罚项时,惩罚项相当于给这个秩亏矩阵加了一个正定的“正则化项”,让整体矩阵变得正定,所以能正常运行。
解决办法
1. 优先减少基函数数量
既然200-700个基函数都能正常运行,完全没必要用800个:
- 无惩罚的B样条平滑中,过多的基函数会导致平滑结果几乎和原始数据重合,完全失去平滑的意义,还会引入过拟合风险。
- 从你的样本量(44467行)来看,200-500个基函数已经足够捕捉数据的趋势了。
2. 手动设置非均匀节点(如果一定要用更多基函数)
如果你因为特殊需求必须用800个基函数,可以放弃默认的均匀节点,改用基于数据分位数的自适应节点,避免基函数过度重叠:
n=44467 argvals=data_totale$temps_ref_st library(fda) TableGCV<-c() i <- 800 j <- 0 # 基于数据分位数设置节点,B样条基函数数 = 节点数 + 3 breaks <- quantile(argvals, seq(0, 1, length.out = i - 3)) # 创建自适应节点的B样条基 basisobj = create.bspline.basis(c(0, max(argvals)), breaks = breaks) fdParobj = fdPar(fdobj=basisobj, Lfdobj=2, j) smoothlist = smooth.basis(argvals, mdata, fdParobj) xfd_acc = smoothlist$fd xfd_acc_coef = smoothlist$fd$coefs gcv = smoothlist$gcv TableGCV <- rbind(TableGCV,c(i,j,gcv))
3. 保留惩罚项(更推荐的方案)
惩罚项不仅能解决正定矩阵的问题,还能有效控制过拟合。即使你想用较多的基函数,也建议设置一个非0的惩罚系数(比如从0.001开始尝试),平衡拟合效果和平滑性。
4. 检查并处理重复的自变量值
如果你的argvals存在大量重复值,会进一步加剧基函数矩阵的秩亏问题。可以先检查并处理:
# 检查重复值数量 sum(duplicated(argvals)) # 对重复的自变量值,合并对应的因变量(比如取均值) library(dplyr) data_clean <- data_totale %>% group_by(temps_ref_st) %>% summarise(mdata = mean(mdata, na.rm = TRUE)) %>% ungroup() argvals_clean <- data_clean$temps_ref_st mdata_clean <- data_clean$mdata
内容的提问来源于stack exchange,提问作者Victoire Louis

