Skip to main content

PyTorchのDropoutによる正則化入門

コードチュートリアルとインタラクティブな可視化付きで、PyTorchモデルをDropoutで正則化する方法を学びましょう
Created on August 11|Last edited on August 11
このチュートリアルでは、PyTorchモデルにDropoutによる正則化を追加する例を示し、Weights & Biasesでモデルを追跡しながら、Dropoutが性能に与える影響を観察します。
Dropoutに馴染みがない方のために、その役割を簡単に説明します。すでに知っている方は、次に進んでください。
Jump to the tutorial


このチュートリアルで扱う内容



機械学習におけるDropoutによる正則化とは何ですか?

Dropoutによる正則化は、ニューラルネットワーク内のユニットを一時的に無効化(「ドロップアウト」)して、多数のアーキテクチャを同時に訓練しているかのような効果を得る機械学習手法です。特に、訓練中の過学習のリスクを大幅に低減できる点が重要です。

過学習は、ニューラルネットワークが訓練データに含まれるノイズや個別のパターンまで過度に学習してしまい、未見データでの性能が低下する現象です。Dropoutは訓練中にランダム性を導入することでこれに対処します。各訓練反復でニューロンの一部をランダムに「ドロップアウト(0に設定)」することで、ネットワークが特定のニューロンや特徴量に過度に依存するのを防ぎます。これにより、より分散的で堅牢な表現を学習するよう促します。
これはニューロン同士の共適応(ニューロンが互いに協調しすぎて特化し、汎化を妨げる現象)も緩和します。Dropoutの概念は、Hinton らによる 2012 年の論文で提案されました。特徴検出器の共適応を防いでニューラルネットワークを改良する以来、深層学習の定番手法となり、モデルの汎化能力を高めることでこの分野に大きな影響を与えてきました。

この Colab で PyTorch の Dropout の例を実行する →

概要torch.nn.Dropout

PyTorchでは、ドロップアウトを実装するために便利なtorch.nn.Dropout クラスです。このクラスは訓練中に入力テンソルの要素をランダムにゼロにし、実質的にニューロンを「ドロップアウト」します。主要なパラメータは次のとおりです。p要素をゼロにする確率を定義するパラメータであり、そしてinplaceこれは処理をインプレースで実行するかどうかを決定します。
そのpパラメータ(一般にドロップアウト率と呼ばれる)は、各訓練ステップでランダムに無効化されるニューロンの割合を制御します。値が高いほど、より多くのニューロンが無効化されます。p値が大きいほど多くのニューロンが無効化され、正則化が強まります。一般的な設定値はp0.2〜0.5の範囲が一般的ですが、最適な値はネットワークやデータセットによって異なります。
そのinplaceパラメータは、設定するとTrueは、入力テンソルを直接変更してメモリを節約します。ただし、インプレース演算は柔軟性に欠ける場合があり、すべての状況に適しているとは限らない点に注意が必要です。
ここでは、インスタンス化して使用する方法を示す簡単なコード例を紹介します。nn.Dropout

PyTorchモデルへのDropoutの追加方法

PyTorchモデルにDropoutによる正則化を追加するための手順を、シンプルに順を追って説明します。

1. PyTorchモデルにDropoutを追加する方法

PyTorchモデルにDropoutを追加する方法は、とても簡単です。torch.nn.Dropoutクラスで、ニュー��ンが無効化される確率であるドロップアウト率をパラメータとして受け取ります。
self.dropout = nn.Dropout(0.25)
出力層以外の任意の層の後にDropoutを適用できます。

2. Dropoutがモデル性能に与える影響を観察する

ドロップアウトの効果を観察するには、モデルを訓練して次のタスクを実行させます。画像分類まずは正則化なしのネットワークを訓練し、その後に Dropout で正則化したネットワークを訓練します。どちらのモデルも CIFAR-10 データセットで各15エポック学習します。

PyTorchモデルにDropoutを追加する完全な例:

class Net(nn.Module):
def __init__(self, input_shape=(3,32,32)):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 32, 3)
self.conv2 = nn.Conv2d(32, 64, 3)
self.conv3 = nn.Conv2d(64, 128, 3)
self.pool = nn.MaxPool2d(2,2)

n_size = self._get_conv_output(input_shape)
self.fc1 = nn.Linear(n_size, 512)
self.fc2 = nn.Linear(512, 10)

# Define proportion or neurons to dropout
self.dropout = nn.Dropout(0.25)
def forward(self, x):
x = self._forward_features(x)
x = x.view(x.size(0), -1)
x = self.dropout(x)
x = F.relu(self.fc1(x))
# Apply dropout
x = self.dropout(x)
x = self.fc2(x)
return x
を使用することでwandb.log()訓練用の関数内で、モデルの性能を自動的に追跡できます。参照してくださいドキュメント詳細についてはこちらをご覧ください。
def train(model, device, train_loader, optimizer, criterion, epoch, steps_per_epoch=20):

# Log gradients and model parameters
wandb.watch(model)

# loop over the data iterator, and feed the inputs to the network and adjust the weights.
for batch_idx, (data, target) in enumerate(train_loader, start=0):
# ...
acc = round((train_correct / train_total) * 100, 2)
# Log metrics to visualize performance
wandb.log({'Train Loss': train_loss/train_total, 'Train Accuracy': acc})



Run set
0


PyTorchにおけるDropout正則化の効果

「Dropoutによる正則化の効果は何だろう?」と思うかもしれません。導入すると、次のような変化が見られます。
  • 正則化を行っていないネットワークは訓練データにすぐ過学習します。検証損失がどのように推移するかに注目してください。without-dropout数エポックのうちに損失が大きく発散しており、これが汎化誤差の増大につながっています。
  • ドロップアウト率(p)を25%に設定したドロップアウト層を2層挿入して訓練すると、モデルの過学習を抑えられます。ただし、その分訓練精度は低下するため、正則化したネットワークはより長く訓練する必要があります。
  • Dropoutによりモデルの汎化が向上します。訓練精度は正則化なしのネットワークより低いものの、全体として検証精度は改善しています。これは汎化誤差の低減を示しています。
以上で、PyTorchのモデルでDropoutを使うための短いチュートリアルは終了です。

自分で試せるDropoutのColabはこちら →

Weights & Biases を試す

Weights & Biases は、機械学習実験の管理を支援します。実行ごとのハイパーパラメータや出力メトリクスを記録し、結果を可視化・比較して、見つかった知見を同僚と素早く共有できます。
Replitで手早く2つの実験を実行し、Weights & Biases(W&B)が作業の整理にどう役立つか確認するには、以下の手順に従ってください。
手順
  1. 下の緑色の「Run」ボタンをクリックしてください(初回に Run をクリックすると、Replit がマシンを割り当てるまで約30〜45秒かかります)
  2. ターミナルウィンドウの指示に従って進めてください(以下の右下ペイン)
  3. ターミナルウィンドウのサイズを変更できます(右下)をクリックすると拡大表示できます




ニューラルネットワークでDropoutを適用すべき場所

ニューラルネットワークにおけるDropout層の配置は、その効果を左右する重要な要素です。Dropoutはさまざまな箇所に適用できますが、一般的には隠れ層の活性化関数の後に置かれ、場合によっては入力層にも用いられます。戦略的な配置はモデルの性能に大きく影響します。
活性化関数の後にDropoutを適用する活性化関数隠れ層に配置するのは一般的な手法です。これにより、その層内のニューロン同士の共適応を抑え、過学習を防ぐのに役立ちます。ただし、最適な配置はアーキテクチャやタスクによって異なる場合があります。
例えば、より深いネットワークでは、前段の層におけるDropoutの方が有効な場合があります。入力層にDropoutを適用すると、任意の単一の入力特徴量に依存しないようモデルを促し、より頑健で分散した表現を学習させるため、特徴選択の観点で有用です。ただし、入力層のDropoutを過度に強くするとアンダーフィッティングを招く点には注意が必要です。
Dropout をどこに適用するかの判断は、多くの場合経験的であり、対象タスクに最適な構成を見つけるために実験が必要になります。

発展的なDropoutの手法と考慮事項

標準的なDropoutは有効ですが、さらに性能を高めるための高度な手法や考慮点もあります。たとえば、適応的なドロップアウト率や各種のDropout派生手法などです。
適応的なドロップアウト率は、訓練中のモデルの性能に基づいてドロップアウト率を動的に調整する手法です。これにより正則化の強さをきめ細かく制御でき、モデルの汎化能力を高められます。さらに、変分ドロップアウトのような他の派生手法では、ニューロンをランダムに無効化するためのより洗練された仕組みを導入します。特に複雑なモデルでは、これらの手法が標準的なDropoutより良い性能につながる場合があります。 層ごとに適切なドロップアウト率(p)を選ぶことも非常に重要です。タスクに応じて最適な構成を見つけるため、各層で異なるドロップアウト率を試行するのが有益なことが多いでしょう。

まとめ

Dropoutは、ニューラルネットワークの過学習を防ぐうえで重要な役割を果たす強力かつ汎用的な正則化手法です。訓練中にランダムにニューロンを無効化することで、より頑健で汎化しやすい特徴の学習を促します。次では、その使い方を理解しtorch.nn.DropoutPyTorchでDropoutを効果的に用いることは、高性能なディープラーニングモデルを構築するうえで不可欠です。