Rの関数 gls {nlme} のスクラッチ再現を試みます。
本ポストはこちらの続きです。

Rの関数:gls {nlme}
Rの関数から gls {nlme} を確認します。gls関数についてglsは、Generalized Least Squares(一般化最小二乗法)を用いて線形モデルをフィッティングするための関数です。通常の線形モデル(lm()関数で実行さ...
gls {nlme} のスクラッチ再現コード
###############################################
# 一般化最小二乗法(GLS)のスクラッチ再現と
# nlme::gls() 関数の結果比較シミュレーション
###############################################
# ----------------------------------------------------------
# 【目的】
# 誤差項に相関構造(AR(1)型)を持つサンプルデータを生成し、
# 1. 既知の共分散行列 Σ を用いた「理論通りのGLS推定(スクラッチ実装)」
# 2. Rの関数 gls() による推定結果
# が一致することを確認する。
# ----------------------------------------------------------
# ----------------------------------------------------------
# 1. 必要なパッケージの読み込み
# ----------------------------------------------------------
library(MASS) # 多変量正規乱数生成 (mvrnorm)
library(nlme) # 一般化最小二乗法 gls() の関数を提供
# ----------------------------------------------------------
# 2. 乱数シード設定(再現性確保)
# ----------------------------------------------------------
<- 20251019
seed set.seed(seed)
# ----------------------------------------------------------
# 3. モデル設定:サンプルサイズと誤差構造
# ----------------------------------------------------------
<- 100 # 標本サイズ
n <- 0.6 # 誤差のAR(1)型相関係数(隣接誤差間の相関)
rho <- 1 # 誤差の分散(全体スケール)
sigma2
# AR(1)型共分散行列 Σ を構築
# Σ_ij = σ^2 * ρ^|i−j|
<- sigma2 * rho^abs(outer(1:n, 1:n, "-"))
Sigma # → outer(1:n, 1:n, "-") は i-j の行列を作る。
# その絶対値を取りρのべき乗を計算し、σ^2を掛けて共分散行列を得る。
cat("--- 生成した共分散行列Σの一部を確認 ---\n")
print(Sigma[1:7, 1:7])
# ----------------------------------------------------------
# 4. 説明変数(X)と真のパラメータ設定
# ----------------------------------------------------------
<- runif(n, 0, 10) # 一様乱数:説明変数1
x1 <- runif(n, 0, 5) # 一様乱数:説明変数2
x2
# デザイン行列(切片を含む)
<- cbind(1, x1, x2)
X
# 真の回帰係数(母数)
<- c(2, 0.5, -0.3)
beta_true # y = 2 + 0.5*x1 - 0.3*x2 + 誤差
# ----------------------------------------------------------
# 5. 相関構造を持つ誤差項 ε の生成
# ----------------------------------------------------------
<- MASS::mvrnorm(1, mu = rep(0, n), Sigma = Sigma)
eps # → 平均0、共分散Σに従う多変量正規乱数ベクトル
cat("\n\n--- 生成した相関構造を持つ誤差項 ε の一部を確認 ---\n")
print(str(eps))
# ----------------------------------------------------------
# 6. 応答変数 y の生成
# ----------------------------------------------------------
<- X %*% beta_true + eps
y # → 線形モデル y = Xβ + ε の生成
# データフレーム化
<- data.frame(y, x1, x2, group = factor(rep(1, n)))
df # 注意:
# gls() の correlation 引数では「グループ単位で相関構造を推定」する。
# 全観測が同一系列に属するように group=1 を指定するのがポイント。
# (id=1:n のようにしてしまうと、各観測が別系列と解釈され相関が無効化される)
# ----------------------------------------------------------
# 7. GLSのスクラッチ実装(既知Σを使用)
# ----------------------------------------------------------
# 一般化最小二乗法の理論式:
# β̂_GLS = (X' Σ^{-1} X)^{-1} X' Σ^{-1} y
<- solve(Sigma)
Sigma_inv <- solve(t(X) %*% Sigma_inv %*% X) %*% t(X) %*% Sigma_inv %*% y
beta_gls
# このβ_glsは「Σを既知として正確にGLS推定を行った結果」であり、
# 理論上は最尤推定値と一致する。
# ----------------------------------------------------------
# 8. Rのgls()関数による推定
# ----------------------------------------------------------
<- gls(
model_gls ~ x1 + x2, # 回帰式
y data = df, # データフレーム
correlation = corAR1( # 誤差構造:AR(1)モデルを指定
value = rho, # 相関係数ρを既知として固定
form = ~ 1 | group, # 1つのグループ(系列)内でAR(1)を仮定
fixed = TRUE # ρを推定せず、指定値を固定
),method = "ML" # 最尤法(REMLでもほぼ同じだが、比較を厳密にするためML)
)
# gls() は誤差共分散構造をcorrelationオブジェクトから内部的に構築し、
# GLS推定を行う関数である。
# ここでは、理論上と同じρを固定しているため、
# スクラッチ実装の結果とほぼ一致するはずである。
# ----------------------------------------------------------
# 9. 結果の比較出力
# ----------------------------------------------------------
cat("\n\n--- スクラッチ実装と関数glsによる係数の比較 ---\n")
print(cbind(
beta_true = beta_true, # 真のパラメータ値
beta_gls_scratch = as.vector(beta_gls), # 手計算(スクラッチ)によるGLS推定
beta_gls_function = coef(model_gls) # gls()関数による推定値
))
--- 生成した共分散行列Σの一部を確認 ---
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1.000000 0.60000 0.3600 0.216 0.1296 0.07776 0.046656
[2,] 0.600000 1.00000 0.6000 0.360 0.2160 0.12960 0.077760
[3,] 0.360000 0.60000 1.0000 0.600 0.3600 0.21600 0.129600
[4,] 0.216000 0.36000 0.6000 1.000 0.6000 0.36000 0.216000
[5,] 0.129600 0.21600 0.3600 0.600 1.0000 0.60000 0.360000
[6,] 0.077760 0.12960 0.2160 0.360 0.6000 1.00000 0.600000
[7,] 0.046656 0.07776 0.1296 0.216 0.3600 0.60000 1.000000
--- 生成した相関構造を持つ誤差項 ε の一部を確認 ---
num [1:100] -0.433 -1.24 -0.799 -0.117 -1.628 ...
NULL
--- スクラッチ実装と関数glsによる係数の比較 ---
beta_true beta_gls_scratch beta_gls_function
(Intercept) 2.0 1.9313673 1.9313673
x1 0.5 0.4742645 0.4742645
x2 -0.3 -0.2753223 -0.2753223
スクラッチ実装 と 関数gls の結果が一致していることを確認できます。
以上です。