• Feature Scaling의 효과 (Loss 시각화) 실습

    2022. 7. 29.

    by. 안녕진

    개인 공부 목적의 포스팅입니다. 잘못된 정보가 있다면 댓글 남겨주시면 수정하도록 하겠습니다.
    감사합니다.

     

    💡 주제 설명

    전 게시글에서 살펴봤던 Feature Scaler를 적용하면, 실제로 Loss의 분포가 어떤 식으로 변하는지 확인해본다.

     


    📌 배경

    Feature Scaling을 왜 하는지 두 눈으로 보고 싶다.

     


    🔍 과정   [실습 Github 링크]

    • 시각화 아이디어
    x1 = np.linspace(0, 10, 100)
    x2 = np.linspace(-100, 20, 100)
    x1, x2 = np.meshgrid(x1, x2)
    
    y = 3*x1 + 2*x2

    이렇게 나름(?) 불균형하다고 볼 수 있는 Feature 데이터를 만들고,
    y를 적절히 정의하고 scatter()로 확인해본다.

    fig, ax = plt.subplots(subplot_kw={'projection':'3d'})
    ax.scatter(x1, x2, y, c=y)
    
    plt.show()​
    x1, x2가 불균형할 때와, scaled 됐을 때의 loss 분포를 비교한다.
    x1, x2 각각의 weights인 w1, w2를 축으로 하는 loss가 어떻게 보일지 확인해본다.

    scaling 하지 않은 Feature들을 이용하여 gradient descent를 적용했을 때 비효율적인 형태가 나타난다고 하는데,
    위에 서술한 과정을 통해 실제로 그런지 확인해보자.

     

    • 실습 코드
    Loss의 분포를 보여주는 함수를 아래와 같이 작성했다.
    def showLossDist(ax, x1, x2, wLim=20000):
        w1 = np.linspace(-wLim, wLim, 30)
        w2 = np.linspace(-wLim, wLim, 30)
        ww1, ww2 = np.meshgrid(w1, w2)
        
        min_val = np.inf
        min_coord = [0, 0]
        
        loss = np.zeros_like(ww1)
        for i in range(len(w1)):
            for j in range(len(w2)):
                predict = w1[i]*x1 + w2[j]*x2
                loss_val = np.mean(np.square(y-predict))
                if loss_val < min_val:
                    min_val = loss_val
                    min_coord = [w2[j], w1[i]]
                loss[i][j] = loss_val
                
        ax.contour(ww1, ww2, loss, levels=15)
        ax.plot(min_coord[0], min_coord[1], 'ro')
        ax.annotate('global min', (min_coord[0], min_coord[1]))​

     

    w1, w2값을 조정해가며 최적화(Loss가 가장 작은)된 w1, w2 값을 찾는 것이 이 모델의 학습의 목표이다.
    따라서, w1과 w2의 후보가 될 수 있는 값을 -20000 ~ 20000까지 30개 정도 설정해줬다. (linspace)
    contour를 그리기 위한 ww1, ww2도 만들었다.

    그 아래는, w1과 w2 값들을 각각 적용해보며, loss값을 저장하고 최적해를 찾는 부분이다.
    최적해를 global min이라고 표시해뒀다.

     

    • 함수 사용하여 결과 확인
    2*3의 axes를 만들었고,
    각각의 axes에 Scaler를 바꿔가며 showLossDist를 이용하여 Loss의 분포를 확인하는 코드이다.
    fig, axes = plt.subplots(ncols=2, nrows=3, figsize=(14, 21))
    
    ax = axes[0][0]
    ax.set_title('none')
    showLossDist(ax, x1, x2)
    
    axes[0][1].set_visible(False)
    
    scaler = minMaxScaling
    ax = axes[1][0]
    ax.set_title('minMax')
    showLossDist(ax, scaler(x1), scaler(x2))
    
    scaler = meanNormalization
    ax = axes[1][1]
    ax.set_title('meanNormalization')
    showLossDist(ax, scaler(x1), scaler(x2))
    
    scaler = standardization
    ax = axes[2][0]
    ax.set_title('standardization')
    showLossDist(ax, scaler(x1), scaler(x2))
    
    scaler = scalingToUnitLength
    ax = axes[2][1]
    ax.set_title('scalingToUnitLength')
    showLossDist(ax, scaler(x1), scaler(x2))
    
    # fig.savefig('scaler')​

     

    Scaler는 이전 게시글에서 작성한 그대로 사용했다.

    결과는 아래와 같다.
    Scaling을 하지 않으면 등고선이 매우 불균형한 형태를 띠는 것을 확인할 수 있다.
    Scaler마다 형태는 다르지만, 적용하지 않은 것에 비하면 상당히 균형 잡힌 형태라는 것을 알 수 있다.
    다음 게시글에서는 Feature Scaling이 실제로 Gradient Descent에서 어떻게 작용하는지 확인할 것이다.

     

    'NLP' 카테고리의 다른 글

    감정분석 (naive bayes classifier, 나이브 베이즈 분류기)  (3) 2022.10.02
    cost function of Logistic Regression  (0) 2022.08.11
    Feature scaling의 종류  (0) 2022.07.28
    Simple Linear Regression 실습  (0) 2022.07.27
    [pytorch] DataLoader  (0) 2022.07.27

    댓글