본문 바로가기
ML&DATA/모두를 위한 딥러닝

multinomial classification

by sun__ 2020. 7. 12.

어떤 데이터의 라벨이 양자화된 값들로 결정되는 경우 multinomial classification으로 새로운 input데이터의 라벨을 예측하는 방법.

#label 번의 binary classification을 수행하여 라벨마다 확률을 구해준 후 가장 큰 확률을 갖는 라벨을 output으로 예측하는 방법이다.

 

#label번의 binary classification을 수행하기 위해 가중치 벡터를 이어붙인 가중치 매트릭스를 사용한다.

 

설명의 편의를 위해 $f(X) = XW+b$ 대신 다음 링크함수를 사용한다. $$f(X) = WX$$

 

라벨 3개, feature 3개인 경우 링크함수의 예시

더보기

bias는 어디있고 XW가 아닌 WX를 사용하는 이유가 뭔지?

 

XW+B를 다르게 표현하면 X*W+1*B로 나타낼 수 있기때문에 1을 X의 벡터 첫번째 항으로 추가시켜주고, B를 W의 첫번째 항으로 추가시켜줍니다. 즉 X = [1 X1 X2 ... Xn], W = [B W1 W2 ...Wm] 이렇게 나타낼 수 있기때문에 이전의 식을 XW로 간단하게 표현할 수 있습니다.

(https://www.youtube.com/watch?v=MFAnsx1y9ZI&list=PLQ28Nx3M4Jrguyuwg4xe9d9t2XE639e5C&index=12)댓글

 

위 그림의 결과 [[y1], [y2], [y3]]를 sigmoid에 넣지 않고, softmax함수를 사용한다. 

$$S(y_i) = \frac{e^{y_i}}{\sum{}{}e^{y_j}}$$

(단순히 전체에 대한 해당 값의 비율이 아닌 위와같은 softmax함수를 쓰는 건 예측함수의 비선형성을 위함이라고 함)

 

softmax함수의 출력값과 실제 값(라벨 값)으로 cross entropy함수를 정의할 수 있다. (비용함수에 사용함)

 

i번째 데이터에 대한 cross entropy $D(S_i, L_i)$는 다음과 같다.

$$D(S_i, L_i) = -\sum_{j}^{num \, of\,  label}L_j\, log\, S_j$$

 

비용함수는 다음과 같다

$$cost = \frac{1}{m}\sum_{i}D(S(X_iW+b), L_i)$$

 

cross entropy와 logistic cost는 본질적으론 같다. 더보기에서 확인하자.

더보기
logistic cost

라벨이 2가지인 경우 binary classification의 결과는 0또는 1인 반면, multinomial classification의 결과는 [1,0] 또는 [0,1]이다.

L2 = 1-L1이라고 할 수 있고 s2 = 1-s1이라고 할 수 있다.

 

cross entropy를 위 식으로 전개해보면 다음과 같다.

$$D(S,L) = -L_1log(S_1) - L_2log(S_2)$$

$$D(S,L) = -L_1log(S_1) - (1-L_1)log(1-S_1)$$

 

따라서 라벨이 2가지인 경우 logisitic cost와 cross entropy는 같다.

 

cross entropy는 logistic cost를 확장시킨 개념이라고 할 수 있겠다.

 


 

가설함수와 비용함수

$$H(X) = S(XW+b)$$

$$cost = \frac{1}{m}\sum_{i}D(S(X_iW+b), L_i)$$

 

hypothesis = tf.nn.softmax(tf.matmul(features,W)+b)
cost = tf.reduce_mean(-tf.reduce_sum(y_data * tf.math.log(hypothesis), axis=1))

 

tf.nn.softf.nn.softmax_cross_entropy_with_logit을 이용한 비용함수. 가설함수가 아닌 로짓을 사용함에 주의

def logit_fn(X):
    return tf.matmul(X,W)+b
    
def cost_fn(X,Y):
    logits = logit_fn(X)
    cost_i = tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = Y)
    cost = tf.reduce_mean(cost_i)
    return cost

 

<csv파일을 이용한 실습> 

data-04-zoo.csv
0.00MB

16개의 feature가 7개 class 중 하나의 label을 결정하는 데이터를 이용한 multinomial classification

 

import tensorflow as tf
import numpy as np

xy = np.loadtxt('data-04-zoo.csv', delimiter = ',', dtype = np.float32)
x_data = xy[:,0:-1]
y_data = xy[:,[-1]].astype(np.int32)

csv파일로부터 데이터를 읽어와서 feature와 label을 분류한다. 이때 label이 0~6값을 갖는데, multinomial classification을 위해 one_hot 형식으로 바꾸는 전처리가 필요하다.

 

y_data를 category variable로 사용할것이므로 int로 형변환이 필요하다. (안하면 에러)

 

nb_classes = 7
Y_one_hot = tf.one_hot(list(y_data), nb_classes)    
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes]) 

y_data는 2차원 리스트인데 tf.one_hot을 적용하면 차원이 하나 늘어서 3차원이 된다.

tf.reshape하여 2차원으로 만들어줘야 한다.

 

 

W = tf.Variable(tf.zeros([16, nb_classes]), name = 'weight')
b = tf.Variable(tf.zeros([nb_classes]), name = 'bias')
variables = [W,b]

가중치 matrix와 bias를 랜덤값으로 초기화해준다. 아래 그림에 맞게 차원을 맞춰줘야 함

결과 = logit(X)

def logit_fn(X):
    return tf.matmul(X,W)+b

def hypothesis(X):
    return tf.nn.softmax(logit_fn(X))

def cost_fn(X,Y):
    logits = logit_fn(X)
    cost_i = tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = Y)
    cost = tf.reduce_mean(cost_i)
    return cost

def grad_fn(X,Y):
    with tf.GradientTape() as tape:
        loss = cost_fn(X,Y)
        grads = tape.gradient(loss, variables)
        return grads
        
def prediction(X,Y):
    pred = tf.argmax(hypothesis(X), 1)
    correct_prediction = tf.equal(pred, tf.argmax(Y,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    return accuracy        

적절히 함수들 정의

 

prediction(X,Y): (W,b)를 이용한 가설함수가 X,Y에 대해 동작하는 정확성 출력

 

위에 그림에서 색칠한 결과가 hypothesis(X)에 해당.

 

pred는 다음과 같음. 1차원 리스트가 담긴 텐서임

tf.argmax(Y,1)은 라벨에서 1이 있는 인덱스임. correct_prediction은 pred와 tf.argmax(Y,1)의 원소 하나씩 비교해서 같으면 1 다르면 0(boolean)을 리스트에 저장. -> correct_prediction도 1차원 리스트

 

correct_prediction은 boolean type이므로 tf.float32으로 cast후에 평균을 구하면 예측이 맞은 횟수의 확률, 즉 정확도를 구할 수 있다.

 

def fit(X, Y, epochs=500, verbose = 50):
    optimizer = tf.keras.optimizers.SGD(learning_rate = 0.01)
    for i in range(epochs):
        grads = grad_fn(X,Y)
        optimizer.apply_gradients(zip(grads, variables))
        if (i==0) | ((i+1)%verbose==0):
            acc = prediction(X,Y).numpy()
            loss = tf.reduce_sum(cost_fn(X,Y)).numpy()
            print("Loss & Acc at {} epoch {}, {}".format(i+1, loss, acc))
            
fit(x_data, Y_one_hot)

전처리한 데이터 x_data와 Y_one_hot으로 fit(가중치 matrix를 조정)하는 코드. 

 

 

 

 

전체코드

import tensorflow as tf
import numpy as np

xy = np.loadtxt('data-04-zoo.csv', delimiter = ',', dtype = np.float32)
x_data = xy[:,0:-1]
y_data = xy[:,[-1]].astype(np.int32)

nb_classes = 7
Y_one_hot = tf.one_hot(list(y_data), nb_classes)
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes])

W = tf.Variable(tf.zeros([16, nb_classes]), name = 'weight')
b = tf.Variable(tf.zeros([nb_classes]), name = 'bias')
variables = [W,b]

def logit_fn(X):
    return tf.matmul(X,W)+b

def hypothesis(X):
    return tf.nn.softmax(logit_fn(X))

def cost_fn(X,Y):
    logits = logit_fn(X)
    cost_i = tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = Y)
    cost = tf.reduce_mean(cost_i)
    return cost

def grad_fn(X,Y):
    with tf.GradientTape() as tape:
        loss = cost_fn(X,Y)
        grads = tape.gradient(loss, variables)
        return grads
    
def prediction(X,Y):
    pred = tf.argmax(hypothesis(X), 1)
    correct_prediction = tf.equal(pred, tf.argmax(Y,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    return accuracy

def fit(X, Y, epochs=500, verbose = 50):
    optimizer = tf.keras.optimizers.SGD(learning_rate = 0.01)
    for i in range(epochs):
        grads = grad_fn(X,Y)
        optimizer.apply_gradients(zip(grads, variables))
        if (i==0) | ((i+1)%verbose==0):
            acc = prediction(X,Y).numpy()
            loss = tf.reduce_sum(cost_fn(X,Y)).numpy()
            print("Loss & Acc at {} epoch {}, {}".format(i+1, loss, acc))
            
fit(x_data, Y_one_hot)

 

'ML&DATA > 모두를 위한 딥러닝' 카테고리의 다른 글

실습  (0) 2020.07.13
application & tips  (0) 2020.07.13
binary classification  (0) 2020.07.10
simple linear regression (단순 선형 회귀)  (0) 2020.07.08
용어/개념  (0) 2020.07.08