Skip to content

Instantly share code, notes, and snippets.

@qnighy
Last active May 25, 2025 10:11
Show Gist options
  • Save qnighy/21b73467c6efed072a81fd5585663cf6 to your computer and use it in GitHub Desktop.
Save qnighy/21b73467c6efed072a81fd5585663cf6 to your computer and use it in GitHub Desktop.
深層学習覚え書き

深層学習覚え書き

深層学習 (ディープラーニング) とは

  • 深層学習 は多数の層を持つニューラルネットワークをモデルとして利用する機械学習手法のことである。
  • 機械学習 は、モデルを既知のデータにフィットさせることでプログラムの振る舞いを決定する手法のことである。

深層学習はニューラルネットワークを使うため、神経回路とのアナロジーで説明されることも多い。ただし、NNの動作を説明するにあたって必須ではないためここでは扱わない。

機械学習のポイント

ここでは教師あり学習のみを考える。

機械学習は数理最適化の一種である。一般の数理最適化との違いは目的関数にある。 古典的な数理最適化では要件から自然に定まる関数を目的関数に置くが、機械学習ではそのようなアプリオリな目的関数を設定しないかわりに、母集団に対して回答と実際の値の誤差を最小化することを目的にする。 実際には母集団そのものに対して目的関数を評価することはできないため、以下のように2段階で評価を行う。

  • 「学習データ」と呼ばれる標本に対する誤差を仮の目的関数に設定し、モデルのパラメーターを最適化する。これは学習ステップと呼ばれる。
  • 「評価用データ」と呼ばれる標本に対して誤差を評価し、これを最終的な目的関数の近似とみなす。

学習データと評価用データを分けるのはオーバーフィットを過大評価しないためである。

学習されたモデルは製品に投入され、実データに対して実行される (推論ステップ)。真に最適化したいのは、実データに対する推論の誤差である。

数理最適化の定式化

解空間 $V$ を集合とし、そのうち実行可能解の空間 $A \subseteq V$ を考える。目的関数 $f: A \to \mathbb{R}$ を考える。多くの定式化では $f$$f: V \to \mathbb{R}$ の制限として与えられる。

このとき $\min_{x \in A} f(x)$ を求めるのが数理最適化の目的である (反転すれば最大化問題にもなる) 。

より正確には、近似解や発見的な解を求める場合もあり、 $f(x) < \varepsilon + \inf_{x' \in A} f(x')$ となる $x$ を求める問題といった形でとらえることもある。

機械学習の定式化

ここでは教師あり学習のみを考える。

$f: B \to C$ を求める問題を考える。ここで、問題の性質にあわせてあらかじめ $C^B$ の部分空間 $A \subseteq C^B$ を選んでおく。これをモデル(のクラス)という。たとえば最小二乗法による回帰であれば1次関数の集合を考えていることになる。

さらに、学習データまたは評価データの集合 $D \in B \times C$ が与えられるとして、 $D$ を使って $f: B \to C$ の評価関数を構成する。

基本は距離 $L: C \times C \to \mathbb{R}$ を定義して、 $e(f) = \sum_{(x, y) \in D} L(f(x), y)$ のようにおく。

学習データに対する $e(f)$ を最小化(または、完全な最小化ができない場合はその近似または探索)し、続いて評価用データでその結果を評価する。

深層学習のポイント

深層学習は機械学習の一種であり、モデルとして「多数の層を持つニューラルネットワーク」を利用する。言い換えると、多数のステップを持つベクトル演算を考える。このステップの典型的な例として以下がある。

  • 入力をモデルパラメーター(重みと呼ばれる)を係数として線形結合する。あるいは行列を掛けると考えてもよい。
  • 入力に固定のベクトル(バイアスと呼ばれる)を足す。
  • 入力の各項に固定の非線形関数(活性化関数と呼ばれる; ReLUが代表的)を適用する。
    • 線形またはアフィン変換だけだと代数的に綺麗すぎて十分な複雑性が生じないため、活性化関数は複雑性を高めるために重要な役割を担っている。

入力、出力、およびパラメーターは実ベクトルと考えることができる。誤差を評価するための距離関数も、問題に応じて定める。

深層学習が古典的な機械学習と異なる点として以下がある。

  • モデルの複雑性が十分に高い (普遍近似定理)ため、画像処理や自然言語処理など高い複雑性を持つ問題に適用することができる。
  • モデルの複雑性が高いため、多くのデータを必要とする (???)
  • モデルの複雑性が高く多くのデータを必要とするため、大量の計算を必要とする。
    • 大量の計算を可能にするためにGPGPUなどの並列計算手法を利用することが多く、並列化に適したモデルを選ぶことも多い。
  • モデルの複雑性が高いため、代数的・解析的に整理された手法を適用できる場面が少なく、汎用の最適化手法をチューニングして用いることが多い。
    • たとえば最小二乗法であれば代数的に解が求まるが、深層学習ではそういった方法がほぼ使えない。
    • したがって、一般の数値計算のテクニックが援用される。
  • 問題が複雑であるため理論的な成果だけで良い結果を出すことは難しく、経験的に良いと知られている手法を組み合わせることでチューニングする。
  • 加えて、モデルや学習アルゴリズムの選択(ハイパーパラメーター)そのものを自動的に最適化するメタ手法(ハイパラチューニング)も用いられる。

深層学習の定式化

入力空間 $\mathbb{R}^\mathrm{nInput} \ni x$、出力空間 $\mathbb{R}^\mathrm{nOutput} \ni y$、およびパラメーター空間 $\mathbb{R}^\mathrm{nParam} \ni p$ を全て実ベクトル空間として、 $y = f(x, p)$ の形でモデルのクラスを記述する。このとき $f$ は前述のようなコンポーネントを組み合わせて記述する。このモデルクラスに対して $p$ を部分適用したものが最終的なモデルインスタンスとなる。

誤差関数は問題に合わせて選択する。

学習問題として見ると、入力はパラメーターベクトル $p$ であり、出力は誤差 (実数値) となる。

学習アルゴリズムの定式化

深層学習では最小値を求めることが難しいため、局所探索によって極小値に近づくことを目的にする。この問題自体は数値計算の最も基本的で重要な問題のひとつである。

数値計算では、たとえば導関数を0にする問題 (停留点を求める問題) と考えてニュートン法を適用するなどの方法もある。しかしニュートン法は複雑な問題では安定化させるのが難しく、高次元にも向いていない。深層学習ではよりシンプルな探索手法として、最急降下法 (gradient descent) ベースの手法が使われることが多い。

最急降下法では、評価関数の微分が計算できることを前提にしている。その計算方法については後述する。

  • 最急降下法 (gradient descent) は、評価関数 $f$ に対して、次のパラメーターを $-c\nabla f$ だけ移動させる繰り返し手法である。基本の形では $c$ は定数であるが、様々なバリエーションがある。
  • 確率的勾配降下法 (stochastic gradient descent) では、評価関数が小さい評価関数の線形結合として表されていることを前提にする (これは機械学習のシナリオでは、教師データの個々の行に対してそれぞれ誤差を計算していることに対応する)。このとき、小さい評価関数のうちどれか1つをランダムに選び、その小さい評価関数に対して最急降下法の1ステップを実行する。小さい評価関数の選択はi.i.d.である必要はなく、通常は各評価関数が均等に選択されるように調整する。
  • ミニバッチは確率的勾配降下法の亜種で、各ステップで評価関数の1つの項を選択するのではなく、複数の項を選択する。これは機械学習のシナリオでは、たくさんあるデータのうち決まった個数をまとめて処理することを意味する。

微分の計算

最適化を効率的に行うためには、目的関数の微分がほぼ必須である。

微分の計算にはリバースモード自動微分を使うのが一般的である。NNの文脈では誤差逆伝播とも呼ばれる。

微分の計算では関数合成に対してライプニッツルールを適用していくが、このとき関数合成は結合的であるため、結合順を好きなように選択できる。このとき関数合成を右結合 (入力側に寄せて結合) して処理するのがフォワードモード、左結合 (出力側に良せて結合) して処理するのがリバースモードと呼ばれる。

つまり、 $f(g(h(x)))$ のような関数の微分を計算するにあたって、 $(f \circ (g \circ h))(x)$ として処理するのがフォワードモード、 $((f \circ g) \circ h)(x)$ として処理するのがリバースモードにあたる。

フォワードモードの計算量が入力の次元(と関数グラフの大きさ)に比例するのに対し、リバースモードでは計算量は出力の次元(と関数グラフの大きさ)に比例する。深層学習で微分したい関数は大量の入力 (=モデルパラメーター) と1つの出力 (=誤差の評価値) を持つため、リバースモードが適している。

似たような状況として、行列連鎖積の計算とDijkstra法を挙げることができる。行列連鎖積においては行列積の結合性により好きな順番で計算できる。このとき、なるべく次元が小さくなっていくような順番で計算するのが良い。というか、大きな合成関数の微分はほぼそのまま行列連鎖積である。また、Dijkstra法では始点と終点を逆にしても同じ結果が求まる (これも距離の和が結合的であることと関係している)。カーナビのように、同じ終点・異なる始点に対して最短経路が求まっているほうが好ましいユースケースでは始点と終点を逆にする手法が使われていると考えられる。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment