ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Multiclass Classification | Advanced Learning Algorithm
    Machine Learning/Stanford ML Specialization 2024. 3. 24. 16:08

    Coursera Machine Learning Specialization > Supervised Machine Learning: Advanced Learning Algorithms > Neural Network Intuition

     

    Multiclass

    Multiclass Classification은 분류 문제 중, 여러가지의 Class를 판별하는 문제이다. Logistic Regression을 이용해서 y가 0이거나 1인 확률을 계산하고, threash hold값을 이용해서(예: 0.5) 판별해내는 모델을 배웠었다. 하지만 그 가지수가 2개 이상이라면? 여러 포켓몬이 있다고 가정해보자. 그러면 그래프상으로 각 결과값마다 결정 경계(Decision Boundry)가 생기고, 그 경계선을 갖고 여러가지의 class라도 추론을 해낼 수 있다.

     

    datascience.stackexchange.com

     

     

    Softmax

    Logistic Regression을 이용하면 2가지의 아웃풋을 낼 수 있다. 1이 될 propability(확률)을 계산해서, 그 값이 1일지 아닐지 추론하게 되고, 만약 그 값이 0.71이라면, 1일 확률이 크다. (물론 이것은 threash hold값에 따라 달라질 수 있다.) 그렇다면 1일 확률이 0.71일 때, 0일 확률은? 0.29가 된다.

     

    그러면 Softmax Regression을 살펴보자. 각 값은 아래와 같이 계산해낼 수 있고, 각 값은 각 클래스가 될 수 있는 확률을 계산하는 각 노드의 z값을 나타낸다. 

     

    z1 = w1⋅x + b1
    z2 = w2⋅x + b2
    z3 = w3⋅x + b3
    z4 = w4⋅x + b4

     

    이후 sigmoid를 이용해서 계산을 하게되면, 

    e^z1
    e^z2
    e^z3
    e^z4

    이렇게 네 값이 나오게 된다. 그러면, 최종적으로 클래스 1일 확률은 어떻게 구할 수 있을까?

     

    a1 = e^z1 / (e^z1 + e^z2 + e^z3 + e^z4)

     

    이렇게 계산할 수 있다. a2, a3, a4 모두 마찬가지이다. 아래와 같은 값을 가졌을 때, a4의 값은 얼마일까?

    a1 = 0.30
    a2 = 0.20
    a3 = 0.15

     

    모두 합쳐 1이 되야하므로, 0.35가 된다. 즉, 이것을 수식으로 표현하면 아래와 같다.

    Apple Developer

     

    조금 복잡해보이지만, 위에서 계산한대로, 각각의 z값을 w⋅x + b 형식으로 구한 후, sigmoid 함수를 이용해서 e^xi (또는 e^zi)값을 구하고, 클래스 갯수별로 나온 모든 값을 합한것으로 현재값을 나눠주면, 0에서 1 사이의 숫자가 나오게 된다. 이 말은, 모든 클래스의 Propability를 합치게 되면 항상 1이 되게 된다. 참고로 YouTube의 Neural Network에서도 이런 Softmax 방식을 사용해서 가장 deman가 높을 것 같은 비디오를 추천하게 된다고 Research에서 설명하고 있다.

     

    Logistic Regression에서는, 아래와 같은 loss function을 사용했다.

    loss = -ylog(a1) - (1 - y)log(1 - a1)

     

    그렇다면, Softmax Regression에서는 어떤 loss function을 사용할까?

    loss = -log(aj) // if y = j

    바로 다음과 같다. 

     

    이렇게 Softmax와 loss function을 사용하면, Neural Network에서 Multiclass Classification 모델을 생성할 수 있게 된다.

     

     

    Neural Network with Softmax Output

    이제, 마지막 Output Layer가 1개가 아닌 여러개인 Neural Network를 생각해보자. 예를 들어, 숫자가 0-9중 하나로 추측하는 함수를 생각해야한다고 해보자. 그러면 Output Layer에는 10개의 뉴런이 있어야하고, Softmax Output을 갖고 있어야한다.

     

     

    그 전의 레이어는 ReLU 함수를 이용해 값을 추론했다고 생각하면 된다. 즉, 각 레이어마다. z1부터 z10까지 계산하게 된다.

    z1 = w1⋅a^[2] + b1
    ...
    z10 = w10⋅a^[2] + b10

     

    그리고 나면 각 class별로 확률을 아래와 같이 계산할 수 있다.

    a1 
    = e^z1 / (e^z1 + ... e^z10)
    = P(y = 1|x)
    
    ...
    
    a10 
    = e^z1 / (e^z1 + ... e^z10)
    = P(y = 10|x)

     

    이렇게 Softmax 계층(Output Layer)는 각 출력 레이블 중 하나가 될 확률에 대한 추정치를 제공한다. 

     

    Tensor Flow

    이제 이것을 TensorFlow를 이용해서 계산해보자. 먼저 모델을 정의해보자. 위에서 만든 예시처럼, hidden layers에는 25, 15개의 뉴런들이 있고, 마지막 output layers에는 softmax 활성화 함수를 이용해서 최종 10개의 아웃풋이 생성된다.

    import tensorflow as tf
    from tensorflow.keras import Sequential
    from tensorflow.keras.layers import Dense
    
    model = Sequential([
        Dense(units=25, activation='relu'),
        Dense(units=15, activation='relu'),
        Dense(units=10, activation='softmax')
    ])

     

    이제, loss function을 이용해서 모델을 컴파일 하고, 트레이닝 데이터를 집어 넣어 모델을 만들 수 있다.

    from tensorflow.keras.losses import SparseCategoricalCrossentropy
    model.compile(loss=SparseCategoricalCrossentropy())
    model.fit(X, Y, epochs=100)

     

    사실, 이 코드는, 예시로 쓴것이지만, 이보다 훨씬 효율적인 방법이 존재한다.

     

    Improved Implementation of Softmax

    Numerical Roundoff Errors라는게 존재한다. 컴퓨터는 연산을 할 때, 지정된 공간을 갖고 연산을 하는데, 특히 소수점을 계산할 때, 오차가 발생한다. 예를 들면 아래와 같다.

    x1 = 2.0 / 10000
    print(x1)

    이런 수식에서는 아래와 같이 정상적인 값이 출력된다.

    0.0002

     

     

    하지만 이런 경우는?

    x2 = 1 + (1/10000) - (1 - 1/10000)
    print(x2)
    0.00019999999999997797

     

    아주 미세하지만 반올림 오차가 발생한것을 보여준다. 컴퓨터에는 이 숫자를 저장하는 메모리가 한정적이어서, 이러한 반올림 오차가 발생한다. Softmax를 계산할 때 발생하는 이러한 오차또한 개선해야지 이러한 오차를 최소한으로 줄일 수 있다.

     

    Logistic Regression을 계산할 때, 아래와 같은 방법으로 모델을 구연하고 loss function을 계산하게 된다.

    a = g(z) = 1 / 1+ e^-z // Logistic Regression
    loss = -ylog(a) - (1 - y)log(1 - a) // Original Los

     

    Loss Function을 더 정확하게 표현하면 아래와 같다.

    loss = -y(log(1 / 1+ e^-z) - (1 - y)log(1 - (1 / 1+ e^-z))

     

    원래 코드를 살펴보자.

    model = Sequential([
        Dense(units=25, activation='relu'),
        Dense(units=15, activation='relu'),
        Dense(units=10, activation='sigmoid')
    ])
    
    model.compile(loss=BinaryCrossEntropy())

     

    여기서, 코드를 다음과 같이 변형해서, Numerical Roundoff Error을 방지할 수 있다.

    model = Sequential([
        Dense(units=25, activation='relu'),
        Dense(units=15, activation='relu'),
        Dense(units=10, activation='linear')
    ])
    
    model.compile(loss=BinaryCrossEntropy(from_logits=True))

    이렇게 함으로써, 마지막 계층이 Linear Activation Function을 사용하도록 설정하게 하고, -z에 대한 Activation Function을 Crosee Entropy loss function의 사양에 넣어버리는 것이다. 여기서 logit은 z 값을 의미한다. 이렇게 하면 Tensorflow는 값을 조금 더 정확하게 계산할 수 있다고 한다.

     

    이제 이 아이디어를 Softmax에 적용해보자. 원래의 코드는 다음과 같았다.

    model = Sequential([
        Dense(units=25, activation='relu'),
        Dense(units=15, activation='relu'),
        Dense(units=10, activation='softmax')
    ])
    
    model.compile(loss=SparseCategoricalCrossEntropy())

    하지만, 위와 같이, Numerical Roundoff Error를 최소화 하기 위해, 아래와 같이 변경할 수 있다.

    model = Sequential([
        Dense(units=25, activation='relu'),
        Dense(units=15, activation='relu'),
        Dense(units=10, activation='linear')
    ])
    
    model.compile(loss=SparseCategoricalCrossEntropy(from_logits=True))

     

     

    Classification with Multiple Outputs

    만약 Output이 여러개일 경우는 어떨까? 가장 대표적인 케이스는 Multi-label Classification 이다. 요즘 로그인에도 많이 쓰이고 있는데, 예를 들어 아래 이미지를 보자.

    https://blog.naver.com/slwkfgo11223/110149826572

     

    피카츄가 있는가? Yes.

    파이리가 있는가? Yes.

    뮤가 있는가? No.

     

    한 이미지에 한가지만 있는게 아니라, 여러가지가 존재한다. 구글 로그인시에도, 버스, 자동차, 사람, 횡단보도, 자전거, 신호등 등을 이용해서 자동 로그인을 방지하곤 한다. 이것을 계산해내려면 어떻게 해야할까? 

     

    피카츄, 파이리, 뮤가 존재하는지 알아보는 Neural Network를 따로 구현해서 3개의 모델을 돌려야할까? 그것도 나쁜 생각은 아니지만, 또다른 방법이 있다. 세가지를 동시에 감지하도록 훈련하면 된다. 마지막 레이어를 3개를 출력하면 된다. 마지막 레이어를 sigmoid activation을 사용해서, 세개가 각각 있는지에 대한 값을 담고있는 벡터를 output하면 된다. 

     

     

     

     

     

     

    Reference

    Coursera Machine Learning Specialization > Supervised Machine Learning: Advanced Learning Algorithms > Neural Network Intuition

     

    고급 학습 알고리즘

    머신러닝 전문 과정의 두 번째 과정에서는 다음을 학습합니다: - 다중 클래스 분류를 수행하기 위해 텐서플로로 신경망 구축 및 훈련 - 모델이 실제 세계의 데이터와 작업에 일반화되도록 머신

    www.coursera.org

    https://developer.apple.com/documentation/accelerate/bnnsactivationfunction/2915301-softmax

     

    softmax | Apple Developer Documentation

    An activation function that returns the softmax function of its input.

    developer.apple.com

     

    댓글

Designed by Tistory.