ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학습, 검증곡선과 편향-분산 트레이드오프(Bias-Variance Tradeoff)
    Programming & Machine Learning/풀어쓰는 머신러닝 2017. 8. 11. 02:57

    본 포스팅을 읽기 전에, 교차검증이 무엇인지에 대해 모르는 분들은 이곳을 참고해주시길 바랍니다.




    학습, 검증곡선과 편향-분산 트레이드오프

    편향-분산 트레이드오프 (Bias-Variance Tradeoff)

    머신 러닝에서의 error는 크게 두 분류로 나뉜다.
    bias(편향), 그리고 variance(분산)이다.
    
    bias는 흔히 생각할 수 있는 error로, 선형 회귀같은 문제에서의 SSE를 떠올리면 쉽다.
    모델이 학습데이터를 충분히 설명할 수 없는 상황에서 커지는 에러이다. 
    이 상황을 흔히 underfitting이라고 한다.
    
    variance는 그 반대로 모델이 학습데이터를 과도하게 잘 설명하는 상황이다.
    모집단을 추정하고자 표본집단을 이용하여 모델을 만들어놨더니, 표본집단만을 거창하게 잘 설명하는 모델이 된 것이다.
    머신러닝을 공부하는 사람이라면 한 번 쯤 들어본, overfitting의 상황이다.
    
    variance에 대해 수학적으로 조금 더 직관적으로 얘기하자면, 
    Training Score와 Cross Validation의 차이가 심해지는 상황이 variance가 증가하는 상황이다.
    아래의 그림을 보면 매우 쉽게 알 수 있다. 
    빨간 곡선은 cross validation error이고, training error가 녹색 곡선이다.
    학습이 진행됨에 따라 오버피팅이 되기 때문에 트레이닝 스코어는 계속해서 증가하는 경향을 보이지만,
    교차검증값은 점점 악화된다. 모델이 일반화 성능을 잘 보여주는 영역에서 벗어나고 있는 상황이다.
    
    (참고 - 트레이닝 스코어 : 학습데이터로 모델을 테스트했을때의 스코어, 
    교차검증 스코어 : 모델의 일반적 성능을 추정하기 위해, 테스트셋을 resampling 하는 등의 모델 일반화 검증을 하는 방법에 
    대한 스코어)
    

    일반적인 머신러닝에서는 편향-분산의 관계는 편향이 올라가면 분산은 내려가고, 
    분산이 올라가면 편향이 내려가는 시소 관계에 놓여있다. 이를 편향-분산 트레이드오프라 한다.
    
    흔히 머신러닝에 있어서 중요한 것으로 비용함수를 최적화 하거나 차원을 축소한다거나 하는 이야기를 하기 쉽다.
    하지만 편향-분산 트레이드오프를 잘 맞춰주는 것이 훨씬, 머신러닝의 정말 기본중의 기본이라고 할 수 있겠다.
    
    편향-분산 트레이드오프를 잘 맞춰주기 위해서는 그리드검색등을 이용한 파라미터 튜닝의 좋은 기법등이 있을 수 있겠으나
    역시 기본이 되면서 사람에게 설득력을 갖는 것은 눈으로 보여지는 것이다.
    학습곡선과 검증곡선을 이용하여 바이어스와 분산 문제를 진단하는 것이 여전히 좋은 방법이다.
    sklearn에서는 learning-curve를 아주 쉽게 그려주는 모듈을 제공한다.
    
    이것을 이용하는 것이 전자보다 더 의미가 있다.
    그리드 검색의 하이퍼 파라미터 튜닝, 중첩 교차검증 등의 고급 기법은 학습곡선과 검증곡선을 토대로
    이 문제를 사람의 직관으로 판단하는 요인을 코드로 구현한 것에 지나지 않기 때문이다.
    
    아래의 예제는 학습곡선과 검증곡선으로 편향-분산 트레이드 오프 상황을 핸들링하는 상황을 재현한 것이다.
    예제에서는 편향-분산 트레이드오프가 x축의 값의 증감에 따라 크게 민감하지 않기 때문에,
    데이터 수나 샘플링에 큰 영향을 받지 않고 모델의 성능을 잘 유지하는 좋은 모델이라고 할 수 있다.
    예제와 달리 위의 두번째 그림같은 상황이 된다면 트레이드 오프 상황이 벌어지기 시작하는, 두 곡선이 갈래길로 분기하는
    상황에서 모델의 조건이 가장 좋다고 할 수있는 것이다.
    
    사람의 패턴 인식능력을 십분 활용하는 이런 방식이 개인적으로는 더 좋은 것 같다.
    물론 더욱 고급기법의 경우는 오히려 코드로는 훨씬 쉽다.
    또한 GridSearchCV등의 클래스에 매우 직관적이면서 쉽게 정리가 되어있기 때문에 sklearn의 튜토리얼을 
    한 번 쯤 따라해보는 것만으로도 충분하다.
    
    %matplotlib inline
    import matplotlib.pyplot as plt
    from sklearn.learning_curve import learning_curve
    
    pipe_lr = Pipeline([('scl', StandardScaler()),
                ('clf', LogisticRegression(penalty='l2', random_state=0))])
    
    train_sizes, train_scores, test_scores =\
                    learning_curve(estimator=pipe_lr, 
                    X=X_train, 
                    y=y_train, 
                    train_sizes=np.linspace(0.1, 1.0, 10), 
                    cv=10,
                    n_jobs=1)
    
    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)
    
    plt.plot(train_sizes, train_mean, 
             color='blue', marker='o', 
             markersize=5, label='training accuracy')
    
    plt.fill_between(train_sizes, 
                     train_mean + train_std,
                     train_mean - train_std, 
                     alpha=0.15, color='blue')
    
    plt.plot(train_sizes, test_mean, 
             color='green', linestyle='--', 
             marker='s', markersize=5, 
             label='validation accuracy')
    
    plt.fill_between(train_sizes, 
                     test_mean + test_std,
                     test_mean - test_std, 
                     alpha=0.15, color='green')
    
    plt.grid()
    plt.xlabel('Number of training samples')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')
    plt.ylim([0.8, 1.0])
    plt.tight_layout()
    # plt.savefig('./figures/learning_curve.png', dpi=300)
    plt.show()

    댓글

분노의 분석실 Y.LAB