Notice
Recent Posts
Recent Comments
Link
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
Tags
more
Archives
Today
Total
관리 메뉴

TechY

[간단 정리] model calibration 에 대해 알아보자 (2) 본문

[간단 정리]

[간단 정리] model calibration 에 대해 알아보자 (2)

hskimim 2021. 11. 6. 05:13

지난 1편에 이어, 이번에는 model calibration 에 대한 기법들을 알아보려 한다. model calibration 기법은 크게 두 개로 나뉘어질 수 있다.

 

1. 모델을 학습한 후 (train-set), calibration post-processing 진행 (validate-set)

2. 모델을 학습할 때, calibration method 동시에 학습 (train-set), calibration method 에 대한 hyper-parameter tuning (validate-set)

 

이번에 다뤄보려고 하는 것은, 위의 1번에 해당하는 post-processing 기법이며 특히 sklearn.calibration.CalibratedClassifierCV 모듈에 있는 기법인 'sigmoid' 와 'isotonic' 에 대해 알아본다.

 

참고한 논문Alexandru Niculescu-Mizil and Rich Caruana (2005) Predicting Good Probabilities With Supervised Learning, in Proceedings of the 22nd International Conference on Machine Learning (ICML) 으로 두 기법에 대한 overview 가 매우 잘 이뤄져있다.

 

이 두 방법을 하나씩 이야기하기 전에, 공통적인 것들을 다뤄보자. 해당 방법은 validate dataset 을 사용하며, 모델의 predicted probability 를 입력값으로 하고 class label 을 결과값으로 하는 task 이다. 내가 이해한 데로 해당 task 를 이해해보자면 해당 예시를 쓸 수 있다. 내 친구 중에 뭐든 자신만만하게 하는 친구가 있다고 하자. 그걸 항상 옆에서 들어온 나는, 친구가 "이번에 A 가 B 할 확률이 90% 이상이야!" 라고 하면 옆에서 듣는 나는 '좀 그럴 듯 한가보다..' 이러면서 대략 60%로 조정 (쉽게 말하면 걸러 듣는다.) 할 것이다.

 

다시 돌아와서 보면, post-processing task 는 모델이 학습된 training dataset 이 아닌, validate dataset에서 predicted probability가 well-calibrated 되도록 조정하는 과정을 의미한다. 해당 regression task 는 모델 예측의 방향을 바꾸지 않고, probability 의 순서를 재정렬하지 않기 때문에, accuracy 와 같은 performance 에는 영향을 주지 않는다. 다만, 그 confidence 의 "정도" 만을 바꾸게 된다.

 

이제 하나씩 보면서 이야기를 더 해나가보자

 

1. Sigmoid

깊게 참고한 논문은 (1) (2) 이다.

 

많이 들어본 sigmoid 이다. binary classification 을 할 때, 최종으로 나온 1X1 크기의 logit 을 [0,1] 으로 조정해줄 때, 사용한다. 자연지수 항이 붙어있기 때문에, 값이 커질 수록, 기하급수적으로 큰 확률값의 형태가 반환된다.

 

sigmoid formula

이제 predicted probability 를 validate dataset 에서 볼 수 있는 class label 로 재학습을 시켜야 한다. train dataset 으로 하지 않는 이유는, 애초에 mis-calibration 은 train dataset 에 class label 에 model 의 logit 또는 probability output 이 overfitting 되었기 때문이다. loss function 은 neural network 학습에서 흔히 볼 수 있는 binary cross-entropy 를 사용한다.

binary cross-entropy loss

흥미로운 점은, 단순 이산변수를 class label 로 쓰는 것이 아닌, 확률값의 형태로 약간 smoothing 된 값을 사용하는데, 각 label 별로 opposite label 에 대한 확률을 조금씩 부여해준 것이다. 이는 bias 를 줄이고 일반화를 높여 overfitting 을 방지하겠다는 이유인데, 아래의 식은 positive 와 negative 각각, a=b=1 로 둔 beta distribution 의 평균값을 의미한다. (negative 의 경우 positive 에 따라 나온 식에서 1을 빼줘서 opposite 하게 만들어준 것이다.)

 

(이를 보면서, label smoothing 이 neural network 에 일반화에 큰 기여를 한 것이 bayesian inference 관점에서의 맥락을 지니고 있는 것이 아닐까 라는 생각이 들었다.)

label considered prior

최종적으로 gradient 를 계산해서 back-propagationt 을 통해 sigmoid 에 있는 A,B weight 를 업데이트해주면 된다.

 

아래는 실제 sklearn.calibration에서 sigmoid 에 대한 최적화 소스 코드이다. 처음에 각 class label 을 Bayesian prior 의 형태로 바꿔주고, objective 라는 함수에서 binary cross entropy loss 를 계산하며, grad 에서는 sigmoid 에 있는 A,B에 대한 gradient 를 계산해주어, scipy.optimize.fmin_bfgs 모듈을 통해 최적화하는 것을 볼 수 있다.

predictions = column_or_1d(predictions)
    y = column_or_1d(y)

    F = predictions  # F follows Platt's notations

    # Bayesian priors (see Platt end of section 2.2)
    prior0 = float(np.sum(y <= 0))
    prior1 = y.shape[0] - prior0
    T = np.zeros(y.shape)
    T[y > 0] = (prior1 + 1.0) / (prior1 + 2.0)
    T[y <= 0] = 1.0 / (prior0 + 2.0)
    T1 = 1.0 - T

    def objective(AB):
        # From Platt (beginning of Section 2.2)
        P = expit(-(AB[0] * F + AB[1]))
        loss = -(xlogy(T, P) + xlogy(T1, 1.0 - P))
        if sample_weight is not None:
            return (sample_weight * loss).sum()
        else:
            return loss.sum()

    def grad(AB):
        # gradient of the objective function
        P = expit(-(AB[0] * F + AB[1]))
        TEP_minus_T1P = T - P
        if sample_weight is not None:
            TEP_minus_T1P *= sample_weight
        dA = np.dot(TEP_minus_T1P, F)
        dB = np.sum(TEP_minus_T1P)
        return np.array([dA, dB])

    AB0 = np.array([0.0, log((prior0 + 1.0) / (prior1 + 1.0))])
    AB_ = fmin_bfgs(objective, AB0, fprime=grad, disp=False)
    return AB_[0], AB_[1]

2. Isotonic

Isotonic regression 은 위의 sigmoid 보다 더 간단하며, 더 일반화된 식을 사용한다. 아래의 두 식에서 m을 학습시키는 mean squared 를 최소화하는 linear regression task 이다. 이전의 sigmoid 는 상하방이 [0,1] 로 막혀있고, 지수승이 들어있는 형태였지만, Isotonic 의 경우 선형식이기 때문에, stepwise 한 성질을 띄고 있고, 식이 결과값에 대한 제약이 없기 때문에(상,하방이 뚫려있다..!!), 적은 데이터에 대해 sigmoid 보다 overfitting 이 취약하다고 알려져 있다.

(실제로 sklearn 에서 sigmoid calibration 을 권장하고 있다.)

Isotonic regression 을 푸는 알고리즘 중 하나인 PAV algorithm 이 있다. 이는 위의 식과 같이 선형적인 관계로 만들기 보다, interpolation 을 통해 옆에 있는 값들을 계단식으로 동일하게 맞춰주면서, 근사적인 선형관계를 만들어준다.

PAV algorithm

PAV algorithm 의 일부반 발췌한 소스코드를 보면,  interplation 을 사용하고 있음을 알 수 있다.

    def _build_f(self, X, y):
        """Build the f_ interp1d function."""

        # Handle the out_of_bounds argument by setting bounds_error
        if self.out_of_bounds not in ["raise", "nan", "clip"]:
            raise ValueError(
                "The argument ``out_of_bounds`` must be in "
                "'nan', 'clip', 'raise'; got {0}".format(self.out_of_bounds)
            )

        bounds_error = self.out_of_bounds == "raise"
        if len(y) == 1:
            # single y, constant prediction
            self.f_ = lambda x: y.repeat(x.shape)
        else:
            self.f_ = interpolate.interp1d(
                X, y, kind="linear", bounds_error=bounds_error
            )

 

보다 쉬운 이해를 위해 참고 논문에 첨부된 이미지를 보면, 제일 윗 행이 input 이 되는 predicted probability이며, 순서대로 sigmoid 와 PAV algo 에 따른 isotonic regression에 따른 fitting 결과이다.


sklearn.calibration 모듈에서 지원하는 두 방법론인 "sigmoid"와 "isotonic" 에 대해 알아보았다. 해당 방법론은 현재까지 효율적으로 사용되고 있으며, 그 방법도 간단한 편이다.

 

함께 이야기해본 방법론 중, "sigmoid" 방법론에 대해서 toy data 로 실험을 해보았고, 결과는 아래와 같다. 데이터는 널리 쓰이는 토이 데이터 'diabetes' 이고, 이진 분류 문제이다. 왼쪽의 파란 bar 는 calibration 전이고, 오른쪽은 sigmoid 를 통한, calibration을 하고 난 후이다.

 

logistic regression 을 제외한 나머지 방법론에 있어서 크고 작은 ECE 감소를 확인할 수 있었다. 참고로 SVC 의 경우 원래 logit 을 반환하는 모델이지만, probability=True 옵션을 주면, 내부적으로 sigmoid calibration 을 진행한다고 한다. sigmoid scaling 을 통한 방법론을 Platt 이 제시해서, 본문에는 Platt scaling이라고 명시되어 있다. 이에 따라 (이미 같은 방법론으로 calibration 을 했음), SVC 의 경우 성능 변화가 거의 보이지 않는다.

 

Logistic Regression 의 경우가 가장 흥미로웠는데, logistic regression 은 애초에 log loss 를 사용하여 학습을 시키기 때문에, 자체적으로 well-calibrated 한 모델이며, 이 경우 sigmoid calibration 은 역효과를 낫는 것으로 보인다. 

ECE bar plot


두 번째 포스팅을 위한 방법론을 다루면서 느낀 것은, 이 방법론은 결국 모델의 over/under - confidence 를 고치지 못한다는 점이었다. 즉, 학습한 모델은 결국 스스로 결정에 대한 확신을 제대로 학습하지 못하고, 다른 보조 모델을 따로 두어야 한다는 것인데, 무언가 본질적인 해결책은 아닌 것 같다는 생각이 들었다. model calibration에 대한 연구는 model generalization 과도 긴밀히 연결되기 때문에, 학습 과정에서 well-calibrated 을 지향하는 것이 좀 더 advanced 라고 생각하여 이에 대해 조금 더 알아보려 한다. 

 

또한, 참고한 논문에 따르면, neural network 은 기본적으로 well-calibrated 라고 되어 있는데, 이 논문이 나온 2005년도 기준에서는 deep 한 network 가 없어서 그런 경향이 띄었던 것이고, 최근의 neural network 에서는 over-confidence 와 같은 mis-calibration 이슈가 많이 등장한다. 그 이유는 무엇이고 이를 해결하기 위한 방법론들이 무엇이 있는지 다음 포스팅에서 알아보도록 하겠다.