Coursera Deep Learning専門講座の受講メモ (コース2 - Improving Deep Neural Networks - Week 3)

この記事のまとめ:

コース2:Improving Deep Neural Networksについて

これまでに受講したコース1のNeural Networks and Deep Learningに続き、コース2ではImproving Deep Neural Networksと題して、主に次の内容を3週に渡って学びます。 この週はボリューム満点です。

Week 3の概要

このコースのWeek 3では、下記の4つについて学びます。

  • ハイパーパラメーター調整
  • バッチ正規化
  • 多クラス分類とソフトマックス関数
  • TensorFlowの使い方
ハイパーパラメーター調整

これまでに出てきたハイパーパラメーターを挙げると次ようなものがあります。 括弧内の数値は参考値です。

  • 学習率
  • モメンタム計算用係数 ,
  • RMSprop計算用係数
  • ゼロ割防止定数
  • NN層数
  • 各層のニューロン (ノード)数

これらを調整する際、調整範囲を決めるとは思いますが、その範囲内を一定間隔で試さなず、ランダムに試して、ある程度領域が絞れて来たらその周辺を中心に粒度を細かくしていくとより良い調整になるでしょう。

また、学習率などパラメーターによっては対数スケールでランダムにする必要もありますので注意しましょう。

はゼロ割を防ぐためのパラメーターなのでほかの値に比べて限りなく小さい値を選択すればよいです。

バッチ正規化 (Batch Normalization)

Week 1で入力データセット に対する正規化は説明しましたが、今回はディープニューラルネットワークの各層において正規化を行います。 正規化の対象は活性化関数の入力 です。

手順としては、各層で次の2つの手順を行います。この手順はミニバッチ処理のときも同じです。

  1. を平均0、分散1のデータセット に変換する
  1. を学習パラメーター でスケーリングされたデータセットに に変換する

は重み やバイアス と同様に学習を行うパラメーターであり、ハイパーパラメーターではありません。 と同様に勾配降下法によって学習します。また、モメンタムやRMSprop、Adam最適化のような最適化も同様に行います。

ミニバッチ処理を行う場合は、 を全体の学習データセットサイズではなく、ミニバッチサイズとして扱えばよいです。

ミニバッチ処理の場合にテストデータセットでテストを行う際には、 学習時に各層における平均 と分散 をミニバッチ処理ごとに指数移動平均を使ってそれぞれ計算しておき、すべての学習データセット終了時の を使えばよいです。

多クラス分類とソフトマックス関数 (Softmax activation function)

これまでは二項分類問題しか扱ってきませんでしたが、ここでは多クラス分類問題を扱います。ソフトマックス関数は多クラス分類を行う際に使う活性化関数です。

クラス分類数を としたとき、ソフトマックス関数は次のように表します。

多クラス分類においての損失関数も二項分類のときからわずかに変わります。

損失関数は次のように表します。

これを交差エントロピー (Cross Entropy) と呼びます。

なお、コスト関数は次の通りです。

TensorFlowについて
深層学習用フレームワーク

この講座ではスクラッチでPythonやNumpyライブラリを使って実装します。これは深層学習の理解のために非常に良いことですが、これからは深層学習のフレームワークを使ってより簡単に実装することを覚えていきます。幸いなことに深層学習用のフレームワークはたくさんあります。

フレームワークを選択する際、重要な点として述べられていることは下記の通りです。

  • プログラミングが簡単で事であること
  • 実行速度
  • 真にオープンであること
TensorFlowの使い方

ここではWeek 3のPythonでのプログラミング課題で使われるTensorFlowの関数類について簡単に説明していきます。

※ただし、私自身調べながら書いているので間違いがあるかもしれません。

まずTensorFlowの構文を覚える前に、TensorFlowの概念について理解しておいた方がよいと思います。

TensorFlowは、Graph、Tensor、Operation、Sessionという概念が存在します。かなり独特な概念ですので、下記の記事は私的には参考になりました。

グラフの定義

ここでは、Week 3で使用するニューラルネットワークのグラフを定義するために使用する構文をいくつか見てきます。なお、ニューラルネットワークのグラフの定義方法はプログラミング課題を見ればわかるため、説明は省略します。

まずはライブラリを読み込みます。もちろんライブラリのインストールをしなければなりませんがここでは省略します。

import tensorflow as tf

TensolFlowで使うすべての定数や変数はTensorFlowのクラスとして定義する必要があります。定数定義の方法は次の通りです。

C = tf.constant({値}, name='{変数名}')

なぜ変数名を定義しなければならないかは名前空間概念を理解する必要があります。 下記の通り記事によると次のように指摘されています。

Neural Networkも層があまり多くないMLP(Multi-Layer Perceptron)等では,名前管理は困りませんが,深いCNNや,RNNで見られる大きなモデルに対しては,重み共有もありますので,きちんとした変数スコープが必要となります.また,スケールアップを考えると(私自信はほとんど経験ありませんが)Multi-Device(GPU),クラスタといった分散環境にコードを適用させなければなりません.ここでも変数スコープが必要となります.

はじめのうちはあまり気にしなくてもよいかもしれませんが、上記のようなDeep Learningを行う予定があるのであれば理解しておいて損はないかと思います。

次に、変数定義は次のように行います。

tf.Variable({式や変数}, dtype={変数型}, name='{変数名}')

tf.Variableはクラスであり、このオブジェクトを作る方法はもう一つあり、tf.get_variableを使う方法です。tf.get_variableは既存の変数を取得するか、新しい変数を作成することができます。また、tf.get_variableではイニシャライザーを使うこともでき、次の例ではXavier初期化や、ゼロ初期化を行っています。

W1 = tf.get_variable("W1", [25,12288], initializer = tf.contrib.layers.xavier_initializer(seed = 1))
 
b1 = tf.get_variable("b1", [25,1], initializer = tf.zeros_initializer())

また、TensorFlowにはPlaceholderというものもあり、後からデータセット等を入力する際に使用するデータ領域の確保する際に使用します。

tf.placeholder(tf.{変数型}, {行列の場合のみ行列のサイズ}, {name = '{変数名}')

また、Placeholderを使う際、行列のサイズが決まっていない場合、Noneを使用することができます。例えば、学習データセット数など場合によって変更があるようなものに対して、Noneを使うことがあります。

四則演算の定義は次のように行います。

tf.add(a, b)
tf.subtract(a, b)
tf.multify(a, b)  # 要素ごとの掛け算
tf.divide(a, b) # 要素ごとの割り算

よく利用する行列演算は次の通りです。

tf.matmul(a, b) # 内積
tf.transpose(a) # 転置

よく利用する活性化関数は次の通りです。

tf.nn.relu(a)
tf.sigmoid(a)
tf.nn.softmax(a)

シグモイド関数でのロジスティクス回帰の損失関数とソフトマックス関数での多クラス分類の損失関数は次のように定義ができます。なお、logitslabelsはそれぞれシグモイド関数、ソフトマックス関数に対するそれぞれの前段までのニューラルネットワークを経たデータセット (学習データセットそのものではない)と教師データセットです。また、入力する行列の形は、(学習データセット数 、分類クラス数 )ですので注意が必要です。

# Loss function of sigmoid
tf.nn.sigmoid_cross_entropy_with_logits(logits = logits,  labels = labels)
 
# Loss function of softmax
tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels)

コスト関数の算出はすべての学習セットに渡って損失関数を平均化すればよいですが、平均化する関数としてtf.reduce_mean()関数があります。これを使って、シグモイド関数、ソフトマックス関数のコスト関数を表すと次の通りになります。

# Cost function of sigmoid
cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = logits, labels = labels))
 
# Cost function of softmax
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels))

最後に最適化手法を定義します。これまで学んできた、勾配降下法、モメンタム法、RMSprop、Adam法は次のように定義できます。

# Gradient descent
optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate).minimize(cost)
 
# Momentum
optimizer = tf.train.MomentumOptimizer(learning_rate = learning_rate, momentum = beta).minimize(cost)
 
# RMSprop
optimizer = tf.train.RMSPropOptimizer(learning_rate = learning_rate).minimize(cost)
 
# Adam
optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)

なお、モメンタム法の実装は公式ドキュメントを見るとWeek 2で習ったものと若干異なるようです。

セッションでのグラフの実行

セッションという所以は、TensorFlowはクライアントとなるPythonプログラムからC++ランタイムを呼びだして実行しており、tf.SessionクラスがクライアントとなるPythonプログラムとC++ランタイムの間のコネクションを提供することからきています。このオブジェクトは、ローカルマシンだけでなく、リモートデバイスへのコネクションも提供できます。

グラフを実行する前に、tf.Variableのオブジェクトを使う場合には初期化が必要です。オブジェクトの初期化は次の通りです。

init = tf.global_variables_initializer()
sess = tf.sesson()
sess.run(init)

引き続いて、グラフの実行は下記の通りで実行できます。feed_dictの引数は、placeholderで準備した変数に対して、入力を実行時に与えるものですので、下記の例ではニューラルネットワークの学習データセットと教師データセットを入力しています。

_ , minibatch_cost = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})
この週でTensorFlowについて覚えておくこと
  • Tensorflowは深層学習用のプログラミングフレームワーク
  • 二つのメインオブジェクトクラス TensorOperator がある
  • TensorFlowでコードを書くとき、次のステップで書く必要がある:
    • Tensor (Variables, Placeholders …) と Operator ((tf.matmul, tf.add, …)) を含んだグラフを作成する
    • Session を作成する
    • Session を初期化する
    • Graph を実行させるために Session を実行する
  • Graph は何度も実行可能
  • "optimizer"オブジェクトと一緒にセッションを実行することで逆伝搬と最適化は自動的に実施される

今回は以上です。 最後まで読んでいただき、ありがとうございます。
関連記事

コメント

このブログの人気の投稿

LinuxでのnVidia GPUのオーバークロック・電力チューニング方法