Ausführliche Erklärung der Batch-Normalisierung und des Pytorch-Experiments

Die Batch-Normalisierung wurde vom Google-Team im 2015 erschienenen Paper „ Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift “ vorgeschlagen. Dieses Verfahren kann die Konvergenz des Netzwerks beschleunigen und die Genauigkeit verbessern. Obwohl es viele verwandte Artikel im Internet gibt, werden sie im Grunde genommen auf die Formeln in den Zeitungen gesetzt und allgemein darüber gesprochen, und wie bn wirklich funktioniert, wird selten erwähnt. Dieser Artikel ist hauptsächlich in die folgenden Teile unterteilt:

(1) Das BN-Prinzip

(2) Verwenden Sie pytorch, um die Ansichten dieses Artikels zu überprüfen

(3) Punkte, die bei der Verwendung von BN zu beachten sind (BN ist eine Grube, wenn es nicht gut verwendet wird)

1. Prinzip der Stapelnormalisierung

Im Prozess der Bildvorverarbeitung standardisieren wir normalerweise das Bild, was die Konvergenz des Netzwerks beschleunigen kann.Wie in der Abbildung unten gezeigt, ist die Eingabe für Conv1 eine Merkmalsmatrix, die eine bestimmte Verteilung erfüllt, aber für Conv2 die Eingabemerkmal Eine Karte erfüllt nicht unbedingt ein bestimmtes Verteilungsgesetz ( beachten Sie, dass die Erfüllung eines bestimmten Verteilungsgesetzes hier nicht bedeutet, dass die Daten einer bestimmten Merkmalskarte dem Verteilungsgesetz genügen müssen, sondern theoretisch bedeutet, dass die Daten der Merkmalskarte entsprechen der gesamte Trainingsstichprobensatz muss das Verteilungsgesetz erfüllen. Verteilungsgesetz ). Der Zweck unserer Batch-Normalisierung besteht darin, dass unsere Feature-Map das Verteilungsgesetz mit einem Mittelwert von 0 und einer Varianz von 1 erfüllt.

Sie sollten immer noch verwirrt sein, wenn Sie dies sehen, keine Panik, trinken Sie Wasser und nehmen Sie sich Zeit. Das Folgende sind die Originalwörter, die aus dem Originalpapier abgefangen wurden, achten Sie auf den gelb markierten Teil:

„Für eine Eingabe x mit d Dimensionen werden wir jede Dimension davon normalisieren.“ Angenommen, unsere Eingabe x ist ein Farbbild mit drei RGB-Kanälen, dann sind d hier die Kanäle des Eingabebilds, dh d=3, x=(x^{(1)}, x^{(2)}, x^{(3)}), was x^{(1)}stellt die Merkmalsmatrix dar, die unserem R-Kanal entspricht, und so weiter. Die Normalisierungsverarbeitung besteht darin , unseren R-Kanal, G-Kanal und B-Kanal separat zu verarbeiten. Die obige Formel muss nicht gelesen werden, der Originaltext enthält eine detailliertere Berechnungsformel:

Wir haben gerade gesagt , dass die Merkmalskarte ein bestimmtes Verteilungsgesetz erfüllen sollte.Theoretisch bedeutet dies, dass die Daten der Merkmalskarte, die dem gesamten Trainingsbeispielsatz entsprechen, das Verteilungsgesetz erfüllen sollten , dh die Merkmalskarte des Ganzen Der Trainingssatz sollte berechnet und dann standardisiert werden. Bei einem großen Datensatz ist dies offensichtlich unmöglich, daher spricht das Papier von Batch-Normalisierung, das heißt, wir berechnen die Merkmalskarte von Batch-Daten und normalisieren sie dann (je größer der Batch, desto Je näher an der Verteilung des gesamten Datensatzes, desto besser der Effekt). Gemäß der Formel in der obigen Abbildung können wir wissen, dass sie \mu_{\ss}den Mittelwert jeder Dimension (Kanal) der von uns berechneten Merkmalskarte darstellt. Beachten Sie \mu_{\ss}, dass ein Vektor kein Wert ist \mu_{\ss}und jedes Element des Vektors den Mittelwert darstellt einer Dimension (Kanal). \sigma_{\ss}^{2}Stellt die Varianz jeder Dimension (Kanal) der von uns berechneten Feature-Map dar. Beachten Sie \sigma_{\ss}^{2}, dass ein Vektor kein Wert ist . \sigma_{\ss}^{2}Jedes Element des Vektors stellt die Varianz einer Dimension (Kanal) dar und berechnet dann den nach der Normalisierung erhaltenen Wert gemäß \mu_{\ss}und . \sigma_{\ss}^{2}Die folgende Abbildung zeigt ein Beispiel für die Berechnung von Mittelwert \mu_{\ss}und Varianz \sigma_{\ss}^{2}:

Die obige Abbildung zeigt den Berechnungsprozess der Stapelnormalisierung mit einer Stapelgröße von 2 (zwei Bilder). Es wird angenommen, dass Merkmal1 und Merkmal2 Merkmalsmatrizen sind, die von Bild1 und Bild2 nach einer Reihe von Faltungs-Pooling erhalten werden, und der Kanal von Merkmal 2 ist Stellen Sie dann x^{(1)}die Daten von Kanal1 aller Merkmale des Stapels dar und x^{^{(2)}}stellen Sie in ähnlicher Weise die Daten von Kanal2 aller Merkmale des Stapels dar. Berechnen Sie dann jeweils den Mittelwert und die Varianz der Summe, x^{(1)}um x^{^{(2)}}unsere \mu_{\ss}Summe \sigma_{\ss}^{2}zweier Vektoren zu erhalten. Berechnen Sie dann den Wert jedes Kanals separat\ epsilon gemäß der Berechnungsformel für die Standardabweichung (die Formel in der Formel ist eine kleine Konstante, um zu verhindern, dass der Nenner Null ist). Beim Training des Netzwerks trainieren wir einen Stapel von Daten, aber normalerweise geben wir ein Bild für die Vorhersage in den Vorhersageprozess ein. Zu diesem Zeitpunkt ist die Stapelgröße 1. Wenn die obige Methode zur Berechnung von Mittelwert und Varianz verwendet wird sind bedeutungslos. Daher müssen wir den Mittelwert und die Varianz jedes Stapels während des Trainingsprozesses kontinuierlich berechnen und die Methode des gleitenden Durchschnitts verwenden, um den statistischen Mittelwert und die Varianz aufzuzeichnen. Nach dem Training können wir den statistischen Mittelwert und die Varianz approximieren. Es ist gleich dem Mittelwert und Varianz des gesamten Trainingssatzes . Dann verwenden wir während unseres Validierungs- und Vorhersageprozesses den statistischen Mittelwert und die Varianz für die Normalisierung .

\GammaAufmerksame Schüler werden feststellen, dass es in der ursprünglichen Papierformel zwei Parameter gibt \Beta? Ja, es \Gammawird verwendet, um die Varianz der numerischen Verteilung anzupassen, und es \Betawird verwendet, um die Position des numerischen Mittels anzupassen. Diese beiden Parameter werden während der Backpropagation gelernt, \Gammader Standardwert ist 1 und \Betader Standardwert ist 0.

2. Experimentieren Sie mit Pytorch

Glaubst du, du verstehst alles? nicht unbedingt. Ich sagte nur, dass in unserem Trainingsprozess der Mittelwert \mu_{\ss}und die Varianz \sigma_{\ss}^{2}erhalten werden, indem der aktuelle Datenstapel als \mu _{jetzt}Summe berechnet wird \sigma _{jetzt}^{2}, und der Mittelwert und die Varianz, die in unserem Validierungs- und Vorhersageprozess verwendet werden, eine Statistik sind und als \mu _{Statistik}Summe aufgezeichnet werden \sigma _{Statistik}^{2}. \mu _{Statistik}Die spezifische Aktualisierungsstrategie von sum \sigma _{Statistik}^{2}lautet wie folgt, wobei das Momentum standardmäßig 0,1 annimmt:

\large \mu _{Statistik+1}=(1-Impuls)*\mu _{Statistik}+Impuls*\mu _{jetzt}

\large \sigma _{Statistik+1}^{2}=(1-Impuls)*\sigma _{Statistik}^{2}+Impuls*\sigma _{jetzt}^{2}

Hierbei ist zu beachten, dass die Gesamtstandardabweichung bei der bn-Verarbeitung des aktuellen Satzes von Merkmalen in Pytorch verwendet wird \large \sigma _{jetzt}^{2}und die Berechnungsformel wie folgt lautet:

\bg_white \large \sigma _{jetzt}^{2}=\frac{1}{m}\sum_{i=1}^{m}(x_{i}-\mu _{jetzt})^{2 }

Beim Aktualisieren von Statistiken \large \sigma _{Statistik}^{2}wird die Standardabweichung\large \sigma _{jetzt}^{2} der Stichprobe verwendet , und die Berechnungsformel lautet wie folgt:

\bg_white \large \sigma _{jetzt}^{2}=\frac{1}{m-1}\sum_{i=1}^{m}(x_{i}-\mu _{jetzt})^ {2}

Das Folgende ist der Test, den ich mit Pytorch durchgeführt habe. Der Code lautet wie folgt:

(1) Die bn_process-Funktion ist eine benutzerdefinierte bn-Verarbeitungsmethode, um zu überprüfen, ob das Ergebnis mit der offiziellen bn-Verarbeitungsmethode übereinstimmt. Berechnen Sie den Mittelwert und die Standardabweichung jeder Dimension der Eingabestapeldaten (die Dimension hier ist die Kanaldimension) in bn_process (die Standardabweichung ist gleich der Quadratwurzel der Varianz) und normalisieren Sie dann jede Dimension des Features durch die den berechneten Mittelwert und die Gesamtstandardabweichung und verwenden Sie dann den Mittelwert und die Standardabweichung der Stichprobe, um den statistischen Mittelwert und die Standardabweichung zu aktualisieren.

(2) Der anfängliche statistische Mittelwert ist ein Vektor mit 0 Elementen, und die Anzahl der Elemente ist gleich der Kanaltiefe; die anfängliche statistische Varianz ist ein Vektor mit 1 Elementen, und die Anzahl der Elemente ist gleich der Kanaltiefe, Initialisierung \Gamma= 1, \Beta= 0.

import numpy as np
import torch.nn as nn
import torch


def bn_process(feature, mean, var):
    feature_shape = feature.shape
    for i in range(feature_shape[1]):
        # [batch, channel, height, width]
        feature_t = feature[:, i, :, :]
        mean_t = feature_t.mean()
        # 总体标准差
        std_t1 = feature_t.std()
        # 样本标准差
        std_t2 = feature_t.std(ddof=1)

        # bn process
        # 这里记得加上eps和pytorch保持一致
        feature[:, i, :, :] = (feature[:, i, :, :] - mean_t) / np.sqrt(std_t1 ** 2 + 1e-5)
        # update calculating mean and var
        mean[i] = mean[i] * 0.9 + mean_t * 0.1
        var[i] = var[i] * 0.9 + (std_t2 ** 2) * 0.1
    print(feature)


# 随机生成一个batch为2,channel为2,height=width=2的特征向量
# [batch, channel, height, width]
feature1 = torch.randn(2, 2, 2, 2)
# 初始化统计均值和方差
calculate_mean = [0.0, 0.0]
calculate_var = [1.0, 1.0]
# print(feature1.numpy())

# 注意要使用copy()深拷贝
bn_process(feature1.numpy().copy(), calculate_mean, calculate_var)

bn = nn.BatchNorm2d(2, eps=1e-5)
output = bn(feature1)
print(output)

Zuerst setze ich am Ende einen Haltepunkt zum Debuggen und überprüfe den statistischen Mittelwert und die Varianz, die ich erhalten habe, nachdem die offizielle bn das Feature verarbeitet hat. Wir können feststellen, dass running_mean und running_var der offiziellen bn genau die gleichen sind wie die von uns berechneten compute_mean und compute_var (nur die Genauigkeit ist unterschiedlich).

Dann drucken wir die Ausgabe der benutzerdefinierten bn_process-Funktion und die Ausgabe des offiziellen bn-Prozesses aus, offensichtlich sind die Ergebnisse dieselben (nur die Genauigkeit ist unterschiedlich):

3. Probleme, die bei der Verwendung von BN beachtet werden müssen

(1) Setzen Sie den Trainingsparameter während des Trainings auf True und setzen Sie den Trainingsparameter während der Validierung auf False. In Pytorch kann es durch die Methoden model.train() und model.eval() zum Erstellen eines Modells gesteuert werden.

(2) Die Stapelgröße sollte so groß wie möglich eingestellt werden, und die Leistung kann sehr schlecht sein, nachdem die Einstellung klein ist. Je größer die Einstellung, desto näher sind der Mittelwert und die Varianz des gesamten Trainingssatzes an dem Mittelwert und der Varianz des gesamten Trainingssatz.

(3) Es wird empfohlen, die bn-Schicht zwischen der Faltungsschicht (Conv) und der Aktivierungsschicht (wie Relu) zu platzieren, und die Faltungsschicht sollte keine Vorspannung verwenden, da dies nutzlos ist, siehe folgende Abbildung zur Begründung , auch wenn Bias Bias verwendet wird Das Ergebnis ist das gleiche\bg_white \large y_{i}^{b}=y_{i}

Abschließend folgt die Videoerklärung von Herrn Li Hongyi zur Stapelnormalisierung:

Li Hongyi Deep Learning (2017)_bilibili_bilibili

Ich denke du magst

Origin blog.csdn.net/qq_37541097/article/details/104434557#comments_20942083
Empfohlen
Rangfolge