正則化によるニューラルネットワークの訓練
正則化によるニューラルネットワークの訓練
- NetTrainのValidationSetオプションを使って,検証損失(簡単な分類ネットにおける誤差)によって決定される最適な性能を備えたネットを返す.
- NetTrainのValidationSetオプションと併せてTrainingStoppingCriterionオプションを使い,過学習が起き始めたら訓練を打切る.
- DropoutLayer等の正規化層,あるいはLongShortTermMemoryLayer等の"Dropout"パラメータのような機能を利用する.
解決策を紹介する前に,簡単な例を使ってこの問題を示す.が薄曲線からノイズの多いサンプルを取ることで合成の訓練データ集合を作成する.次に,これらのサンプルでネットを訓練する.ネットは必要以上の「容量」を持っている.つまり,このネットはガウス曲線をフィットするのに必要なものよりずっと複雑な関数をモデル化することができるということである.実際のモデルの形式が分かっているので,過学習が起こったときは見れば分かる.訓練されたネットはもとのデータの「ノイズを学習」するため,ガウシアンとは全く異なる関数を生成するのである.これは,ガウシアンから2つ目の点の集合を抽出し,その値を予測するようにネットを訓練することによって定量化することができる.訓練されたネットは「正規化することができない」.訓練データには適合したフィットであるが,新しいテストデータをうまく近似しない.
data = Table[x -> Exp[-x ^ 2] + RandomVariate[NormalDistribution[0, .15]], {x, -3, 3, .2}];
Length[data]plot = ListPlot[List@@@data, PlotStyle -> Red]net = NetChain[{150, Tanh, 150, Tanh, 1}]results1 = NetTrain[net, data, All, TimeGoal -> 30]results1["RoundLoss"]NetTrainResultsObjectからネットを取得する:
overfitNet = results1["TrainedNet"]Show[Plot[overfitNet[x], {x, -3, 3}], plot]testData = Table[x -> Exp[-x ^ 2] + RandomVariate[NormalDistribution[0, .15]], {x, -3, 3, .2}];
testX = Keys[testData];
testY = Values[testData];meanTestLoss[net_] := SquaredEuclideanDistance[net[testX], testY] / Length[testX];meanTestLoss[overfitNet]
results1["RoundLoss"]Show[Plot[overfitNet[x], {x, -3, 3}], ListPlot[List@@@testData, PlotStyle -> Orange]]オーバーフィットを軽減する最初のアプローチは,2つ目の検証データ(訓練に使われたものではない)に対するネットの性能を測定し,訓練履歴全体から検証周到に対して最も性能がよい特定のネットを選ぶというものである.これは,各ラウンドの終了後に検証データに対するネットを測定するValidationSetオプションを使って実行できる.これらの測定値は2つのことを行う.まず,検証損失曲線(分類が実行されいるときは検証誤差曲線)を生成する.また,最低の「訓練」損失ではなく最低の「検証」損失を持つ中間のネットを選ぶよう,訓練が使用する選択プロセスを変更する.
NetTrainのValidationSetオプションを使って,実際に取得するネットが確実に検定損失を最小化するようにする.オーバーフィットが起こり始める前の訓練の部分が見やすくなるよう,訓練ラウンドを制限する点に注意のこと:
results2 = NetTrain[net, data, All, ValidationSet -> testData, MaxTrainingRounds -> 2000]results2["BestValidationRound"]NetTrainResultsObjectから訓練されたネットを抽出し,それをプロットする.ネットが訓練集合のノイズの特異性を記憶し始める前に,NetTrainが効率的にネットのスナップショットを撮ったため,結果はずっと滑らかになる:
bestPerformingNet = results2["TrainedNet"]Show[Plot[bestPerformingNet[x], {x, -3, 3}], ListPlot[List@@@data, PlotStyle -> Purple]]Min[results2["ValidationLossList"]]meanTestLoss[overfitNet]過学習を軽減するためによく使われる2つ目の方法は,早期打切りである.これは,ネットの何らかの測定値が悪化し始めたときに訓練を打ち切るというものである.この操作はNetTrainのValidationSetオプションと併せてTrainingStoppingCriterionオプションを使うことで実行することができる.これにはValidationSetだけを使う場合よりも有利な点が2つ考えられる.前の例で1300ラウンド余計にネットを訓練した.この場合はネットと訓練データ集合が両方小さいので問題にならなかったが,非常に無駄になる可能性がある,という点が1つである.2つ目は,損失以外の測定値を使って最適なネットを決定した方がよいという点である.
results3 = NetTrain[net, data, All, ValidationSet -> testData, MaxTrainingRounds -> 2000, TrainingProgressMeasurements -> "RSquared", TrainingStoppingCriterion -> <|"Criterion" -> "RSquared", "Patience" -> 20|>]NetTrainResultsObjectの訓練済みのネットを抽出して,前と同じようにそれをプロットする:
earlyStoppingNet = results3["TrainedNet"]Show[Plot[earlyStoppingNet[x], {x, -3, 3}], ListPlot[List@@@data, PlotStyle -> Purple]]results3["ValidationLossList"][[results3["BestValidationRound"]]]meanTestLoss[overfitNet]3つ目のよくある正則化のテクニックは「重み減衰」と呼ばれるものである.このアプローチでは,ネットの重みの大きさが,各バッチ更新の後わずかに減少し,重みがゼロに近付く.これは重みのL2ノルムに当る損失項を加えることとほぼ同じである.
results4 = NetTrain[net, data, All, Method -> {"SGD", "L2Regularization" -> 0.01}]l2Net = results4["TrainedNet"]Show[Plot[l2Net[x], {x, -3, 3}], plot]meanTestLoss[l2Net]meanTestLoss[overfitNet]よく使われる正則化テクニックの4つ目はドロップアウトである.ドロップアウトはネットの隠れ活性化にノイズを導入するが,与えられた層での活性化の全体的な統計量は変化しない.ノイズは非活性化のランダムパターンの形を取る.このとき,入力配列の成分のランダムな集合(通常「ユニット」あるいは「ニューロン」と呼ばれる)がゼロに設定され,残りの成分の大きさが埋め合せのために増大する.基本的な考えは,ドロップアウトはニューロンが,それより下位の層にある特定のニューロンに依存しすぎないようにし,より強力な表現の学習を促進させるというものである.
dropoutNet = NetChain[{150, DropoutLayer[], Tanh, 150, Tanh, 1}]results5 = NetTrain[dropoutNet, data, All]dropoutNet = results5["TrainedNet"]Show[Plot[dropoutNet[x], {x, -3, 3}], plot]meanTestLoss[dropoutNet]meanTestLoss[overfitNet]5つ目の正則化の方法は,バッチ正規化である.これは,データの平均と分散を学習することによって,入力データを正規化するものである.バッチ正規化は多数の便利な特性を持ち,訓練速度を向上させ正則化を提供する.BatchNormalizationLayerは通常,LinearLayerまたはConvolutionLayerとそのアクティベーション関数との間に挿入される.
BatchNormalizationLayerを含む多層パーセプトロンを作成する:
batchNormNet = NetChain[{150, BatchNormalizationLayer[], Tanh, 150, BatchNormalizationLayer[], Tanh, 1}]results6 = NetTrain[batchNormNet, data, All]batchNormNet = results6["TrainedNet"]Show[Plot[batchNormNet[x], {x, -3, 3}], plot]meanTestLoss[batchNormNet]meanTestLoss[overfitNet]関連するガイド
-
▪
- 機械学習 ▪
- ニューラルネットワーク