🧠

機械学習で使用される目的関数の理論

に公開

海洋ロボコンをやってた人です。

今回は機械学習で使用される目的関数:Objective function(活性化関数、損失関数、最適化関数)の数学的な理論式をパッと確認したく、色々調べたことを書き記しました。

どのような理論式かはPytorchの中身や実装時の挙動に意識を向けなければ、なかなか定着しないなと思ったのが背景です。

機械学習については専門ではありませんので、修正点等あればご遠慮なくご指摘ください。

各目的関数については随時追加し、pytorchで使用するときの関数も記載しています。

以下箇条書きになりますが、よろしくお願いします。

1. ニューラルネットワークの学習フロー

ニューラルネットワークの学習では下記のフローに応じて動作します。
このデータフローでは関数の理論を紹介するブロックを色付きとして示しています。

2. Activation Function

活性化関数(Activation Functions)は、各ニューロン(ノード)での出力を決定する関数であり、非線形性を導入することで、複雑なネットワークのパターンを学習する。

基本的な活性化関数の考え方は下記になります。

y = f(w_1x_1 + w_2x_2 + ... + w_nx_n + b)

ここで f が活性化関数です。よく参考書籍などで出てきますね。

このfの選び方を列挙していきます。

2.1. Sigmoid

Sigmoidは最初期から使用されている活性化関数で、出力[0,1]の範囲に正規化する。

f(x) = \sigma(x) = \frac{1}{1 + e^{-x}}

ニューラルネットワークの重みとバイアスを考慮した場合は下記となる。
w_1が大きければ出力は急になり、小さければ緩やかに出力が変化する

f(x) = \sigma(w_1x+b) = \frac{1}{1 + e^{-(w_1x+b)}}

図での理解は下記

wの増加で傾きを急にして、bで左右方向のオフセットを行う。

pytorch
import torch.nn as nn
sigmoid = nn.Sigmoid()

2.2. Tanh (Hyperbolic Tangent)

Tanhは双曲線正接関数で、Sigmoidの改良版として使用され、出力[-1,1]の範囲に正規化し、RNNのHidden Layerなどで利用される。

\tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} = \frac{e^{2x} - 1}{e^{2x} + 1} \\ \tanh'(x) = 1 - \tanh^2(x)
pytorch
import torch.nn as nn
sigmoid = nn.Tanh()

2.3. ReLU

ReLU(Rectified Linear Unit)は深層学習で最も広く使用される活性化関数であり、正の領域では勾配を1に、負の領域では0へ(スパース性)を与える。

\text{ReLU}(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{if } x \leq 0 \end{cases}
pytorch
import torch.nn as nn
sigmoid = nn.ReLU()

この派生としてLeaky ReLUがあり、負の領域でも勾配を保持し致死ニューロンが発生することを防止するものがある。

2.4. Softmax

Softmaxは多クラス分類の出力層で使用される正規化関数であり、出力[0,1]で合計\sum=1となる。
DRLでは主にPolicy(方策)として利用される。

\text{Softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^K e^{x_j}}
pytorch
import torch.nn as nn
sigmoid = nn.Softmax(dim=1)

3. Loss Function

損失関数(Loss Functions)は機械学習や最適化においてモデルの予測結果と正解データとの「誤差」や「ズレ」を数値で表す関数で、モデルが正しいか、間違っているかを示す指標になります。

3.1. MSE

Mean Squared Error (MSE)は回帰問題で最も基本的な損失関数です。
2乗は損失の符号を正にするためです。

\text{MSE} = \frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2
pytorch
import torch.nn as nn

criterion = nn.MSELoss()

3.2. RMSE

RMSE(Root Mean Squared Error)はMSEに対して、二乗を外したものです。例えば、元のデータが「cm」の単位なら、MSEは「cm²」の単位になり、誤差の大きさを直感的に理解しづらいため一乗に戻すことができます。

\text{RMSE} = \sqrt{\frac{1}{n} \sum_{i=0}^n (y_i - f_w(x_i))^2}

3.3. Cross Entropy

交差エントロピー誤差(Closs-entrop:CE Loss)は分類問題において最も広く使用される損失関数で、確率分布間の「距離」を測定し、予測分布と真の分布の差を定量化します。

その前に確率分布 P として、分布の「ランダムさ」を定量化するエントロピーも理解する必要があります。(自己情報量)

エントロピーは一般的に下記で表されます。

H(P) = -\sum_{i=1}^{n} p_i \log p_i

例えば、サイコロの場合

公正なサイコロ (各面 1/6):
H = -6 \times \frac{1}{6} \log_2\left(\frac{1}{6}\right) = -\log_2\left(\frac{1}{6}\right) = \log_2(6) = 2.585 \text{ bit}
偏ったサイコロ (P = [0.5, 0.2, 0.1, 0.1, 0.05, 0.05]):

H = -0.5 \log_2(0.5) - 0.2 \log_2(0.2) - 0.1 \log_2(0.1) - 0.1 \log_2(0.1) - 0.05 \log_2(0.05) - 0.05 \log_2(0.05)
= 0.5 + 0.464 + 0.332 + 0.332 + 0.216 + 0.216 = 2.060 \text{ bit}

となり公正なサイコロの方が不確実性/ランダムさが高く、エントロピーが大きいです。
つまり、結果が予測しづらいといえますね。

一方、偏ったサイコロではエントロピーが小さいので、結果が予測しやすいということです。


では2つの確率分布 P(真の分布)と Q(予測分布)の交差エントロピーを考えると

H(P, Q) = -\sum_{i=1}^{n} p_i \log q_i \\

と表され、交差エントロピーとエントロピーの差はKLダイバージェンス(Kullback-Leibler)として定義される

D_{KL}(P||Q) = H(P, Q) - H(P)


また、standard binary cross-entropy lossは下記で与えられる

L_\text{BCE} = -\frac{1}{M} \sum_{m=1}^M [y_m \log(h_{\theta(x_m)}) + (1-y_m) \log(h_{\theta(x_m)})]
  • M: トレーニング数
  • y_m: ターゲットラベル
  • x_m: インプット
  • h_{\theta}: 結合重み\thetaのニューラルネットワークmodel

さらに、standard categorical cross-entropy loss

L_\text{CCE} = -\frac{1}{M} \sum_{k=1}^K \sum_{m=1}^M y_m^k \log(h_{\theta}(x_m,k))
  • K: Number of Classes

と与えられる。

pytorch
import torch.nn as nn

criterion = nn.CrossEntropyLoss()
kld_loss = nn.KLDivLoss()

4. Optimizer

最適化関数(Optimizer)とは損失(Loss)の勾配値(偏微分の計算結果)を基に、どのようなアルゴリズムでパラメータを修正するかを指す方式で、最適化関数次第で学習速度や精度が異なります。

計算コストの観点では

  • 軽量: SGD, SGD with Momentum
  • 普通: RMSprop, AdaGrad, Lion
  • 重い: Adam, AdamW, Nadam, RAdam

対称領域では

  • 画像認識: SGD with Momentum, AdamW
  • 自然言語処理: Adam, AdamW, Lion
  • 強化学習: Adam, RMSprop
  • スパースデータ: AdaGrad, Adam

などが考えられます。

また、ニューラルネットワークの活性化関数(ReLU、Sigmoid、タンジェント双曲線など)は非線形関数であり、凸最適化ではありません。

なのでADMM(交互方向乗数法)や Graphical Lasso(グラフィカルラッソ)で扱うような問題は、根本的に異なる性質を持つため、適用されるアプローチや考え方も異なります。

4.1. SGD

SGD (Stochastic Gradient Descent) は最も基本的な最適化アルゴリズムで、各イテレーションで勾配の負の方向にパラメータを更新します。

\theta_{t+1} = \theta_t - \alpha \nabla_\theta J(\theta_t) = \theta_t - \alpha \frac{\partial J}{\partial \theta_t}
  • \theta_t: 時刻tでのパラメータ
  • \alpha: 学習率
  • \nabla_\theta J(\theta_t): 損失関数Jの勾配
pytorch
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(10, 1)  # 例のモデル

# SGD
optimizer_sgd = optim.SGD(model.parameters(), lr=0.01)

シンプルで理解しやすい一方、学習率の発散や収束遅延の課題がある。

原論文:「On the variance of the adaptive learning rate and beyond.

4.2. Momentum

Momentumは過去の勾配情報を指数移動平均として保持し、勾配の方向に慣性を与える。

v_t = \gamma v_{t-1} + \alpha \nabla_\theta J(\theta_t) \\ \theta_{t+1} = \theta_t - v_t
  • v_t: 時刻tでの速度(モメンタム)
  • \gamma: モメンタム係数(通常0.9)
pytorch
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(10, 1)  # 例のモデル

# Momentum
optimizer_momentum = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

これにより下記が可能になる。

  • 振動の減少: 勾配が振動する場合でも安定した学習
  • 局所最適解からの脱出: 慣性により浅い局所最適解を突破
  • 収束の高速化: 一貫した方向への加速

4.3. AdaGrad

AdaGradは各パラメータの過去の勾配情報を累積し、頻繁に更新されるパラメータの学習率を減少させる。

G_t = G_{t-1} + g_t^2 \\ \theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{G_t + \epsilon}} g_t
  • G_t: 時刻tまでの勾配の二乗の累積和
  • g_t: 時刻tでの勾配
pytorch
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(10, 1)  # 例のモデル

# AdaGrad
optimizer_adagrad = optim.Adagrad(model.parameters(), lr=0.01)

これにより下記が可能になる。

  • スパースデータに効果的: 稀に更新されるパラメータには大きな学習率を維持
  • 学習率の単調減少: 時間が経つにつれて学習率が0に近づく問題
  • 長期学習での停滞: 累積効果により学習が停止する可能性

4.4. RMSProp

RMSpropはAdaGradの改良版で、勾配の二乗の指数移動平均を使用して学習率を適応的に調整する。

E[g^2]_t = \beta E[g^2]_{t-1} + (1-\beta) g_t^2 \\ \theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{E[g^2]_t + \epsilon}} g_t
  • E[g^2]_t: 勾配の二乗の指数移動平均
  • \beta: 減衰率(通常0.9)
  • g_t = \nabla_\theta J(\theta_t): 時刻tでの勾配
  • \epsilon: 数値安定性のための小さな定数(通常10^{-8}

二乗移動平均は

MeanSquare(w,t) = \beta MeanSquare(w,t_{t-1}) + (1-\beta)g_t^2

とも表せる。

pytorch
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(10, 1)  # 例のモデル

# RMSProp
optimizer_rmsprop = optim.RMSprop(model.parameters(), lr=0.01)

これにより下記の特徴を発揮できる。

  • 適応的学習率: 各パラメータに対して個別に学習率を調整
  • 勾配の大きさに応じた正規化: 大きな勾配は抑制、小さな勾配は増強
  • 非凸問題での安定性: 深層学習で広く使用される理由

原論文:「Tijmen Tieleman and Geoffrey Hinton. Lecture 6.5-rmsprop: Divide the
gradient by a running average of its recent magnitude. COURSERA: Neural
networks for machine learning, 4(2):26–31, 2012.」

4.5. Adam

Adam(Adaptive Moment Estimation)はMomentumRMSpropの利点を組み合わせた最適化アルゴリズムのことです。

m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t \\ v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2 \\ \hat{m}_t = \frac{m_t}{1-\beta_1^t} \\ \hat{v}_t = \frac{v_t}{1-\beta_2^t} \\ \theta_{t+1} = \theta_t - \alpha \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}
  • m_t: 1次モーメント(勾配の指数移動平均)
  • v_t: 2次モーメント(勾配の二乗の指数移動平均)
  • \hat{m}_t, \hat{v}_t: バイアス補正されたモーメント推定
  • \beta_1, \beta_2: 指数減衰率(通常\beta_1=0.9, \beta_2=0.999
pytorch
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Linear(10, 1)  # 例のモデル

# Adam
optimizer_adam = optim.Adam(model.parameters(), lr=0.001)

これにより下記が可能になった。

1次と2次モーメントの利用: 勾配の方向と大きさの両方を考慮
バイアス補正: 初期段階でのモーメント推定のバイアスを補正
幅広い適用性: 多くの深層学習タスクでデフォルトの選択肢
ハイパーパラメータの堅牢性: デフォルト値でも良好な性能

原論文:「Adam: A method for stochastic optimization.

Nadam

NadamはAdamにNesterov Momentumを組み込んだ改良版であり

\theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{\hat{v}_t} + \epsilon} \left(\beta_1 \hat{m}_t + \frac{(1-\beta_1) g_t}{1-\beta_1^t}\right)

これにより下記が可能となる。

  • 先読み効果: Nesterovの加速効果をAdamに追加
  • より効率的な収束: 特に初期段階での収束速度向上
  • Adam互換: Adamのハイパーパラメータ設定がそのまま使用可能

原論文:「Incorporating nesterov momentum into adam.

RAdam

RAdam(Rectified Adam)はAdamの初期段階での不安定性を解決する改良版であり、適応学習率の分散を修正し、安定的な学習を実現する方法です。

詳しくはオミータ氏の記事を参照。
https://qiita.com/omiita/items/d24568a835da6911b01e

原論文:「On the variance of the adaptive learning rate and beyond.

4.6. Lion

Lion optimization algorithm は進化的アルゴリズムによって発見された新しい最適化手法で下記で表される。 (Google researches, Chen et al. (2023))

c_t = \beta_1 m_{t-1} + (1-\beta_1) g_t \\ \theta_{t+1} = \theta_t - \alpha \cdot \text{sign}(c_t + \lambda \theta_{t-1}) \\ m_t = \beta_2 m_{t-1} + (1-\beta_2) g_t
  • c_t: モーメンタム補間
  • \text{sign}(\cdot): 符号関数
  • \beta_1, \beta_2: モーメンタム係数(通常\beta_1=0.9, \beta_2=0.99

Lionを用いることにより、AdamWよりも収束速度が早く下記を実現できる。

  • 符号ベースの更新: 勾配の符号のみを使用
  • メモリ効率: 2次モーメントを保存する必要がない
  • 大規模モデルでの効果: 特にTransformerの事前学習で優秀な性能

原論文:Symbolic Discovery of Optimization Algorithms.


以上、Likeいただけると大変励みになりますので、よろしくお願いいたします。

Discussion