深いモデルでの正則化、勾配クリッピング、およびバイアス初期化操作

最近、コードをデバッグしたところ、どのようにデバッグするにしても、いくつかの最適化方法を使用することを考えました。その後、これらの最適化方法の具体的な詳細を知らなかったので、少し勉強したので、ここに記録します。今後の参考に。

正則化

一般的に使用される正則化方法

L1 正則化

L1 正則化は L1 ノルムに基づく正則化手法であり、その数式は次のとおりです。

L = L データ + λ ∑ i = 1 n ∣ wi ∣ L = L_{data} + \lambda \sum_{i=1}^n |w_i|L=Lダタ_ _ _+i = 1w私は

ここで、L データ L_{data}Lダタ_ _ _データ損失です、wi w_iw私ははモデルパラメータλ \lambdaλは正則化パラメータです。L1 正則化の役割は、モデル パラメーターの絶対値を罰して、一部のパラメーターが 0 になるようにして、特徴選択の効果を実現し、モデルの複雑さを軽減することです。

L2 正則化

L2 正則化は、L2 ノルムに基づく正則化手法であり、その数式は次のとおりです。

L = L データ + λ ∑ i = 1 nwi 2 L = L_{data} + \lambda \sum_{i=1}^n w_i^2L=Lダタ_ _ _+i = 1w2

ここで、L データ L_{data}Lダタ_ _ _データ損失です、wi w_iw私ははモデルパラメータλ \lambdaλは正則化パラメータです。L2 正則化の役割は、モデル パラメーターの二乗和を罰し、モデルの重み分布をより滑らかにし、モデルの複雑さを軽減し、過剰適合を回避することです。

ドロップアウトの正則化

ドロップアウト正則化はランダム非アクティブ化正則化手法であり、その数式は次のとおりです。

y = 1 1 − p × x × my = \frac{1}{1-p} \times x \times my=1p1×バツ×メートル

ここでpppはノードを保持する確率、xxxは入力、mmmは 2 値化されたマスクで、どのノードが保持され、どのノードがランダムに非アクティブ化されるかを示します。ドロップアウト正則化の機能は、いくつかのノードをランダムに破棄することにより、モデル内の共適応を減らし、過剰適合を回避することです。

データ増強

データ拡張はデータ拡張に基づく正則化手法であり、その数式は次のとおりです。

xaug = f ( x ) x_{aug} = f(x)バツうぐ_=f ( x )

ここでxxxは元のデータ、fffはデータ拡張関数、xaug x_{aug}バツうぐ_強化されたデータの場合。データ拡張では、モデルの汎化能力を向上させ、過剰適合を防ぐために、ランダムにトリミング、回転、反転、スケーリングなどを行うことでデータセットを拡張できます。

カーネル最大ノルム正則化

https://github.com/kevinzakka/pytorch-goodies#max-norm-constraint

特徴検出器の同時適応を防止することでニューラルネットワークを改善

カーネル最大ノルム正則化は、過学習の程度を制御するために、ニューラル ネットワーク内の各畳み込みカーネルの重み値の最大ノルムを制限できる、一般的に使用される正則化方法です。

カーネルの最大ノルム正則化はトレーニング中にのみ有効であるため、モデルをコンパイルするときに対応するパラメーターを設定する必要があります。テストまたは予測するときに、この正則化方法を使用する必要はありません。

隠れユニットの重みベクトルの L2 ノルムLLの場合L は特定の最大値ccc、重みベクトルにc / L c/Lc / L重みベクトルの更新直後、またはXXXグラデーションの更新。

この制約は、正則化の別の形式です。L2 は損失関数を使用して高い重みにペナルティを与えますが、「最大ノルム」は重みに直接作用します。L2 は重みをゼロに近づけるよう一定の圧力をかけますが、損失関数が重みをゼロから遠く離れたままにするインセンティブを提供しない場合、有用な情報が捨てられる可能性があります。一方、「最大ノルム」では重みがゼロ近くになることはありません。ノルムが制約値より小さい限り、制約は効果がありません。

最初の実装方法:

def max_norm(model, max_val=3, eps=1e-8):
    for name, param in model.named_parameters():
        if 'bias' not in name:
            norm = param.norm(2, dim=0, keepdim=True)
            desired = torch.clamp(norm, 0, max_val)
            param = param * (desired / (eps + norm))

2 番目の実装方法:

class Conv2dWithConstraint(nn.Conv2d):
    def __init__(self, *args, doWeightNorm = True, max_norm=1, **kwargs):
        self.max_norm = max_norm
        self.doWeightNorm = doWeightNorm
        super(Conv2dWithConstraint, self).__init__(*args, **kwargs)

    def forward(self, x):
        if self.doWeightNorm: 
            self.weight.data = torch.renorm(
                self.weight.data, p=2, dim=0, maxnorm=self.max_norm
            )
        return super(Conv2dWithConstraint, self).forward(x)

class Conv1dWithConstraint(nn.Conv1d):
    def __init__(self, *args, doWeightNorm = True, max_norm=1, **kwargs):
        self.max_norm = max_norm
        self.doWeightNorm = doWeightNorm
        super(Conv1dWithConstraint, self).__init__(*args, **kwargs)

    def forward(self, x):
        if self.doWeightNorm: 
            self.weight.data = torch.renorm(
                self.weight.data, p=2, dim=0, maxnorm=self.max_norm
            )
        return super(Conv1dWithConstraint, self).forward(x)


class LinearWithConstraint(nn.Linear):
    def __init__(self, *args, doWeightNorm = True, max_norm=1, **kwargs):
        self.max_norm = max_norm
        self.doWeightNorm = doWeightNorm
        super(LinearWithConstraint, self).__init__(*args, **kwargs)

    def forward(self, x):
        if self.doWeightNorm: 
            self.weight.data = torch.renorm(
                self.weight.data, p=2, dim=0, maxnorm=self.max_norm
            )
        return super(LinearWithConstraint, self).forward(x)

過学習を防ぐ効果を得るために損失に L1 および L2 正則化を追加する原理は何ですか?

損失関数に正則化項を追加することは、過学習を防ぐ一般的な方法です。基本原理は、对模型参数进行约束モデルがトレーニング データに過剰適合するのを避けるために、 によってモデルの複雑さを軽減することです。

具体的には、正則化用語には通常、L1 正則化と L2 正則化という 2 つの形式があります。L1 正則化はモデル パラメータの絶対値を正則化項として使用し、L2 正則化はモデル パラメータの 2 乗を正則化項として使用します。在损失函数中加入正则化项后,优化器在训练模型时不仅需要最小化损失函数的输出值,还需要最小化正则化项的输出值,从而使得模型参数尽量接近于0

正則化項を追加する効果は、モデル パラメーターの値が大きくなりすぎるのを防ぎ、それによってモデルがトレーニング データに過剰適合するのを避けることですこれは、モデルのパラメーターが大きすぎると、モデルがトレーニング データに過剰適合し、テスト データに一般化できなくなるためです。正則化項の制約により、モデル パラメーターの値がより狭い範囲内で制御され、モデルがより一般化可能になります。

正則化項の制約強度は正則化パラメータによって制御されることに注意してください。つまり、正則化パラメータが大きいほど、モデル パラメータの値は 0 に近づきますただし、正則化パラメータが大きすぎるとモデルの適合が不十分になる可能性があるため、特定の状況に応じて適切な正則化パラメータを選択する必要があります。

L1 正則化と L2 正則化の違いは何ですか

L1 正則化は、重みパラメータの L1 ノルムに制約を課すことによって実現されます。具体的には、L1 正則化では、重みパラメータの各要素の絶対値を加算し、正則化係数 λ を乗じて正則化項を求め、これを目的関数に加算します。通过L1正则化可以使得部分权重参数变成0,从而实现特征选择的效果,即去除对模型影响较小的特征

L2 正則化は、重みパラメータの L2 ノルムに制約を課すことによって実現されます。具体的には、L2 正則化では、重みパラメータの各要素の 2 乗を加算し、正則化係数 λ を乗じて正則化項を求め、これを目的関数に加算します。通过L2正则化可以使得权重参数的值变得更加平滑,从而减少模型的复杂度,提高模型的泛化性能

正則化係数 λ の値はモデルにどのような影響を与えますか?

  1. 正則化係数 λ が小さい場合、モデルの適合能力が強くなり、トレーニング データをより適切に適合させることができますが、過適合の問題が発生し、テスト データに対するモデルのパフォーマンスが低下する可能性があります。
  2. 正則化係数 λ が大きい場合、モデルのフィッティング能力は弱いため、オーバーフィッティングの問題は回避できますが、アンダーフィッティングの問題が発生し、トレーニング データに対するモデルのパフォーマンスが低下する可能性があります。

正則化係数 λ の最適な値を決定する方法

正則化係数 λ の最適な値を決定することは、深層学習における一般的な問題です。この問題を解決するには、さまざまな方法があります。一般的に使用されるいくつかの方法を次に示します。

グリッド検索

グリッド検索は、最適な正則化係数 λ を見つけるために使用できる、シンプルですが効果的な方法です。具体的には、候補となる正則化係数 λ のセットを最初に定義し、次にこれらの値の間で徹底的な検索を実行し、最後に検証セットでモデルが最高のパフォーマンスを発揮する正則化係数 λ が選択されます。

ランダム検索

ランダム検索は、最適な正則化係数 λ を見つけるために使用できる、より効率的な方法です。具体的には、まず正則化係数のセットの値の分布 λ を定義し、次にこれらの分布でランダムにサンプリングし、最後に検証セットでモデルのパフォーマンスを最高にする正則化係数 λ を選択します。

相互検証

相互検証は、モデルの一般化パフォーマンスを評価し、最適な正則化係数 λ を選択するために使用できる一般的な方法です。具体的には、データセットをトレーニングセットと検証セットに分割し、トレーニングセットでモデルをトレーニングし、検証セットを使用して最適な正則化係数 λ を選択し、最後にテストセットを使用してモデルの汎化パフォーマンスを評価します。 。

重みの適応的正則化

正則化による適応学習率は、重みパラメータと正則化係数 λ を同時に最適化する効果的な方法です。具体的には、重みパラメータが正則化係数 λ とともに最適化されるように、損失関数にペナルティ項を追加できます。この方法では、正則化係数 λ の値を自動的に調整して、より良い汎化パフォーマンスを得ることができます。

L2 正則化をモデルに追加する方法

以下は、PyTorch を使用して単純な深層学習フレームワークを定義し、L2 正則化を追加するサンプル コードです。

import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(784, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = x.view(-1, 784)
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 创建模型实例
model = Net()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.01)

# 训练模型
for epoch in range(10):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        # 梯度清零
        optimizer.zero_grad()

        # 前向传播
        outputs = model(inputs)

        # 计算损失
        loss = criterion(outputs, labels)

        # 反向传播
        loss.backward()

        # 更新参数
        optimizer.step()

        running_loss += loss.item()

    print('Epoch %d, loss: %.3f' % (epoch + 1, running_loss / len(trainloader)))

オプティマイザでweight_decayパラメータを設定すると、オプティマイザは勾配更新に正則化項を自動的に追加し、L2正則化を実現します。

pytorchの最適化関数のweight_decayパラメータはネットワーク内のすべてのパラメータを正規化しますか?

PyTorch では、オプティマイザーのweight_decay パラメーターを使用して、L2 正則化 (重み減衰とも呼ばれます) の強度を制御します。Weight_decay パラメータが設定されている場合、オプティマイザはパラメータが更新されるたびにすべてのパラメータに対して L2 正則化を実行します。つまり、各パラメータの更新値に 1 未満の係数を乗算します。この係数は、weight_decay パラメータの値になります。 。したがって、weight_decay パラメータはネットワーク内のすべてのパラメータを正規化します。

Weight_decay パラメータはオプティマイザごとに異なる意味を持つことに注意してください。SGD や Adam などのオプティマイザでは、weight_decay パラメータによってL2 正則化の強度が制御され、RMSprop などのオプティマイザでは、weight_decay パラメータによってL2 正則化の係数が制御されます。したがって、異なるオプティマイザーを使用する場合、より良い汎化パフォーマンスを得るには、特定の状況に応じてweight_decayパラメーターの値を調整する必要があります。さらに、一部のオプティマイザーは、AdamW オプティマイザーや LAMB オプティマイザーなどの他の正則化メソッドも提供しており、これらのオプティマイザーを使用するときに正則化の効果をさらに制御できます。

SGD や Adam などのオプティマイザーと RMSprop などのオプティマイザーでのweight_decay パラメーターの意味の違いは何ですか?

SGD や Adam などのオプティマイザでは、通常、weight_decay パラメータを使用して L2 正則化の強度を制御します。具体的には、weight_decay参数会在每次参数更新时对参数值进行衰减,从而使得权重参数尽量分散,防止过拟合SGD および Adam では、weight_decay パラメーターは、損失関数に L2 正則化項を追加することと同じです。つまり、重みの二乗和に重み減衰係数を乗算し、それによって重みパラメーターのノルムを制約します。

RMSprop などのオプティマイザでは、weight_decay パラメータの意味は異なり、L2 正則化の係数を制御するために使用されます。具体的には、weight_decay参数会在计算梯度平方的移动平均值时,对其进行加权衰减,从而使得梯度的范数尽量分散,防止过拟合RMSprop では、weight_decay パラメーターは、勾配の上に L2 正則化項を追加することと同等です。つまり、重みの二乗和に重み減衰係数を乗算し、それによって重みパラメーターのノルムを制約します。

Adam 最適化アルゴリズムと AdamW 最適化アルゴリズムの違いは何ですか

Adam 最適化アルゴリズムの重み減衰は、L2 正則化に基づいて実装されます。つまり、重みパラメーターには、パラメーターが更新されるたびに重み減衰係数が乗算されます。ただし、この方法では、重みパラメータの更新がより大きな制約を受けることになります特别是在学习率较小时,可能会导致模型的收敛速度减慢

この問題を解決するために、AdamW 最適化アルゴリズムは新しい重み減衰法を提案します。AdamW では、重み減衰は、L2 正則化と重み減衰の重み付き合計に基づいて実装されます。つまり、パラメーターが更新されるたびに、重みパラメーターに L2 正則化係数と重み減衰係数の重み付き合計が乗算されます。このようにして機能します缓解权重参数更新受到较大约束的问题,同时还可以防止过拟合

重み減衰の処理が異なることを除けば、AdamW と Adam は他の点では基本的に同じです。これらはすべて適応学習率に基づく最適化アルゴリズムであり、さまざまなモデルやデータセットに合わせて学習率を自動的に調整できます。さらに、どちらも疎勾配や非定常目的関数などの問題を処理できます。

アプリケーションの観点から見ると、Adam 最適化アルゴリズムは、深層学習のほとんどのタスク、特に多くのパラメーターを持つモデルに適しており、 Adam のパフォーマンスは通常、SGD などの基本的な最適化アルゴリズムよりも優れています。AdamW 最適化アルゴリズムは、特に学習率が小さい場合に、重み減衰の問題を処理するのにより適しており、AdamW は重みパラメータの更新をより適切に制御できるため、モデルの汎化パフォーマンスが向上します。したがって、重みの減衰が必要なタスクでは、AdamW を使用するとパフォーマンスが向上します。

モデルの特定の層に正則化項を追加する方法

以下は、PyTorch でレイヤーの正則化を実装する方法を示すコード例です。

import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.lin1 = nn.Linear(10, 10)
        self.lin2 = nn.Linear(10, 5)
    
    def forward(self, x):
        x = self.lin1(x)
        x = nn.functional.relu(x)
        x = self.lin2(x)
        return x

model = MyModel()

# 定义正则化项的权重
weight_decay = 0.01

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
for epoch in range(10):
    running_loss = 0.0
    for i in range(100):
        # 获取数据和标签
        inputs = torch.randn(10)
        labels = torch.randint(0, 5, (1,)).long()
        
        # 清空梯度
        optimizer.zero_grad()
        
        # 前向传播和计算损失
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        # 计算正则化项
        reg_loss = 0.0
        for name, param in model.named_parameters():
            if 'weight' in name:
                reg_loss += torch.norm(param, p=2)**2
                
        # 总损失为交叉熵损失加上正则化项
        total_loss = loss + weight_decay * reg_loss
        
        # 反向传播和计算梯度
        total_loss.backward()
        
        # 更新参数
        optimizer.step()
        
        running_loss += loss.item()
    
    print("Epoch %d, loss: %.3f" % (epoch+1, running_loss/100))

上記のコードでは、最初に、完全に接続された 2 つのレイヤーを含む MyModel という単純なモデルを定義します。次に、正則化項の重みweight_decayを定義します。トレーニング プロセス中に総損失を計算する際、クロスエントロピー損失と正則化項の積を総損失に追加して、特定の層の正則化を実現します。

モデルやタスクが異なると、最適な正則化項のタイプと重みが異なる場合があることに注意してください。通常、モデルのパフォーマンスを向上させるために、さまざまな正則化方法と重み値を試すことで、適切な正則化戦略を見つけることができます。

モデルにclip_grad_norm_を追加します

以下は、モデルのトレーニング中に torch.nn.utils.clip_grad_norm_() 関数を使用して勾配をクリップする方法を示す、PyTorch フレームワークを使用したコード例です。

import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.lin1 = nn.Linear(10, 10)
        self.lin2 = nn.Linear(10, 5)
    
    def forward(self, x):
        x = self.lin1(x)
        x = nn.functional.relu(x)
        x = self.lin2(x)
        return x

model = MyModel()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
for epoch in range(10):
    running_loss = 0.0
    for i in range(100):
        # 获取数据和标签
        inputs = torch.randn(10)
        labels = torch.randint(0, 5, (1,)).long()
        
        # 清空梯度
        optimizer.zero_grad()
        
        # 前向传播和计算损失
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        # 反向传播和计算梯度
        loss.backward()
        
        # 对梯度进行裁剪
        nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
        
        # 更新参数
        optimizer.step()
        
        running_loss += loss.item()
    
    print("Epoch %d, loss: %.3f" % (epoch+1, running_loss/100))

上記のコードでは、最初に、完全に接続された 2 つのレイヤーを含む MyModel という単純なモデルを定義します。次に、損失関数とオプティマイザーを定義し、モデルのトレーニングを開始します。データの各ミニバッチの逆伝播プロセス中に、nn.utils.clip_grad_norm_() 関数を使用してモデルの勾配をクリップし、勾配爆発の問題を回避します。この後、オプティマイザーの step() 関数を呼び出して、モデルのパラメーターを更新します。

モデルやタスクが異なると、最適な勾配クリッピングしきい値が異なる場合があることに注意してください。通常、モデルのパフォーマンスを向上させるために、しきい値のサイズを調整することで適切なクリッピング範囲を見つけることができます。

正則化と勾配クリッピングの役割、違い、およびそれらはどのような状況で使用されるのか

正則化と勾配クリッピングは一般的に使用されるモデル最適化手法であり、その機能はモデルの過剰適合や勾配爆発の問題を回避することです。どちらのテクノロジーも同様の目的を果たしますが、実装および使用される状況は若干異なります。

正則化の役割は、損失関数のモデル パラメーターに制約を追加することで、モデルの過学習の問題を回避することです一般的な正則化方法には、L1 正則化、L2 正則化などが含まれます。実装プロセスでは、モデルの制約を実現するために、損失関数に正則化項目 (重みのノルムなど) を追加して、モデル パラメーターのサイズにペナルティを課すことができます。正則化は通常、モデルの汎化誤差を減らすためにモデルのトレーニング中に適用されます。

勾配クリッピングの機能は、モデルの勾配を制限することによって勾配爆発の問題を回避することですモデルの勾配が大きすぎる場合、勾配をクリップすることで勾配を適切な範囲に制限することができ、それによってモデル パラメーターの過度の更新を回避できます。勾配クリッピングは通常、モデルに対する勾配爆発の影響を回避するために、オプティマイザーの逆伝播プロセスで適用されます。

違い:

  1. 正則化はモデル パラメーターを制限することですが、勾配クリッピングは勾配を制限することです。
  2. 正則化によりモデルの過学習を回避でき、勾配クリッピングにより勾配の爆発を回避できます。
  3. 正則化は通常、モデルのトレーニング中に適用され、勾配クリッピングは通常、オプティマイザーの逆伝播中に適用されます。

使用するシーン:

  1. 正則化は通常、モデルが過学習しているときに適用されます。モデルがトレーニング セットでは良好なパフォーマンスを発揮するが、テスト セットでは良好なパフォーマンスを発揮しない場合は、正則化手法の使用を試みることができます。
  2. 勾配クリッピングは、通常、モデルに勾配爆発がある状況に適用できます。モデルの勾配が大きすぎる場合、モデル パラメーターの更新が激しすぎて、モデルのパフォーマンスに影響を与える場合、勾配クリッピングを使用してみることができます。クリッピングテクニック。

畳み込み層のバイアスを0に初期化します。

ほとんどの深層学習フレームワークでは、畳み込み層のバイアス初期化パラメーターを 0 に設定することでこれを実現できます。以下は、Python と PyTorch フレームワークを使用したコード例です。

import torch.nn as nn

# 定义卷积层(具体参数可以根据实际情况进行修改)
conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1, bias=True)

# 将卷积层的偏置初始化为0
conv_layer.bias.data.fill_(0.0)

上記のコードでは、まず PyTorch フレームワークを使用して畳み込み層 conv_layer を定義し、bias=True パラメーターを通じて層にバイアスが含まれる必要があることを指定します。次に、conv_layer.bias.data.fill_(0.0) によって畳み込み層のバイアスを 0 に初期化します。

おすすめ

転載: blog.csdn.net/qq_41990294/article/details/130240722