pytorch의 모델.eval() 및 BN 레이어 사용

코드 보세요~


class ConvNet(nn.module):
    def __init__(self, num_class=10):
        super(ConvNet, self).__init__()
        self.layer1 = nn.Sequential(nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
                                    nn.BatchNorm2d(16),
                                    nn.ReLU(),
                                    nn.MaxPool2d(kernel_size=2, stride=2))
        self.layer2 = nn.Sequential(nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
                                    nn.BatchNorm2d(32),
                                    nn.ReLU(),
                                    nn.MaxPool2d(kernel_size=2, stride=2))
        self.fc = nn.Linear(7*7*32, num_classes)
         
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        print(out.size())
        out = out.reshape(out.size(0), -1)
        out = self.fc(out)
        return out

# Test the model
model.eval()  # eval mode (batchnorm uses moving mean/variance instead of mini-batch mean/variance)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
네트워크 모델 모델에 BN층이 포함되어 있으면 예측할 때 모델을 평가 모델, 즉 모델로 전환해야 한다.eval().
평가 시뮬레이션에서 BN층의 균일치와 방차는 전체 훈련집의 균일치와 방차, 즉 moving mean/variance이다.
훈련 모드에서 BN층의 균일치와 방차는 미니-batch의 균일치와 방차이므로 특히 주의해야 한다.
보충: Pytorch 모형 훈련 모형과 eval 모형의 차이가 매우 크다(Pytorch train and eval) 부속 해결 방안
pytorch모델이 eval()이라고 쓰였을 때 때때로 표현된 결과는train(True)에 비해 차이가 매우 크다. 이런 차이는 층층이 보면 주로 BN을 사용했기 때문이다. eval에서 사용하는 BN은 고정된runningrate이고 train에서 이 runningrate는 입력에 따라 바뀐다.

해결 방안은 동결bn


def freeze_bn(m):
    if isinstance(m, nn.BatchNorm2d):
        m.eval()
model.apply(freeze_bn)
이렇게 하면 안정적인 출력의 결과를 얻을 수 있다.
이상의 개인적인 경험으로 여러분께 참고가 되었으면 좋겠습니다. 또한 많은 응원 부탁드립니다.

좋은 웹페이지 즐겨찾기