Skip to content

기계학습 SoftMax #

Find similar titles

5회 업데이트 됨.

Edit
  • 최초 작성자
    ecjang
  • 최근 업데이트
    ecjang

Structured data

Category
Programming

SoftMax Regression #

SoftMax 분석은 결과값이 여러 가지일 경우 사용하는 분석 방법이다. 1등급, 2등급, 3등급, 4등급 같은 등급이나 자동차, 비행기, 기차 같은 구분처럼 3가지 이상의 결괏값으로 구분할 때 사용한다. SoftMax 분석의 핵심인 Logistic 분석, 다항함수(행렬) 분석, Cross Entory 3가지를 알아보고 예제 데이터를 분석해본다.

Logistic Regression #

지난 게시물에서는 Logistic Regression 알고리즘에 대해서 알아보았다. 간단히 정리하면 키, 길이, 너비, 무게, 부피 등 다양한 단위를 가진 값들을 계산하기 위해 Sigmoid 함수를 사용하여 0과 1 사이의 값으로 균등한 비율로 바꾸는 기능이다. SoftMax는 이런 Logistic 분석을 한 번에 여러 번 계산하여 결괏값을 계산한다. 자세한 내용은 아래 링크를 참고하면 알 수 있다.

Multinomial Classification #

이번 게시물에서는 결괏값이 여러 가지일 경우에 대해서 알아본다. Logistic 분석에서는 결괏값이 0 또는 1로 2가지로만 구분되었지만, A등급, B등급, C등급처럼 3가지 이상으로 구분할 필요가 있는 경우 행렬을 사용하여 계산한다. 우선 행렬에 대해서 알아본다.

  • 제목의 'Multinomial'이란 단어는 '다항 함수'를 의미

Matrix #

수학에서 '행렬'이라고 하며 수, 기호, 수식 등을 행과 열에 맞추어 배치한 것이다. '2x3 행렬'식으로 표기하며 이는 2행 3열을 가진 행렬이라는 의미이며 안에 배치된 것들을 '성분, 항, 원소'라고 한다.

matrix

일반적인 행렬 - 위키백과

Multiple Matrix #

행렬의 곱셈은 분석에서 핵심적인 연산이다. 2개의 행렬 A, B의 곱셈은 A 행렬의 행과 B 행렬의 열을 하나씩 곱해서 계산한다. 연산은 복잡하지 않지만 어떤 순서로 곱하여 계산하는지 알아두어야 한다.

matrixMultipleOperation

행렬 A와 B의 곱 계산법 - 위키백과

matrixMultipleOperationSample

행렬 곱셈의 예 - 위키백과

Hat #

행렬의 곱셈으로 나온 결과 행렬의 각 원소 값햇( ̄)이라고 한다. 분석의 예측값과 같은 의미이며 예측값 위에 언더바 기호를 추가해준다.

$$ \begin{equation} \left({\begin{array}{cc} W_{A1} & W_{A2} & W_{A3} \\ W_{B1} & W_{B2} & W_{B3} \\ W_{C1} & W_{C2} & W_{C3} \end{array}}\right) \times \left({\begin{array}{cc} X_1 \\ X_2 \\ X_3 \end{array}}\right) = \left({\begin{array}{cc} W_{A1}X_1 & W_{A2}X_2 & W_{A3}X_3 \\ W_{B1}X_1 & W_{B2}X_2 & W_{B3}X_3 \\ W_{C1}X_1 & W_{C2}X_2 & W_{C3}X_3 \end{array}}\right) = \left({\begin{array}{cc} \bar Y_A \\ \bar Y_B \\ \bar Y_C \end{array}}\right) \end{equation} $$

행렬 곱셈 과정

  • 위 식의 경우 가장 오른쪽의 행렬이 예측값 행렬임
  • 햇 기호를 '^'기호로 표시하기도 함
  • 결괏값인 hat Y1은 기계학습을 통해 계산된 예측값을 의미
  • Logistic 분석에서는 0과 1 사이로 계산되지만 SoftMax에서는 2, 10, 0.009등 다양한 결괏값이 나올 수 있음

Cross Entropy #

'Entropy'는 열역학에서 사용하는 용어로써 '복잡도, 무질서 정도'를 의미하는 반면, 분석에서는 '정보량의 평균'을 의미한다. 즉 정보량을 계산하는 알고리즘으로, 복잡한 정도를 계산하는 방법의 하나다.

  • 'S(Y)'라고 표시하며 SoftMax 분석으로 예측한 값을 의미
  • 실제 결괏값은 'L(Y)'라고 표시하며 S(Y)와 비교하여 계산
  • L(Y)값과 S(Y)값의 차이를 줄이는 것을 Entropy를 줄인다고 표현

Method #

Cross Entropy 함수는 아래와 같은 공식으로 계산한다.

$$ - \sum_{i} L_i log(S_i) \quad = \quad - \sum_{i} L_i log(\hat y_i) \quad = \quad \sum_{i} L_i - log(\hat y_i) $$

  • -로그x 함수는 logx 함수를 x축으로 대칭한 것
  • -로그x 함수는 x가 0일 때 무한대 1일 때 0을 나타냄
  • 즉 0일 때는 벌점이 가중되고, 1에 가까워지게 계산됨
  • 실제로 0 또는 1인 극단적인 값으로 나오지 않고 그 중간값으로 계산됨

Operation Process #

Cross Entropy가 어떻게 계산되는지 과정을 알아본다.

  • 실제값과 예측값이 같을 경우

    1. $$ \text{실제값이 A인 경우} \quad L = \begin{bmatrix} 1 \\ 0 \end{bmatrix} $$

    2. $$ \text{예측값이 A인 경우} \quad \hat Y = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : } \, \sum_{i} L_i - log(\hat y_i) \, \text{공식에 대입} $$

    3. $$ = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \times -log\begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : -log 함수에 의해 1은 0으로, 0은 무한대로 변환} $$

    4. $$ = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \times \begin{bmatrix} \infty \\ 0 \end{bmatrix} = 0 $$

    5. 예측값이 맞았으므로 cost의 값이 0이 나옴

  • 실제값과 예측값이 다를 경우

    1. $$ \text{예측값이 B인 경우} \quad \hat Y = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \text{ : } \, \sum_{i} L_i - log(\hat y_i) \, \text{공식에 대입} $$

    2. $$ \begin{bmatrix} 0 \\ 1 \end{bmatrix} \times -log\begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : -log 함수에 의해 1은 0으로, 0은 무한대로 변환} $$

    3. $$ = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \times \begin{bmatrix} 0 \\ \infty \end{bmatrix} $$

    4. $$ = \begin{bmatrix} 0 \\ \infty \end{bmatrix} \, = \, \infty \quad $$

    5. 예측값이 틀렸으므로 cost의 값이 무한대가 나옴

SoftMax Function #

SoftMax를 직접 공식을 함수로 만들어 사용할 수 있지만, 기본적으로 제공되는 라이브러리를 사용한다.

  • N개의 결괏값을 예측할 때 유용하며 예, 아니오 2단계로만 예측하는 Binary Classification에 비해 다양한 단계로 예측 가능
  • softmax 함수를 적용하면 결괏값이 확률로 나옴(3가지의 결과를 출력할 경우 [0.5 0.3 0.2] 식으로 출력)
  • 첫번째 값이 맞을 확률이 0.5(50%)라는 의미

Step1. Variables & Hypothesis #

우선 분석에 사용할 변수를 만들어 준다. 텐서플로우를 로드한 후 분석에 사용할 변수들과 예측값을 계산할 SoftMax 함수를 작성한다.

    import tensorflow as tf
    # Temporary Value
    X = tf.placeholder(tf.float32)
    Y = tf.placeholder(tf.float32)
    W = tf.placeholder(tf.float32)
    b = tf.placeholder(tf.float32)

    hypothesis = tf.nn.softmax(tf.matmul(X,W)+b)
  • softmax 라이브러리 = tf.nn.softmax()
  • 예측값 = tf.matmal(X,W)+b
  • 예측값에 softmax를 적용 = tf.nn.softmax(tf.matmal(X,W)+b)
  • X는 입력값, Y는 예측값, W는 가중치, b는 편차를 의미

Step2. Cross Entropy #

Softmax가 적용된 예측값과 실제값과의 차이를 계산하여 이를 비용화(수치화)하는 cost 값을 계산한다.

    cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1)) 
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
  • cost가 작다는 것은 그만큼 높은 확률로 예측값이 실제값과 같다는 의미
  • cost function과 loss function은 같은 의미
  • Y * tf.log(hypothesis)의 값은 행렬(Matrix)로 나옴
  • 결괏값을 계산하기 위해 W의 행과 열 조절 필요
  • reduce_sum으로 합을 구하고 reduce_mean으로 평균을 구함
  • cost의 최적화는 GradientDescentOptimizer함수를 사용

SoftMax Implement #

Implement 1 - Set Data #

간단한 예제 데이터를 통해 SoftMax를 실습해본다. 우선 텐서플로우를 로드하고 실습할 데이터를 만들어둔다.

    # load Tensorflow
    import tensorflow as tf
    # Using Matrix Data : 8 row x 4 col / 8 row x 3 col
    x_data = [
    [1, 2, 1, 1], # 1
    [2, 1, 3, 2], # 2
    [3, 1, 3, 4], # 3
    [4, 1, 5, 5], # 4
    [1, 7, 5, 5], # 5
    [1, 2, 5, 6], # 6
    [1, 6, 6, 6], # 7
    [1, 7, 7, 7], # 8
    ]

    y_data = [
    [0, 0, 1], # 1 
    [0, 0, 1], # 2
    [0, 0, 1], # 3 
    [0, 1, 0], # 4 
    [0, 1, 0], # 5 
    [0, 1, 0], # 6 
    [1, 0, 0], # 7 
    [1, 0, 0], # 8 
    ]
  • y_data는 실제값을 의미
  • 여러개의 값이 있을 수 있기 때문에 형렬 형식으로 나타냄
  • one-hot 인코딩 방식이라고 하며 특정 수만 1로, 나머지는 0으로 표현
  • 예> [0,1,2] 중 실제값이 1이라고 하면 [0,1,0]으로 나타냄

Implement 2 - Set Variables #

분석에 사용할 입력 변수를 설정한다.

    # Variable for Feed data
    X = tf.placeholder("float", [None, 4])
    Y = tf.placeholder("float", [None, 3])
    nb_classes = 3

    W = tf.Variable(tf.random_normal([4, nb_classes], name='weight'))
    b = tf.Variable(tf.random_normal([nb_classes], name='bias'))
  • [None, 4]은 행과 열의 숫자를 의미
  • None은 행은 정하지 않고 자동으로 입력, 4는 4열을 의미
  • nb_classes은 클래스의 개수로써 3개의 단계를 나타냄
  • W는 가중치(Weight), b는 증가값(Bias)을 의미
  • 행과 열의 개수를 맞추는 것에 주의
  • X는 [8x4], Y는 [8X3] 이므로 X에 [4X3]행렬을 곱해야 Y행렬의 형태 [8x3]가 됨

Implement 3 - Set Hypothesis #

정의한 변수들을 통해 SoftMax 함수식을 작성한다. 그리고 Cost값을 명시한 후 최적화 방법을 지정한다.

    hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)
    cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1)) # axis: The dimensions to reduce.
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
  • hypothesis 가설이며 예측값을 의미
  • cost는 예측값과 실제값의 차이를 의미
  • cost 함수는 저번 시간의 cost 공식을 code로 표현
  • 최적화는 GradientDescentOptimizer함수를 사용

Implement 4 - Train & modeling #

반복해서 훈련을 실시하며 그래프로 그리기 위해 200번째 계산마다 계산 값들을 저장한다.

    with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    step_list= []
    W_list = []
    hy_list = []
    cost_list = []
    feed = {X:x_data, Y:y_data}

    for step in range(2001):

    sess.run(optimizer, feed_dict=feed)

    if step % 200 == 0:
    step_list.append('step'+str(step))
    W_list.append(sess.run(W))
    hy_list.append(sess.run(hypothesis, feed_dict=feed))
    cost_list.append(sess.run(cost, feed_dict=feed))
  • 위에서 설정해 준 노드를 초기화해주고 데이터들을 리스트에 저장

Implement 5 - Result Table #

저장된 값들을 테이블로 출력하여 어떻게 값이 변경되었는지 확인한다.

    import pandas as pd

    first_class_list = []
    second_class_list = []
    third_class_list = []

    for first_val in hy_list:

    first_class_list.append(first_val[0][0])
    second_class_list.append(first_val[0][1])
    third_class_list.append(first_val[0][2])

    result_data = {
    'hy1' : first_class_list,
    'hy2' : second_class_list,
    'hy3' : third_class_list,
    'cost' : cost_list,
    }

    df = pd.DataFrame(result_data, index=step_list)

ResultTable

계산결과 테이블 - 자체 제작

  • 해당 과정을 통해 위와 같은 테이블이 출력
  • 계산이 진행될 수록 Cost가 낮아짐을 확인
  • Cost값에 따라 가중치 값도 달라짐

Implement 6 - Visualizaion #

해당 값을 한눈에 파악하기 위해 그래프로 그려본다.

    import matplotlib.pyplot as plt
    import numpy as np

    plt.figure(figsize=(15,5))
    x = np.arange(0,len(step_list))
    plt.scatter(step_list, first_class_list, s=200 , edgecolors='black', label="First Classification")
    plt.scatter(step_list, second_class_list, s=200, edgecolors='black', label="Second Classification")
    plt.scatter(step_list, third_class_list, s=200, edgecolors='black', label="Third Classification")
    plt.plot(cost_list, 'rs--', label="Cost value")

    plt.xticks(x, step_list)
    plt.ylim(0,1.2)
    plt.title('First Value Hypothesis')
    plt.legend()
    plt.show()

ResultPlot

계산결과의 시각화 - 자체 제작

  • X축은 계산횟수, Y축은 예상값을 의미
  • 예시중 첫번째 값만 계산, 나온 예상값을 그래프로 출력
  • 예상값 3가지 중 첫번째는 파란색, 두번째는 주황색, 세번째는 초록색으로 표시
  • 예상값은 0과 1사이의 값으로 나오며 높을 수록 해당 구분값이 맞을 확률이 높음
  • 훈련이 반복될 수록 cost의 값이 낮아지는 것을 확인 가능
  • 처음에는 두번째 값의 확률이 높았다가 훈련이 반복되면서 세번째값의 확률이 올라감
  • 실제 결괏값(3)과 동일하므로 잘 훈련되 모델이라고 예상

Implement 6 - Evaluation #

새로운 데이터를 입력하여 해당 모델이 잘 훈련되었는지 평가한다.

    x_data = [[1, 11, 7, 9], [1, 3, 4, 3], [1, 1, 0, 1]]
    y_data = [[0, 1, 0], [1, 0, 0], [0, 0, 1]]

    with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    feed = {X:x_data, Y:y_data}

    for step in range(2001): 
    sess.run(optimizer, feed_dict=feed)

    if step % 200 == 0:
    all = sess.run(hypothesis, feed_dict={X: x_data})

    print("-> step{:5} cost: {:5.3f} \033[1m softmax: {} \033[0m hypothesis: {} ... "
    .format(step, sess.run(cost,feed_dict={X:x_data, Y:y_data}), sess.run(tf.arg_max(all, 1)), all[0] ))

Evaluation

시험결과 - 자체 제작

  • x_data를 한 개가 아닌 여러개를 넣어서 테스트
  • softmax값은 x_data의 행의 개수에 맞게 출력됨
  • [1 0 2]은 첫번째 구분자를 1로, 두번째를 0으로, 세번째는 2로 예측했다는 의미
  • 새로운 예제 데이터 훈련결과 예측값과 실제값이 일치함
  • 잘 훈련된 모델이라고 평가 할 수 있음

참고 링크 #

0.0.1_20230725_7_v68