Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Python 機械学習 (Machine Learning)

勾配消失問題とは?原因や対策についてもご紹介

投稿日:2022年11月6日 更新日:

<目次>

勾配消失問題とは?原因や対策についてもご紹介
 やりたいこと/概要
 STEP0:前提
 STEP1:勾配消失問題の原因と流れ
 STEP2:サンプルプログラム
 STEP3:まとめと学び

勾配消失問題とは?原因や対策についてもご紹介

やりたいこと/概要

ニューラルネットワークの学習において良く起きる問題の1つに「勾配消失問題」があります。
本記事では、この問題がニューラルネットワークにどのような影響を与えるか?について、原因・仕組み・実際の例を通じて分かりやすく紹介します。

目次にもどる

STEP0:前提

モデルの学習において、勾配が0になってしまい学習がうまく進まない現象を「勾配消失問題」と呼びます。
特に隠れ層が多い深層学習モデルでは、誤差逆伝播の過程で微小な勾配が何度も掛け合わされることで、結果的に勾配が0に近づく現象がよく見られます。

(図110)

目次にもどる

STEP1:勾配消失問題の原因と流れ

STEP1-1:勾配消失問題が発生する流れ

簡単なモデルを使って、勾配消失がどのように起こるかを見ていきます。

(図121)住宅ローンを契約するかどうか?のモデル

【学習の流れ】
① 重み”w”、”v”とバイアス”b”、”c”に初期値を設定
(図122)


② 入力⇒出力の方向に値が伝播
(図123)


③ 正解値”t”と出力”y”の差から「誤差を計算」
(図124)


④ 誤差”E”を「出力層⇒隠れ層」の方向に逆伝播して重み”v”を更新
(図125)

更新式の例(v1):

v1 = v1 - η * (∂E/∂v1)

これは「v1の変化が誤差Eにどれだけ影響を与えるか?」を表しています。
たとえば、”Acceptability”が最終判断に80%貢献する場合、v1はその割合に近づくように調整されます。


⑤ 次に「隠れ層⇒入力層」の方向に誤差を逆伝播し、w11を更新
(図126)

更新式の例(w11):

w11 = w11 - η * (∂E/∂w11)
     = w11 - η * (∂E/∂Acceptability) * (∂Acceptability/∂w11)

例えば、(∂E/∂Acceptability)=0.01、(∂Acceptability/∂w11)=0.02 のとき、
勾配値は 0.01 × 0.02 = 0.0002 とさらに小さくなります。
学習率ηが0.01など小さい値だと、入力層に近い層の勾配がほとんど0に近づき、学習が止まります。

STEP1-2:勾配消失が起きる根本原因

上記の流れは「現象としての発生メカニズム」ですが、根本原因は「微小な導関数値を持つ関数を使っている」ことにあります。

例えば、シグモイド関数の導関数は最大でも0.25です。
N層あると、0.25^N という乗算がかかり、勾配は急激に0へ近づきます。

(図131)

目次にもどる

STEP2:サンプルプログラム

以下は、実際に勾配消失問題が起こる様子を確認するPythonコードです。

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.initializers import RandomNormal
from keras.datasets import mnist

# 入力xの次元
M = 784
# 隠れ層h1の次元(クラス数)
J = 128
# 隠れ層h2の次元(クラス数)
K = 10
# エポック数
epoch_num = 10
# ミニバッチのサイズ
mini_batch_size = 128

def multi_layer_perceptron(X_train,t_train,X_test,t_test):

    X,t = X_train,t_train

    ############################################
    # STEP1:モデルの定義
    ############################################
    w_init = RandomNormal(mean=1,stddev=1)
    model = Sequential()
    # 入力層 - 隠れ層の定義
    model.add(Dense(input_dim=M, units=J, kernel_initializer=w_init))
    model.add(Activation('sigmoid'))
    # 隠れ層 - 出力層の定義
    model.add(Dense(units=K, kernel_initializer=w_init))
    model.add(Activation('softmax'))

    ############################################
    # STEP2:誤差関数の定義
    # STEP3:最適化手法の定義(例:確率的勾配降下法)
    ############################################
    model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['accuracy'])

    ############################################
    # STEP4:セッションの初期化
    ############################################
    # ⇒今回は不要
    # (TensorFlow v2以降はSessionを使用しないため)
    ############################################
    # STEP5:学習
    ############################################
    model.fit(X, t, epochs=epoch_num, batch_size=mini_batch_size)

    ############################################
    # STEP6:学習結果の確認
    ############################################
    classes = np.argmax(model.predict(X,batch_size=mini_batch_size),axis=1) 
    prob = model.predict(X,batch_size=mini_batch_size)

    print("*******************************")
    print("classified: ",t==classes)
    print("probability: ",prob)
    print("*******************************")

    ############################################
    # STEP7:学習結果の評価
    ############################################
    X_,t_ = X_test,t_test
    evaluation = model.evaluate(X_,t_)
    print(evaluation)

def main():

    # テストデータを「学習用」と「テスト用」に分ける
    (X_train, T_train), (X_test, T_test) = mnist.load_data()
    X_train = X_train.reshape(X_train.shape[0],28*28)
    X_train = X_train / 255.0
    X_test = X_test.reshape(X_test.shape[0],28*28)
    X_test = X_test / 255.0

    # トレーニング&評価
    multi_layer_perceptron(X_train, T_train, X_test, T_test)
  
if __name__ == "__main__":
    main()

このプログラムを実行すると、Epoch=2以降で誤差が減らなくなり、学習が進んでいないことが確認できます。

(図141)

目次にもどる

STEP3:まとめと学び

勾配消失問題は、深いニューラルネットワークにおける学習の停滞を招く重大な課題です。
特にシグモイドなど微小な導関数を持つ関数を使う場合に起こりやすく、対策として以下が有効です。

  • ReLU関数など勾配が消失しにくい活性化関数を使う
  • バッチ正規化を導入する
  • 残差接続(ResNet構造)を活用する
  • He初期化など適切な重み初期化手法を採用する

こうした工夫により、層が深いモデルでも安定した学習が可能となります。

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Python, 機械学習 (Machine Learning)
-

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

ロジスティック回帰の式変形(多クラス版)のご紹介(ディープラーニング)

  <目次> ロジスティック回帰の式変形(多クラス版)のご紹介(ディープラーニング)  【前提】多クラスロジスティック回帰とは?  【本編】多クラスロジスティック回帰の流れを整理   STE …

Pythonのdatapackage学習中に遭遇したエラー「StopIteration」と「AttributeError」の対応

(0)目次&概説 (1) 記事の目的 (2) エラー1:AttributeError: ‘generator’ object has no attribute ‘n …

ロジスティック回帰をエクセルで計算する方法(ディープラーニング)

<目次> (1) ロジスティック回帰をエクセルで計算する方法(ディープラーニング)  (1-1) 【前提①】ロジスティック回帰とは?  (1-2) 【前提②】解決したい課題  (1-3) ロジスティッ …

no image

AzureのMachine Learning(機械学習)の始め方

  <目次> (1) AzureのMachine Learning(機械学習)の始め方  (1-0) やりたいこと  (1-1) STEP1:(事前準備)ワークスペースの作成  (1-2) …

no image

OpenAIでPDFファイルを要約する方法(サンプルプログラムをご紹介)

  <目次> OpenAIでPDFファイルを要約する方法(サンプルプログラムをご紹介)  やりたいこと/概要  サンプルプログラム  動かし方 OpenAIでPDFファイルを要約する方法(サ …

  • English (United States)
  • 日本語
Top