juuuding

[Advanced Learning Algorithms] Neural network training - Multiclass 본문

인공지능/코세라 머신러닝 특화과정

[Advanced Learning Algorithms] Neural network training - Multiclass

jiuuu 2023. 12. 6. 00:21

 Multiclass

 

 이때까지 y 값이 두개인 binary classification을 다루었다. 이와 달리 multiclass classification은 y가 두개 이상의 가능한 값을 가질 수 있는 것을 말한다. 아래의 그래프로 예를 들자면 왼쪽 그림은 binary classification이고, 오른쪽 그림은 y가 1,2,3,4 값을 가질 수 있는 multiclass classification이다. 

 

 

 

 

 Softmax

 

 softmax는 binary classification인 logistic regression algorithm의 일반화이다. softmax를 사용해서 앞서 본 multiclass classification을 해결할 수 있다. 우선 2개의 결과 값을 가질 수 있는 logistic regression을 다시 보면, 다음과 같은 g 함수를 적용할 수 있고 결과는 0 / 1이 될 확률을 뜻한다. 여기서는 가능한 값이 두가지이기 때문에 한 결과 값(a1)을 구하면 나머지 결과 값은 1-a1을 하면 a2를 얻을 수 있다. 

 

logistic regression

 

 이러한 logistic regression을 일반화하면 softmax regression이다. 아래의 예제에서는 가능한 y의 값이 1,2,3,4 총 4가지이며, 각각의 결과는 해당 y 값이 될 확률을 의미하고 확률이기 때문에 총 합은 1이다. 즉 a1+a2+a3+a4=1이다.

 

softmax regression example

 

 이 예제를 공식화하면 아래와 같은 식이 나오고, 아래의 식에 N=2로 적용하면 logistic regression이기 때문에 softmax는 logistic의 일반화라고 말할 수 있는 것이다. 

 

softmax regression

 

 

[Cost]

 softmax regression이 무엇인지 알아보았으니 이제 softmax의 cost의 표현법에 대해 알아보자. softmax regression은 logisitc regression의 일반화이므로, cost를 구할 때도 logistic regression의 cost를 구하는 방법을 참조할 수 있다. logistic regression의 loss function은 다음과 같이 표현되는데, 이 식의 의미는 y=1일 때 -loga1이 loss, y=2일 때 -log(1-a1)이 loss라는 것이다. 즉 풀어서 설명하면 y=1일 때 y=1일 확률을 예측한 값인 a1이 크면 잘 예측한 것인데, -log 함수 모양을 생각하면 a1이 클 수록 -loga1 값이 줄어든다. 즉, 잘 예측할수록 loss 값이 줄어든다는 말이다. 반대로 y=0일 때도 마찬가지로 이 원리가 적용된다. 

 

logistic regression's loss function

 

 이것을 기반으로 softmax regression의 loss function의 식은 다음과 같이 표현할 수 있다.  

 

softmax regression's loss function

 

 logistic에 적용한 것처럼 y=n일 때 y가 그 값(n)일 거라 예측한 값인 a_n을 -log 함수에 넣어 loss function을 계산해주는 것이다. 

 

 

 

 Neural Network with Softmax output

 

 위에서 본 softmax를 neural network에 사용하려면 마지막 output layer에 y가 가능한 값들의 개수만큼 unit을 설정해주어야 한다. logistic regression은 가능한 값이 둘 중 하나이기 때문에 하나의 unit으로 그 결과를 나타낼 수 있었지만, softmax에서는 가능한 값이 여러개일 수 있기 때문이다. 만약 가능한 y 값이 10개이면 output layer의 unit을 10개로 변경해주어야 한다. 

 

 

 

 

[MNIST with softmax]

 softmax를 사용하는 코드를 작성하면 다음과 같다. 

 

import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras import Dense

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

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

 

 위의 코드에서 "SparseCategoricalCrossentropy"는 y를 카테고리로 분류하고, y는 카테고리들 중 하나의 값만 가질 수 있다는 의미로 사용된다. 참고로 sigmoid일 때는 loss 값으로 "BinaryCrossentropy"가 사용된다. 하지만 이 방법은 사용하지 않는 것이 좋으며 다음 section에 있는 코드를 사용하는 것이 좋다. 

 

 

 

 Improved implementation of softmax

 

[Numerical Roundoff Errors]

  위의 코드를 사용하는 것이 좋지 않다고 했었는데, 그 이유와 해결법에 대해 알아보자. 우선 컴퓨터로 2/10,000을 두가지 방법으로 계산해보자. 

 

# 방법 1
x=2/10000
print(x)

# 방법 2
x=(1+1/10000)-(1-1/10000)
print(x)

 

 위의 코드를 작동시키면 다음과 같은 결과가 나온다. 

 

 수학적으로 계산하면 두 식의 값은 같지만, 이렇게 컴퓨터로 계산했을 때 다른 값이 나오는 것을 확인할 수 있다. 이것을 "Numerical Roundoff Errors"라고 하며, 컴퓨터가 각 숫자를 저장할 수 있는 메모리가 한정되어 있기 때문에 발생하는 현상이다. 이러한 에러 때문에 loss 값을 계산할 때 약간의 오차가 생기면서 정확하지 않은 loss 값이 계산되기 때문에 위에 있는 softmax 사용 코드를 사용하면 좋지 않은 결과를 얻게 된다.

 logistic으로 예를 들었을 때 a 값이 다음과 같이 계산되고, 이 a 값이 아래의 loss function으로 들어가 loss 값이 계산이 되는데, 계산된 a 값을 loss function에 넣을 때 위와 같은 numerical roundoff error가 발생한다. 그렇기 때문에 loss값이 정확하지 않게 된다. 이를 해결하기 위해 계산된 a값을 loss function에 넣는 것이 아닌, loss function의 a 자리에서 바로 계산되도록 하여 정확도를 높여줄 수 있다. 이러한 방법을 적용하기 위해서는 윗 section의 코드를 다음과 같이 변경해주어야 한다. 

 

import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras import Dense

model = Sequential([
    Dense(units=25, activation='relu'),
    Dense(units=15, activation='relu'),
    Dense(units=10, activation='linear')	# 변경 부분
    ])

from tensorflow.keras.losses import SparseCategoricalCrossentropy
model.compile(loss=SparseCategoricalCrossentropy(from_logits=True))	# 변경 부분
model.fit(X,Y,epochs=100)

logits = model(X)
f_x=tf.nn.softmax(logits)	# z1...z10, not a1...a10

 

 

 logistic regression에서도 마찬가지로 output layer의 activation을 sigmoid -> linear로 변경해주고 "loss=BinaryCrossEntropy(from_logits=True)"로 코드를 작성하면 numerical roundoff error를 피할 수 있다.