기계학습
SoftMax
#
Find similar titles
- 최초 작성자
- 최근 업데이트
Structured data
- Category
- Programming
Table of Contents
SoftMax Regression #
SoftMax 분석은 결과값이 여러 가지일 경우 사용하는 분석 방법이다. 1등급, 2등급, 3등급, 4등급 같은 등급이나 자동차, 비행기, 기차 같은 구분처럼 3가지 이상의 결괏값으로 구분할 때 사용한다. SoftMax 분석의 핵심인 Logistic 분석, 다항함수(행렬) 분석, Cross Entory 3가지를 알아보고 예제 데이터를 분석해본다.
Logistic Regression #
지난 게시물에서는 Logistic Regression 알고리즘에 대해서 알아보았다. 간단히 정리하면 키, 길이, 너비, 무게, 부피 등 다양한 단위를 가진 값들을 계산하기 위해 Sigmoid 함수를 사용하여 0과 1 사이의 값으로 균등한 비율로 바꾸는 기능이다. SoftMax는 이런 Logistic 분석을 한 번에 여러 번 계산하여 결괏값을 계산한다. 자세한 내용은 아래 링크를 참고하면 알 수 있다.
- 참고 : Logistic Regression
Multinomial Classification #
이번 게시물에서는 결괏값이 여러 가지일 경우에 대해서 알아본다. Logistic 분석에서는 결괏값이 0 또는 1로 2가지로만 구분되었지만, A등급, B등급, C등급처럼 3가지 이상으로 구분할 필요가 있는 경우 행렬을 사용하여 계산한다. 우선 행렬에 대해서 알아본다.
- 제목의 'Multinomial'이란 단어는 '다항 함수'를 의미
Matrix #
수학에서 '행렬'이라고 하며 수, 기호, 수식 등을 행과 열에 맞추어 배치한 것이다. '2x3 행렬'식으로 표기하며 이는 2행 3열을 가진 행렬이라는 의미이며 안에 배치된 것들을 '성분, 항, 원소'라고 한다.
일반적인 행렬 - 위키백과
Multiple Matrix #
행렬의 곱셈은 분석에서 핵심적인 연산이다. 2개의 행렬 A, B의 곱셈은 A 행렬의 행과 B 행렬의 열을 하나씩 곱해서 계산한다. 연산은 복잡하지 않지만 어떤 순서로 곱하여 계산하는지 알아두어야 한다.
행렬 A와 B의 곱 계산법 - 위키백과
행렬 곱셈의 예 - 위키백과
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가 어떻게 계산되는지 과정을 알아본다.
-
실제값과 예측값이 같을 경우
-
$$ \text{실제값이 A인 경우} \quad L = \begin{bmatrix} 1 \\ 0 \end{bmatrix} $$
-
$$ \text{예측값이 A인 경우} \quad \hat Y = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : } \, \sum_{i} L_i - log(\hat y_i) \, \text{공식에 대입} $$
-
$$ = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \times -log\begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : -log 함수에 의해 1은 0으로, 0은 무한대로 변환} $$
-
$$ = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \times \begin{bmatrix} \infty \\ 0 \end{bmatrix} = 0 $$
-
예측값이 맞았으므로 cost의 값이 0이 나옴
-
-
실제값과 예측값이 다를 경우
-
$$ \text{예측값이 B인 경우} \quad \hat Y = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \text{ : } \, \sum_{i} L_i - log(\hat y_i) \, \text{공식에 대입} $$
-
$$ \begin{bmatrix} 0 \\ 1 \end{bmatrix} \times -log\begin{bmatrix} 1 \\ 0 \end{bmatrix} \text{ : -log 함수에 의해 1은 0으로, 0은 무한대로 변환} $$
-
$$ = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \times \begin{bmatrix} 0 \\ \infty \end{bmatrix} $$
-
$$ = \begin{bmatrix} 0 \\ \infty \end{bmatrix} \, = \, \infty \quad $$
-
예측값이 틀렸으므로 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)
계산결과 테이블 - 자체 제작
- 해당 과정을 통해 위와 같은 테이블이 출력
- 계산이 진행될 수록 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()
계산결과의 시각화 - 자체 제작
- 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] ))
시험결과 - 자체 제작
x_data
를 한 개가 아닌 여러개를 넣어서 테스트- softmax값은 x_data의 행의 개수에 맞게 출력됨
- [1 0 2]은 첫번째 구분자를 1로, 두번째를 0으로, 세번째는 2로 예측했다는 의미
- 새로운 예제 데이터 훈련결과 예측값과 실제값이 일치함
- 잘 훈련된 모델이라고 평가 할 수 있음