Pytorch 에서 Batch Normalization layer 가 밟 은 구 덩이 를 해결 합 니 다.

1.momentum 의 정의 에 주의
Pytorch 의 BN 층 의 운동량 이 부 드 럽 고 흔히 볼 수 있 는 운동량 계산 방식 은 반대 이 며,기본 momentum=0.1 입 니 다.

BN 계층 의 표현 식 은 다음 과 같 습 니 다.

그 속γ화해시키다β배 울 수 있 는 인자 입 니 다.Pytorch 에서 BN 층 의 클래스 인 자 는 다음 과 같 습 니 다.

CLASS torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
매개 매개 매개 변수 의 구체 적 인 의 미 는 문 서 를 참조 합 니 다.주의해 야 할 것 은 affine 이 BN 층 의 인 자 를 정의 한 것 입 니 다.γ화해시키다β배 울 수 있 는 지 여부(배 울 수 없 는 기본 값 은 상수 1 과 0).
2.BN 층 에 통계 데이터 수치,즉 평균 값 과 분산 이 포함 되 어 있 음 을 주의 하 십시오.
track_running_stats C a boolean value that when set to True, this module tracks the running mean and variance, and when set to False, this module does not track such statistics and always uses batch statistics in both training and eval modes. Default: True
훈련 과정 에서 model.train(),train 과정의 BN 의 통계 수치 인 평균 값 과 방 차 는 현재 batch 데 이 터 를 통 해 추정 된다.
그리고 테스트 시 model.eval()후 trackrunning_stats=True,모델 이 현재 사용 하고 있 는 통계 데 이 터 는 Running status 에 있 는 것 입 니 다.즉,지수 감쇠 규칙 을 통 해 현재 의 수 치 를 축적 하 는 것 입 니 다.그렇지 않 으 면 현재 batch 데이터 에 기반 한 추정 치 를 사용 합 니 다.
3.BN 계층 의 통계 업데이트
모든 훈련 단계 모델.train()후의 forward()방법 에서 자동 으로 이 루어 집 니 다.경사도 계산 과 역방향 전파 에서 optim.step()를 업데이트 하 는 것 이 아 닙 니 다.
4.BN 및 그 통계 동결
위의 분석 을 통 해 알 수 있 듯 이 정확 한 BN 동결 방식 은 모델 훈련 시 BN 을 따로 골 라 서 eval(model.train()이후 트 레이 닝 상 태 를 덮어 쓰 는 것)으로 재 설정 하 는 것 이다.
해결 방안:
You should use apply instead of searching its children, while named_children() doesn't iteratively search submodules.

def set_bn_eval(m):
    classname = m.__class__.__name__
    if classname.find('BatchNorm') != -1:
      m.eval()
model.apply(set_bn_eval)
또는 module 의 train()방법 을 다시 쓰 십시오.

def train(self, mode=True):
        """
        Override the default train() to freeze the BN parameters
        """
        super(MyNet, self).train(mode)
        if self.freeze_bn:
            print("Freezing Mean/Var of BatchNorm2D.")
            if self.freeze_bn_affine:
                print("Freezing Weight/Bias of BatchNorm2D.")
        if self.freeze_bn:
            for m in self.backbone.modules():
                if isinstance(m, nn.BatchNorm2d):
                    m.eval()
                    if self.freeze_bn_affine:
                        m.weight.requires_grad = False
                        m.bias.requires_grad = False
5. Fix/frozen Batch Norm when training may lead to RuntimeError: expected scalar type Half but found Float
해결 방법:

import torch
import torch.nn as nn
from torch.nn import init
from torchvision import models
from torch.autograd import Variable
from apex.fp16_utils import *
def fix_bn(m):
    classname = m.__class__.__name__
    if classname.find('BatchNorm') != -1:
        m.eval()
model = models.resnet50(pretrained=True)
model.cuda()
model = network_to_half(model)
model.train()
model.apply(fix_bn) # fix batchnorm
input = Variable(torch.FloatTensor(8, 3, 224, 224).cuda().half())
output = model(input)
output_mean = torch.mean(output)
output_mean.backward()
Please do

def fix_bn(m):
    classname = m.__class__.__name__
    if classname.find('BatchNorm') != -1:
        m.eval().half()
Reason for this is, for regular training it is better (performance-wise) to use cudnn batch norm, which requires its weights to be in fp32, thus batch norm modules are not converted to half in network_to_half. However, cudnn does not support batchnorm backward in the eval mode , which is what you are doing, and to use pytorch implementation for this, weights have to be of the same type as inputs.
추가:딥 러 닝 요약:pytorch 로 dropout 와 Batch Normalization 을 할 때 주의해 야 할 부분,tensorflow 로 dropout 와 BN 을 할 때 주의해 야 할 부분
pytorch 로 dropout 와 BN 을 만 들 때 주의해 야 할 부분.
pytorch 드 롭 아웃 하기:
바로 train 때 dropout 를 사용 하고 훈련 할 때 dropout 를 사용 하지 않 습 니 다.
pytorch 에 서 는 net.eval()을 통 해 전체 네트워크 파 라 메 터 를 고정 시 킵 니 다.이 는 전방 향 파 라 메 터 를 업데이트 하지 않 고 dropout,BN 파라미터 가 고정 되 지 않 으 며 이론 적 으로 모든 vaidation set 에 net.eval()을 사용 해 야 합 니 다.
net.train()은 경사도 계산 에 포함 시 키 겠 다 고 밝 혔 다.

net_dropped = torch.nn.Sequential(
    torch.nn.Linear(1, N_HIDDEN),
    torch.nn.Dropout(0.5),  # drop 50% of the neuron
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN, N_HIDDEN),
    torch.nn.Dropout(0.5),  # drop 50% of the neuron
    torch.nn.ReLU(),
    torch.nn.Linear(N_HIDDEN, 1),
)
for t in range(500):
    pred_drop = net_dropped(x)
    loss_drop = loss_func(pred_drop, y)
    optimizer_drop.zero_grad()
    loss_drop.backward()
    optimizer_drop.step()
    if t % 10 == 0:
        # change to eval mode in order to fix drop out effect
        net_dropped.eval()  # parameters for dropout differ from train mode
        test_pred_drop = net_dropped(test_x)
        # change back to train mode
        net_dropped.train()
pytorch 배치 Normalization:
net.eval()전체 네트워크 매개 변수 고정,BN 매개 변수 고정,movingmean 과 movingvar,이 걸 모 르 면 다음 그림 을 보 세 요.

            if self.do_bn:
                bn = nn.BatchNorm1d(10, momentum=0.5)
                setattr(self, 'bn%i' % i, bn)   # IMPORTANT set layer to the Module
                self.bns.append(bn)
    for epoch in range(EPOCH):
        print('Epoch: ', epoch)
        for net, l in zip(nets, losses):
            net.eval()              # set eval mode to fix moving_mean and moving_var
            pred, layer_input, pre_act = net(test_x)
            net.train()             # free moving_mean and moving_var
        plot_histogram(*layer_inputs, *pre_acts)  
moving_mean 과 movingvar
在这里插入图片描述
tensorflow 로 dropout 와 BN 을 만 들 때 주의해 야 할 부분.
dropout 와 BN 은 모두 training 의 매개 변 수 를 가지 고 있 습 니 다.train 인지 test 인지 테스트 인지 테스트 를 나타 내 는데 test 의 dropout 는 dropout 가 아니 라 BN 은 BN 의 매개 변 수 를 고정 시 켰 습 니 다.

tf_is_training = tf.placeholder(tf.bool, None)  # to control dropout when training and testing
# dropout net
d1 = tf.layers.dense(tf_x, N_HIDDEN, tf.nn.relu)
d1 = tf.layers.dropout(d1, rate=0.5, training=tf_is_training)   # drop out 50% of inputs
d2 = tf.layers.dense(d1, N_HIDDEN, tf.nn.relu)
d2 = tf.layers.dropout(d2, rate=0.5, training=tf_is_training)   # drop out 50% of inputs
d_out = tf.layers.dense(d2, 1)
for t in range(500):
    sess.run([o_train, d_train], {tf_x: x, tf_y: y, tf_is_training: True})  # train, set is_training=True
    if t % 10 == 0:
        # plotting
        plt.cla()
        o_loss_, d_loss_, o_out_, d_out_ = sess.run(
            [o_loss, d_loss, o_out, d_out], {tf_x: test_x, tf_y: test_y, tf_is_training: False} # test, set is_training=False
        )
# pytorch
    def add_layer(self, x, out_size, ac=None):
        x = tf.layers.dense(x, out_size, kernel_initializer=self.w_init, bias_initializer=B_INIT)
        self.pre_activation.append(x)
        # the momentum plays important rule. the default 0.99 is too high in this case!
        if self.is_bn: x = tf.layers.batch_normalization(x, momentum=0.4, training=tf_is_train)    # when have BN
        out = x if ac is None else ac(x)
        return out
BN 의 training 매개 변수 가 train 일 때 BN 의 매개 변 수 는 변 할 수 있다 는 것 을 의미 할 뿐 BN 이 스스로 moving 을 업데이트 하 는 것 은 아 닙 니 다.mean 과 movingvar,이 동작 은 이전에 업 데 이 트 된 op 이기 때문에 train 을 하기 전에 moving 를 확보 해 야 합 니 다.mean 과 movingvar 업데이트,moving 업데이트mean 과 movingvar 의 조작 은 tf.GraphKeys.UPDATEOPS

 # !! IMPORTANT !! the moving_mean and moving_variance need to be updated,
        # pass the update_ops with control_dependencies to the train_op
        update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        with tf.control_dependencies(update_ops):
            self.train = tf.train.AdamOptimizer(LR).minimize(self.loss)
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기