You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用spgwr包LMZ.F3GWR.test()计算p值时遇奇异错误求助

解决GWR模型LMZ.F3GWR.test()函数的计算奇异错误问题

你遇到的错误本质是局部子样本的加权设计矩阵出现严重共线性,导致矩阵无法求逆。虽然全局数据无共线性,但自适应带宽下的局部样本可能出现变量线性相关、样本量过小等问题,以下是针对性解决方法:

1. 对齐核函数或调整带宽参数

当前模型拟合用的是gwr.Gauss核,但带宽选择用的是gwr.bisquare,核函数不一致可能导致局部权重分布差异,引发奇异矩阵。另外,自适应带宽可能在部分区域选得过小,导致局部样本不足。

# 方案1:更换核函数为带宽选择时的bisquare
gwr.model = gwr(alias(modelo)$Model,
                data = df_mun_spatial,
                adapt=bw,
                gweight = gwr.bisquare,  # 与gwr.sel保持一致
                hatmatrix=TRUE,
                se.fit=TRUE)

# 方案2:手动扩大带宽(比如乘以1.1),增加局部样本量
gwr.model = gwr(alias(modelo)$Model,
                data = df_mun_spatial,
                adapt=bw*1.1,
                gweight = gwr.Gauss,
                hatmatrix=TRUE,
                se.fit=TRUE)

2. 重新选择更大比例的自适应带宽

自适应带宽的adapt参数是按比例选取邻居,比如bw=0.3代表选30%的样本作为局部邻居。尝试提高这个比例,重新计算带宽后拟合模型:

# 指定起始比例为0.4,引导选择更大的自适应带宽
bw_new <- gwr.sel(alias(modelo)$Model,
                  data=df_mun_spatial, adapt = TRUE, gweight = gwr.bisquare,
                  start=0.4)

gwr.model_new = gwr(alias(modelo)$Model,
                    data = df_mun_spatial,
                    adapt=bw_new,
                    gweight = gwr.Gauss,
                    hatmatrix=TRUE,
                    se.fit=TRUE)

3. 给局部矩阵添加岭正则化

直接修改LMZ检验的内部逻辑,给奇异的局部设计矩阵添加小的岭惩罚项,避免无法求逆。以下是自定义的带正则化的LMZ检验函数:

LMZ.F3GWR.test_reg <- function(model, lambda=1e-8) {
  y <- model$y
  X <- model$X
  n <- length(y)
  p <- ncol(X)
  w <- model$SDF$gw.weights
  trH <- sum(model$hatmatrix)
  res <- y - model$fitted.values
  sigma2 <- sum(res^2)/(n - trH)
  
  t_vals <- matrix(NA, n, p)
  for (i in 1:n) {
    wj <- w[[i]]
    Xj <- X[wj>0,,drop=FALSE]
    Wj <- diag(wj[wj>0])
    XtWX <- t(Xj) %*% Wj %*% Xj
    # 添加岭惩罚项,避免矩阵奇异
    XtWX_reg <- XtWX + lambda * diag(p)
    
    tryCatch({
      invXtWX <- solve(XtWX_reg)
      beta_j <- invXtWX %*% t(Xj) %*% Wj %*% yj
      var_beta_j <- sigma2 * invXtWX %*% t(Xj) %*% Wj %*% Xj %*% invXtWX
      se_beta_j <- sqrt(diag(var_beta_j))
      t_vals[i,] <- beta_j / se_beta_j
    }, error=function(e) {
      warning(paste("局部模型", i, "添加lambda=", lambda, "后仍奇异"))
      t_vals[i,] <- NA
    })
  }
  
  # 计算双侧t检验的p值
  p_vals <- 2 * pt(-abs(t_vals), df = n - trH)
  colnames(p_vals) <- colnames(X)
  rownames(p_vals) <- rownames(model$SDF)
  return(list(t_values=t_vals, p_values=p_vals))
}

# 使用自定义函数计算p值
lmz_result <- LMZ.F3GWR.test_reg(gwr.model)
# 查看结果
head(lmz_result$p_values)

4. 检查变量的局部恒定值

全局标准化后无共线性,但某些局部区域可能存在变量取值完全恒定的情况,导致局部设计矩阵列线性相关。用以下代码检查:

library(spdep)
# 根据自适应带宽生成邻居列表
nb <- knn2nb(knearneigh(coordinates(df_mun_spatial), k=round(bw*nrow(df_mun_spatial))))
listw <- nb2listw(nb)

# 计算每个变量在局部邻居内的变异系数(标准差/均值)
vars <- colnames(gwr.model$X)
local_cv <- lapply(vars, function(var) {
  sapply(1:nrow(df_mun_spatial), function(i) {
    # 获取当前点及邻居的变量值
    neighbor_ids <- c(i, nb[[i]])
    vals <- df_mun_spatial[[var]][neighbor_ids]
    # 避免除以0,添加极小值
    sd(vals)/(mean(vals) + 1e-10)
  })
})
names(local_cv) <- vars

# 查看每个变量局部变异系数接近0的数量(即局部恒定的次数)
lapply(local_cv, function(x) sum(x < 1e-10))

如果某个变量存在大量局部恒定的情况,建议移除该变量,或对其进行分组合并(若为分类变量)。

内容的提问来源于stack exchange,提问作者ElMago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:15:57