からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

【R】3.1.4:リッジ回帰の実装【PRMLのノート】

はじめに

 『パターン認識と機械学習』の独学時のまとめです。一連の記事は「数式の行間埋め」または「R・Pythonでのスクラッチ実装」からアルゴリズムの理解を補助することを目的としています。本とあわせて読んでください。

 この記事は、3.1.4項「正則化最小二乗法」の内容です。リッジ回帰(L2正則化)をR言語で実装します。

【数理読解編】

www.anarchive-beta.com

【前節の内容】

www.anarchive-beta.com

【他の節一覧】

www.anarchive-beta.com

【この節の内容】

・Rで実装

 リッジ回帰(L2正則化)を実装します。線形基底関数モデルについては「【R】3.1.1:線形基底関数モデル【PRMLのノート】 - からっぽのしょこ」を参照してください。

 利用するパッケージを読み込みます。

# 3.1.4項で利用するパッケージ
library(tidyverse)


・リッジ回帰

 リッジ回帰により観測データから真のモデルを推定(近似)します。

・モデルの設定とデータの生成

 データを生成する関数を設定して、利用するデータを人工的に生成します。処理の内容は3.1.1項と同じです。詳しくはそちらを参照してください。

 データ生成関数(推定対象の関数)と基底関数を作成します。

# 真の関数を作成
y_true <- function(x) {
  # 計算式を指定
  y <- sin(2 * pi * x)
  return(y)
}

# 多項式基底関数を作成
phi_poly <- function(x, m) {
  # m乗を計算
  y <- x^m
  return(y)
}

# 計画行列を作成
Phi <- function(x_n, M) {
  # 変数を初期化
  x_nm <- matrix(0, nrow = length(x_n), ncol = M)
  
  # m列目を計算
  for(m in 0:(M-1)) {
    x_nm[, m+1] <- phi_poly(x_n, m)
  }
  return(x_nm)
}

 この例では、多項式基底関数を使います。ガウス基底関数やシグモイド基底関数を使う場合は3.1.1項を参照してください。

 真のモデルの精度パラメータを指定して出力を計算します。

# データの範囲を指定
x_min <- 0
x_max <- 1

# 作図用のxの値を作成
x_vec <- seq(x_min, x_max, by = 0.01)

# 真の精度パラメータを指定
beta_true <- 3
sigma_true <- sqrt(1 / beta_true) # 真の標準偏差

# 真のモデルを計算
model_df <- tidyr::tibble(
  x = x_vec, # x軸の値
  y = y_true(x), # y軸の値
  minus_sigma = y - 2 * sigma_true, # μ - 2σ
  plus_sigma = y + 2 * sigma_true # μ + 2σ
)


 設定したモデルに従って、データを生成します。

# データ数を指定
N <- 100

# (観測)データを生成
x_n <- runif(n = N, min = x_min, max = x_max) # 入力
t_n <- y_true(x_n) + rnorm(n = N, mean = 0, sd = sigma_true) # 出力

# 観測データをデータフレームに格納
data_df <- tidyr::tibble(
  x_n = x_n, # 入力
  t_n = t_n # 出力
)

 $N$個の観測データ(入力$\mathbf{x} = \{x_1, x_2, \cdots, x_N\}$と目標値$\mathbf{t} = \{t_1, t_2, \cdots, t_N\}$)を作成できました。

・最尤推定

 正則化しない場合とする場合の最尤推定を行い、グラフを比較します。

 基底関数の数(パラメータの数)$M$を指定して、入力データを基底関数により変換します。

# 重みパラメータの次元数(基底関数の数)を指定
M <- 6

# 基底関数により入力を変換
phi_x_nm <- Phi(x_n, M)


 正則化を行わない場合の重みパラメータと分散パラメータの最尤解を計算します。

# 重みパラメータの最尤解を計算
w_ml_m <- solve(t(phi_x_nm) %*% phi_x_nm) %*% t(phi_x_nm) %*% t_n %>% 
  as.vector()

# 分散パラメータの最尤解を計算
sigma2_ml <- sum((t_n - t(w_ml_m) %*% t(phi_x_nm))^2) / N

# 精度パラメータの最尤解を計算
beta_ml <- 1 / sigma2_ml

# 推定したパラメータによるモデルを計算
ml_df <- tidyr::tibble(
  x = x_vec, # x軸の値
  t = t(w_ml_m) %*% t(Phi(x, M)) %>% 
    as.vector(), # y軸の値
  minus_sigma = t - 2 * sqrt(sigma2_ml), # μ - 2σ
  plus_sigma = t + 2 * sqrt(sigma2_ml) # μ + 2σ
)

 重みパラメータ、分散パラメータ、精度パラメータをそれぞれ次の式で計算します。

$$ \begin{align} \mathbf{w}_{\mathrm{ML}} &= (\boldsymbol{\Phi}^{\top} \boldsymbol{\Phi})^{-1} \boldsymbol{\Phi}^{\top} \mathsf{t} \tag{3.15}\\ \sigma^2_{\mathrm{ML}} &= \frac{1}{N} \sum_{n=1}^N \Bigl( t_n - \mathbf{w}_{\mathrm{ML}}^{\top} \phi(\mathbf{x}_n) \Bigr)^2 \tag{3.21}\\ \beta_{\mathrm{ML}} &= \frac{1}{\sigma^2_{\mathrm{ML}}} \end{align} $$

 ただし、$t_n - \mathbf{w}^{\top} \phi(\mathbf{x}_n)$の計算を$N$個同時に行うため、$\mathbf{t} - \mathbf{w}^{\top} \boldsymbol{\Phi}^{\top}$で計算しています。

 また、推定した重みパラメータを使って、y軸の値を次の式で計算します。

$$ \begin{aligned} \mathbf{t} &= \mathbf{w}_{\mathrm{ML}}^{\top} \boldsymbol{\Phi}^{\top} \\ t_n &= \mathbf{w}_{\mathrm{ML}}^{\top} \boldsymbol{\phi}(x_n) \end{aligned} $$

 さらに、分散パラメータsigma2_hat(精度パラメータ$\beta_{\mathrm{ML}}$)を用いて、推定した精度を求めます。

 ここまでは、3.1.1項と同様の処理です。

 続いて、正則化を行う場合の重みパラメータと分散パラメータの最尤解を計算します。

# 正則化係数を指定
lambda <- 0.5

# リッジ回帰の重みパラメータの最尤解を計算
w_ridge_m <- solve(lambda * diag(M) + t(phi_x_nm) %*% phi_x_nm) %*% t(phi_x_nm) %*% t_n %>% 
  as.vector()

# リッジ回帰の分散パラメータの最尤解を計算
sigma2_ridge <- sum((t_n - t(w_ridge_m) %*% t(phi_x_nm))^2) / N

# リッジ回帰の精度パラメータの最尤解を計算
beta_ridge <- 1 / sigma2_ridge

 重みパラメータ、分散パラメータ、精度パラメータをそれぞれ次の式で計算します。

$$ \begin{align} \mathbf{w}_{\mathrm{Ridge}} &= \Bigl( \lambda \mathbf{I} + \boldsymbol{\Phi}^{\top} \boldsymbol{\Phi} \Bigr)^{-1} \boldsymbol{\Phi}^{\top} \mathsf{t} \tag{3.28}\\ \sigma^2_{\mathrm{Ridge}} &= \frac{1}{N} \sum_{n=1}^N \Bigl( t_n - \mathbf{w}_{\mathrm{Ridge}}^{\top} \phi(\mathbf{x}_n) \Bigr)^2 \tag{3.21}\\ \beta_{\mathrm{Ridge}} &= \frac{1}{\sigma^2_{\mathrm{Ridge}}} \end{align} $$

 こちらも、$N$個同時に計算(処理)します。
 diag()で単位行列を作成できます。

 求めたパラメータを確認しましょう。

# 最尤推定のパラメータを確認
w_ml_m
beta_ml
## [1]   -0.1919435    8.4493592    6.2285041 -111.6199518  168.0748626
## [6]  -70.9656561

## [1] 3.48164
# リッジ回帰のパラメータを確認
w_ridge_m
beta_ridge
## [1]  1.0575828 -1.1872979 -2.0072705 -0.7966285  0.5942722  1.6961360

## [1] 2.157043


 リッジ回帰により推定したパラメータを用いて、モデルの出力を計算します。

# 推定したパラメータによるモデルを計算
ridge_df <- tidyr::tibble(
  x = x_vec, # x軸の値
  t = t(w_ridge_m) %*% t(Phi(x, M)) %>% 
    as.vector(), # y軸の値
  minus_sigma = t - 2 * sqrt(sigma2_ridge), # μ - 2σ
  plus_sigma = t + 2 * sqrt(sigma2_ridge) # μ + 2σ
)

# 確認
head(ridge_df)
## # A tibble: 6 x 4
##       x     t minus_sigma plus_sigma
##   <dbl> <dbl>       <dbl>      <dbl>
## 1  0    1.06       -0.304       2.42
## 2  0.01 1.05       -0.316       2.41
## 3  0.02 1.03       -0.329       2.39
## 4  0.03 1.02       -0.342       2.38
## 5  0.04 1.01       -0.355       2.37
## 6  0.05 0.993      -0.369       2.35

 先ほどと同様に、推定した重みパラメーを使って、y軸の値を次の式で計算します。

$$ \begin{aligned} \mathbf{t} &= \mathbf{w}_{\mathrm{Ridge}}^{\top} \boldsymbol{\Phi}^{\top} \\ t_n &= \mathbf{w}_{\mathrm{Ridge}}^{\top} \boldsymbol{\phi}(x_n) \end{aligned} $$


 リッジ回帰により推定したパラメータを用いたモデルを作図します。

# 推定したパラメータによるモデルを作図
ggplot() + 
  geom_point(data = data_df, aes(x = x_n, y = t_n)) + # 観測データ
  geom_line(data = model_df, aes(x = x, y = y), color = "cyan4") + # 真のモデル
  geom_ribbon(data = model_df, aes(x = x, ymin = minus_sigma, ymax = plus_sigma), 
              fill = "cyan4", alpha = 0.1, color = "cyan4", linetype = "dotted") + # 真のノイズ範囲
  geom_line(data = ml_df, aes(x = x, y = t), color = "blue", linetype ="dashed") + # 推定したモデル:(正則化なし)
  geom_line(data = ridge_df, aes(x = x, y = t), color = "blue") + # 推定したモデル:(L2正則化)
  geom_ribbon(data = ridge_df, aes(x = x, ymin = minus_sigma, ymax = plus_sigma), 
              fill = "blue", alpha = 0.1, color = "blue", linetype = "dotted") + # 推定したノイズ範囲
  #ylim(c(-5, 5)) + 
  labs(title = "Ridge Regression", 
       subtitle = paste0("N=", N, ", M=", M, ", lambda=", lambda, ", beta=", round(beta_ridge, 2)), 
       x = "x", y = "t")

f:id:anemptyarchive:20211119043211p:plain
リッジ回帰

 緑の実線が真のモデル、青の実線がリッジ回帰(L2正則化)による近似曲線、青の破線が正則化なしの近似曲線です。
 この例だと、正則化しない方がうまく近似できていますね。
 $\lambda$の値が大きいほど、正則化の効果が強まります。

 正則化の効果を見るために、観測データ数を減らしパラメータ数を増やして、過学習が起きやすい設定にしてみます。

f:id:anemptyarchive:20211119043225p:plain
リッジ回帰

 正則化していない方(青の破線)はデータに過剰に適合しているのが分かります。正則化している方(青の実線)は過剰適合を回避できています。

・重みパラメータと誤差関数の関係

 ここまでで、リッジ回帰を実装できました。次は、「二乗和誤差関数・正則化項」と「重みパラメータの最尤解」との関係をグラフで確認します。

・モデルの設定

 作図用の$\mathbf{w} = (w_1, w_2)$の値を作成します。2次元のグラフで描画するため$M = 2$とします。

# パラメータの次元数を設定:(固定)
M <- 2

# 作図用のwの範囲を指定
w_i <- seq(-3, 3, by = 0.1)

# 作図用のwの点を作成
w_im <- cbind(
  rep(w_i, times = length(w_i)), # x軸の値
  rep(w_i, each = length(w_i)) # y軸の値
)

 w_imの各行が1つの点$\mathbf{w}$です。

 二乗和誤差関数と正則化項を計算します。

# 値を設定:(固定)
q <- 2

# 基底関数により入力を変換
phi_x_nm <- Phi(x_n, M)

# 正則化項を計算
E_df <- tidyr::tibble(
  w_1 = w_im[, 1], # x軸の値
  w_2 = w_im[, 2], # y軸の値
  E_D = colSums((t_n - t(w_im %*% t(phi_x_nm)))^2) / N, # 二乗和誤差
  E_W = abs(w_1)^q + abs(w_2)^q # 正則化項
)

# 確認
head(E_df)
## # A tibble: 6 x 4
##     w_1   w_2   E_D   E_W
##   <dbl> <dbl> <dbl> <dbl>
## 1  -3      -3  21.1  18  
## 2  -2.9    -3  20.2  17.4
## 3  -2.8    -3  19.4  16.8
## 4  -2.7    -3  18.5  16.3
## 5  -2.6    -3  17.7  15.8
## 6  -2.5    -3  16.9  15.2

 二乗和誤差関数$E_D(\mathbf{w})$と正則化項(L2ノルムの2乗)$E_W(\mathbf{w})$をそれぞれ次の式で計算します。ノルムについては「【R】Lpノルムの作図【PRMLのノート】 - からっぽのしょこ」を参照してください。

$$ \begin{align} E_D(\mathbf{w}) &= \frac{1}{2} \sum_{n=1}^N \Bigl\{ t_n - \mathbf{w}^{\top} \boldsymbol{\phi}(\mathbf{x}_n) \Bigr\}^2 \tag{3.26}\\ E_W(\mathbf{w}) &= \frac{1}{2} \sum_{j=1}^M |w_j|^2 = \frac{1}{2} \mathbf{w}^{\top} \mathbf{w} \tag{3.25} \end{align} $$


 二乗和誤差関数と正則化項のグラフを作成します。

# 二乗和誤差関数の等高線図を作成
ggplot(E_df, aes(x = w_1, y = w_2)) + 
  geom_contour_filled(aes(z = E_D, fill = ..level..), alpha = 0.7) + # 二乗和誤差関数:(塗りつぶし)
  #geom_contour(aes(z = E_D, color = ..level..)) + # 二乗和誤差関数:(等高線)
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = expression(E[D](w)), 
       subtitle = paste0("q=", q), 
       x = expression(w[1]), y = expression(w[2]), fill = expression(E[D](w)))

# 正則化項の等高線図を作成
ggplot(E_df, aes(x = w_1, y = w_2)) + 
  geom_contour_filled(aes(z = E_W, fill = ..level..), alpha = 0.7) + # 正則化項:(塗りつぶし)
  #geom_contour(aes(z = E_W, color = ..level..)) + # 正則化項:(等高線)
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = expression(E[W](w)), 
       subtitle = paste0("q=", q), 
       x = expression(w[1]), y = expression(w[2]), fill = expression(E[W](w)))

f:id:anemptyarchive:20211119043320p:plainf:id:anemptyarchive:20211119043323p:plain
二乗和誤差関数と正則化項のグラフ

 二乗和誤差関数が最小になる$\mathbf{w}$の値は、モデルによって異なります。一方、正則化項が最小になるのは、全ての要素が0のときです。

・最尤推定

 正則化係数を指定して、重みパラメータの最尤解を計算します。

# 正則化係数を指定
lambda <- 5

# リッジ回帰の重みパラメータの最尤解を計算
w_ridge_m <- solve(lambda * diag(M) + t(phi_x_nm) %*% phi_x_nm) %*% t(phi_x_nm) %*% t_n %>% 
  as.vector()

# 重みパラメータの最尤解を計算
w_ml_m <- solve(t(phi_x_nm) %*% phi_x_nm) %*% t(phi_x_nm) %*% t_n %>% 
  as.vector()

# 重みパラメータをデータフレームに格納
w_df <- tidyr::tibble(
  w_1 = c(w_ridge_m[1], w_ml_m[1]), # x軸の値
  w_2 = c(w_ridge_m[2], w_ml_m[2]), # y軸の値
  method = factor(c("ridge", "ml"), levels = c(c("ridge", "ml"))) # ラベル
)

# 確認
head(w_df)
## # A tibble: 2 x 3
##     w_1    w_2 method
##   <dbl>  <dbl> <fct> 
## 1 0.192 -0.218 ridge 
## 2 0.661 -1.14  ml


 推定したパラメータによる二乗和誤差と正則化項を計算します。

# 推定したパラメータによる誤差項を計算
E_D <- sum((t_n - w_ridge_m %*% t(Phi(x_n, M)))^2) / N
E_W <- abs(w_ridge_m[1])^q + abs(w_ridge_m[2])^q

# 確認
E_D
E_W
## [1] 0.6246592

## [1] 0.08428112


 推定した重みパラメータをプロットします。

# 最尤推定量を作図
ggplot() + 
  geom_contour_filled(data = E_df, aes(x = w_1, y = w_2, z = E_D, fill = ..level..), alpha = 0.7) + # 二乗和誤差関数:(塗りつぶし)
  geom_contour(data = E_df, aes(x = w_1, y = w_2, z = E_D), color = "blue", breaks = E_D) + # 二乗和誤差関数:(等高線)
  geom_contour(data = E_df, aes(x = w_1, y = w_2, z = E_W), color = "red", breaks = E_W) + # 正則化項:(等高線)
  geom_point(data = w_df, aes(x = w_1, y = w_2, color = method), shape = 4, size = 5) + # パラメータの最尤解
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = "Ridge Regression", 
       subtitle = paste0("lambda=", lambda, 
                         ", w_ridge=(", paste0(round(w_ridge_m, 2), collapse = ", "), ")", 
                         ", w_ml=(", paste0(round(w_ml_m, 2), collapse = ", "), ")"), 
       x = expression(w[1]), y = expression(w[2]), fill = expression(E[D](w)))

f:id:anemptyarchive:20211119043410p:plain
リッジ回帰の最尤解

 推定した重みパラメータを通る二乗和誤差関数と正則化項の等高線の1本をそれぞれ描画します。この図が、リッジ回帰の説明でよく見る図です(よね?)。
 正則化なしの最尤推定で求めた値(青色のバツ印)$\mathbf{w}_{\mathrm{ML}}$は、誤差関数を最小化する値(点)なので、塗りつぶし等高線(青色の等高線)の中心に位置します。
 正則化ありの最尤推定で求めた値(赤色のバツ印)$\mathbf{w}_{\mathrm{Ridge}}$は、正則化なしの位置から正則化項の等高線(赤色の等高線)の中心(原点)に近付きます。どれだけ変化するのかは、$\lambda$の大きさに依存します。
 また、2つの等高線が接する点であるのも確認できます。

 誤差関数の等高線も作図してみます。

# 正則化係数を指定
lambda <- 1

# 誤差関数を作図
ggplot(E_df, aes(x = w_1, y = w_2)) + 
  geom_contour_filled(aes(z = E_D + lambda * E_W, fill = ..level..)) + # 二乗和誤差関数:(塗りつぶし)
  geom_contour(aes(z = E_D), color = "blue", alpha = 0.5, linetype = "dashed") + # 二乗和誤差関数:(等高線)
  geom_contour(aes(z = E_W), color = "red", alpha = 0.5, linetype = "dashed") + # 正則化項
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = expression(E(w) == E[D](w) + lambda * E[w](w)), 
       subtitle = paste0("q=", q, ", lambda=", lambda), 
       x = expression(w[1]), y = expression(w[2]), fill = expression(E(w)))

f:id:anemptyarchive:20211119043432p:plain
誤差関数のグラフ

 誤差関数は、$E_{\mathrm{Ridge}}(\mathbf{w}) = E_D(\mathbf{w}) + \lambda E_W(\mathbf{w})$で計算します。
 2つの破線は、確認用に表示しているだけです。

・おまけ:正則化係数と最尤解の関係

 最後に、正則化係数$\lambda$の値と最尤解の関係をアニメーションで確認します。

・作図コード(クリックで展開)

 forループでlambdaの値を変更して繰り返し最尤解を計算して、計算結果をデータフレームに追加していきます。

# 正則化係数の最大値を指定
lambda_max <- 100

# 使用するlambdaの値を作成
lambda_vec <- seq(0, lambda_max, by = 1)
length(lambda_vec)

# lambdaごとに最尤解を計算
anime_w_df <- tidyr::tibble()
anime_E_df <- tidyr::tibble()
for(lambda in lambda_vec) {
  # リッジ回帰の重みパラメータの最尤解を計算
  w_ridge_m <- solve(lambda * diag(M) + t(phi_x_nm) %*% phi_x_nm) %*% t(phi_x_nm) %*% t_n %>% 
    as.vector()
  
  # 推定したパラメータによる誤差項を計算
  tmp_E_D <- sum((t_n - w_ridge_m %*% t(Phi(x_n, M)))^2) / N # 二乗和誤差
  tmp_E_W <- abs(w_ridge_m[1])^q + abs(w_ridge_m[2])^q # 正則化項
  
  # アニメーション用のラベルを作成
  tmp_label <- paste0(
    "lambda=", lambda, ", E=", round(tmp_E_D + tmp_E_W, 2), ", E_D=", round(tmp_E_D, 2), ", E_W=", round(tmp_E_W, 2)
  )
  
  # 推定したパラメータをデータフレームに格納
  tmp_w_df <- tidyr::tibble(
    w_1 = c(w_ridge_m[1], w_ml_m[1]), # x軸の値
    w_2 = c(w_ridge_m[2], w_ml_m[2]), # y軸の値
    method = factor(c("ridge", "ml"), levels = c(c("ridge", "ml"))), # ラベル
    label = as.factor(tmp_label) # フレーム切替用のラベル
  )
  
  # 結果を結合
  anime_w_df <- rbind(anime_w_df, tmp_w_df)
  anime_E_df <- E_df %>% 
    dplyr::select(w_1, w_2, E_D) %>% # 使用する列を抽出
    cbind(label = as.factor(tmp_label)) %>% # フレーム切替用のラベル列を追加
    rbind(anime_E_df, .)
}

# 確認
head(anime_w_df)
head(anime_E_df)
## # A tibble: 6 x 4
##     w_1    w_2 method label                               
##   <dbl>  <dbl> <fct>  <fct>                               
## 1 0.661 -1.14  ridge  lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 2 0.661 -1.14  ml     lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 3 0.412 -0.640 ridge  lambda=1, E=1.15, E_D=0.57, E_W=0.58
## 4 0.661 -1.14  ml     lambda=1, E=1.15, E_D=0.57, E_W=0.58
## 5 0.310 -0.439 ridge  lambda=2, E=0.88, E_D=0.59, E_W=0.29
## 6 0.661 -1.14  ml     lambda=2, E=0.88, E_D=0.59, E_W=0.29

##    w_1 w_2      E_D                                label
## 1 -3.0  -3 21.13854 lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 2 -2.9  -3 20.24739 lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 3 -2.8  -3 19.37624 lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 4 -2.7  -3 18.52508 lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 5 -2.6  -3 17.69393 lambda=0, E=2.29, E_D=0.55, E_W=1.74
## 6 -2.5  -3 16.88278 lambda=0, E=2.29, E_D=0.55, E_W=1.74


 gganimateパッケージを利用してアニメーション(gif画像)を作成します。

# 二乗和誤差と最尤解の関係を作図
anime_graph <- ggplot() + 
  geom_contour_filled(data = anime_E_df, aes(x = w_1, y = w_2, z = E_D, fill = ..level..), alpha = 0.7) + # 二乗和誤差関数:(塗りつぶし)
  geom_contour(data = E_df, aes(x = w_1, y = w_2, z = E_W), color = "red", breaks = 1) + # 正則化項
  geom_point(data = anime_w_df, aes(x = w_1, y = w_2, color = method), shape = 4, size = 5) + # パラメータの最尤解
  gganimate::transition_manual(label) + # フレーム
  coord_fixed(ratio = 1) + # アスペクト比
  labs(title = "Ridge Regression", 
       subtitle = paste0("{current_frame}"), 
       x = expression(w[1]), y = expression(w[2]), fill = expression(E[D](w)))

# gif画像に変換
gganimate::animate(anime_graph, nframes = length(lambda_vec), fps = 10)


f:id:anemptyarchive:20211119043457g:plain
正則化係数と最尤解の関係

 $\lambda$の値が大きくなるにしたがって、最尤解が原点に近付くのが確認できます。

参考文献

  • C.M.ビショップ著,元田 浩・他訳『パターン認識と機械学習 上下』,丸善出版,2012年.

おわりに

 こっちは問題なくできた問題はラッソ回帰...

 先ほど配信されたモーニング娘。'21の新曲MVをどうぞ!

 してほしーい🔫

【次節の内容】

続く