티스토리 뷰
[모두의딥러닝] Softmax Regression (Multinomial Logistic Regression)
Sh.TK 2017. 8. 23. 16:35모두의 딥러닝
Softmax Regression (Multinomial Logistic Regression)
강의-1
이번 강의에서는 Softmax에 대해서 강의를 한다. Softmax란 기존의 Logistic(binary) classification을 여러 그룹으로 분류하기 위한 학습법이라고 설명한다.
다시 한번 강의에서 Logistic regression에 대해 설명한다. 해당 내용을 간단히 설명하자면, Wx를 z로 두고, 해당 값을 sigmoid라는 0~1사이의 값으로 변환하는 함수에 대입을 시킨다. 그러면 우리가 원하는 hypothesis를 구할 수 있다. 추가적으로 hypothesis를 통해 나온 값을 Y hat이라 부르는데 위에 모자를 쓴 것과 비슷한 모양이라고 해서 hat이라고 부른다고 한다.
이제 본론으로 넘어가 Multinomial classification에 대해 알아보자.
다음과 같은 트레이닝 셋이 있다고 하자. 기존과는 다르게 두가지(binary)로의 분류가 아닌, A,B,C와 같은 3개의 분류를 해야한다. 그렇다면 어떤 그래프를 그리면 다음과 같이 분류된 값들을 분류할 수 있을까?
김성훈 교수님께서는 다음과 같이 설명을 하신다.
첫번째 그래프는 C와 C가 아닌 binary regression. 두번째 그래프는 B와 B가 아닌 binary regression. 마지막으로 세번째는 A와 A가 아닌 binary regression.
이렇게 그래프들을 분류하면 각각의 값들을 분류할 수 있는 그래프가 완성될 것 이다.
이것을 식으로 나타내면 다음과 같다.
X값에 각각의 W값(A, B, C 그래프)을 넣어주고, 계산을 하면, 다음과 같은 Y hat 값들을 출력한다.
우리는 기존에 배웠던 행렬 곱셈을 통해, 다음과 같이 조금 더 간편하고 쉽게 해당 데이터들을 구할 수 있다.
여기서 왜 W 값을 위의 이미지에서 9개를 곱해야 하는가에 대해 생각해보자. 우선 x 데이터가 3개 이다. 그리고 우리는 각각의 그래프에 대한 W를 구하는 것이 학습을 하는 목적이다. 그러므로 W가 위의 그림과 같이 여러 개가 생성 된다.
강의-2
이번 강의는 sigmoid는 그럼 어디에 위치할까? 부터 시작한다.
위의 이미지를 설명하자면, 각각의 A,B,C에 대한 Logistic regression을 구한 결과인 Ya hat = 2.0, Yb hat = 1.0, Yc hat = 0.1로 나온 것을 확인 할 수 있다. 왜 3개의 값이 나왔는지 생각을 해보면, 우선 해당 Y hat들의 값은 각각의 a, b, c에 binary classification을 적용한 값이다. 그래서 해당 값들은 a, b, c일 확률에 대한 값 임을 알 수 있다.
강의에서 김성훈 교수님은 해당 값들을 확률로 나타낼 수 있으면 좋을 것 같다란 이야기를 하신다. 그걸 구현해주는 것이 Softmax 이다.
특징으로는 sigmoid와 마찬가지로 0과 1사이의 값으로 변환하고, 전체의 합은 1이 되도록 만들어준다.
해당 이미지 Softmax를 나타내는 이미지 인데, 해석을 해보면, 전체의 값에 해당 값을 나눠서 확률 값을 나타내는 걸 알 수 있다.
우리가 해당 학습 모델을 통해 이루려고 하는 것은, 입력한 값이 a인지, b인지 c인지에 대해 알고자 함이다. 그렇다면 가장 큰 값을 뺀 나머지는 의미가 없는 값이 된다. One-Hot Encoding을 사용하여, 가장 큰 값은 1로 두고, 나머지는 0으로 변환할 수 있다. 텐서플로우에서는 argmax라는 함수를 사용하여 One Hot Encoding을 적용할 수 있다.
해당 이미지에서 S(y)는 Y hat을 나타내고, L은 Label값으로 Y를 나타낸다. Cross-entropy는 예측한 값과 실제 값의 차를 계산하는 것으로, entropy 값이 감소하는 방향으로 진행하다 보면 최저 값을 찾을 수 있다.
Cross entropy cost 함수를 나타내면 오른쪽 그래프와 같아진다.
Cross entropy cost function을 계산하기 쉽게 식을 정리한 다음, 곱은 행렬곱이 아닌 엘리먼트 곱임을 주의하고 위의 이미지와 같이 각각의 값들을 대입해본다. 그러면 정답인 경우의 Cost값은 0이고, 정답이 아닌 경우, Cost값이 무한대 인 것을 알 수 있다.
Logistic cost와 Cross entropy의 차이점은 무엇일까? 정답은 없다.
교수님은 각각의 함수들은 차이가 없다고 말한다.
실제로 행렬로 계산을 한다는 것 말고는 Logistic cost 함수와 차이점은 없다.
0을 one hot encoding을 이용하면, 0 => [1,0] 이 되고
1을 one hot encoding을 이용하면, 1 => [0,1] 이 된다.
그렇게 생각을 하면 Cross entropy로 Logistic cost를 대체할 수 있기 때문이다.
Lab-1
이번 강의는 Softmax 학습법을 이용하여, 여러 개의 클래스로 분류를 하는 소스를 만들어본다.
우선 Softmax 함수에 대해 다시 한번 설명한다.
Softmax regression란 Logistic classification을 분류하고자 하는 클래스 수 만큼 사용하여 각 각의 Y hat값을 출력하는 학습법이다.
이 부분을 조금 쉽게 하기 위해, matmul이라는 matrix multification을 사용하여 한 번의 행렬 곱셈으로 위의 그림과 같이 2.0, 1.0, 0.1이라는 값의 Y hat을 출력 할 수 있다.
여기서 Softmax란 sigmoid함수로 생각하면 되는데, 전체에 해당되는 Y hat 값에 각 각의 Y hat 값을 나눠. 총 합이 1인 확률값으로 만들어 주는 함수이다. 그래서 0.7, 0.2, 0.1이라는 값이 출력하는 걸 확인할 수 있다.
cost 비용이 최저 비용인 w와 b값을 찾는 것이 우리의 최종 목표이다. 바로 다음 동영상에서 위의 소스와 달리 텐서플로우에서 제공하는 Cross entropy 함수를 사용하여 조금 더 쉽게 구할 수 있다.
import tensorflow as tf
x_data = [[1,
2, 1, 1], [2, 1, 3,
2], [3, 1,
3, 4],
[4, 1,
5, 5],
[1, 7,
5, 5],
[1, 2,
5, 6],
[1, 6,
6, 6],
[1, 7, 7,
7]]
y_data = [[0,
0, 1],
[0, 0,
1], [0, 0,
1], [0, 1,
0], [0, 1,
0], [0, 1,
0], [1, 0,
0], [1, 0,
0]]
X = tf.placeholder(tf.float32, [None,
4])
Y = tf.placeholder(tf.float32, [None,
3])
W = tf.Variable(tf.random_normal([4, 3]), name='weight')
b = tf.Variable(tf.random_normal([3]), name='bias')
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for
step in
range(2001):
sess.run(optimizer, feed_dict={X:
x_data, Y:
y_data})
if step % 200 ==
0:
print(step, "cost:
", sess.run(cost, feed_dict={X:
x_data, Y:
y_data}))
기존의 소스와 차이점은 y_data의 shape가 (2, 3) 이라는 점이 다르다. 해당 shape를 통해, 해당 소스는 클래스가 3개라는 걸 알 수 있다.
다른 부분은 기존의 소스와 별 차이가 없으나, cost 함수 중, axis=1이라는 부분을 확인 할 수 있다.
해당 부분이 무엇일까? 찾아보니 “축” 이다. 나중에 김성훈 교수님께서 해당 부분에 대해 간략히 설명을 해주시지만, 이 부분의 이해를 돕기 위해, 더 간략히 예제를 들여 설명해보자.
Y_data의 값으로 axis를 0과 1로 두었을 때의 차이에 대해 설명하겠다.
우선 Y_data는 위에 말했듯이, (2, 3)의 모양을 갖춘 매트릭스이다.
해당 부분을 tf.reduce_sum을 사용하여 계산을 하면, 모든 값들이 합해져, 8이 나온다.
Axis = 0 으로 두면? [2 3 3]
Axis = 1 은? [1 1 1 1 1 1 1 1] 이다.
축을 어떻게 정의하느냐에 따라 배열을 합하는 방향(축)이 달라진다.
Lab-2
해당 내용이, 위의 소스와 가장 큰 차이점이다. 복잡한 식을 1번째 함수와 같이 구현할 수 있지만, 친절하게도 텐서플로우에서는 2번째 함수를 제공하여, 사용자들에게 편리함을 제공한다. 어느 것을 사용하느냐는 개발자의 선택이지만, 아무래도 2번을 더 자주 사용할 것 같다.
그럼 2번째 함수를 사용하여 파일로부터 데이터를 가져와, 동물들을 분류하는 내용을 소스로 만들어본다.
import tensorflow as tf
import numpy as np
xy = np.loadtxt('zoo.csv',
delimiter=',', dtype=np.float32)
x_data = xy[:, 0:-1]
y_data = xy[:, [-1]]
nb_classes = 7
X = tf.placeholder(tf.float32,
[None, 16])
# int로 변환한 이유는 one
hot 적용시 float인 경우 에러가 발생
Y = tf.placeholder(tf.int32, [None,
1])
Y_one_hot = tf.one_hot(Y, nb_classes)
Y_one_hot = tf.reshape(Y_one_hot, [-1,
nb_classes])
W = tf.Variable(tf.random_normal([16, nb_classes]),
name='weight')
b = tf.Variable(tf.random_normal([nb_classes]),
name='bias')
logits = tf.matmul(X, W)
+ b
hypothesis = tf.nn.softmax(logits)
cost_i = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=Y_one_hot)
cost = tf.reduce_mean(cost_i)
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
prediction = tf.argmax(hypothesis, 1)
correct_prediction = tf.equal(prediction,
tf.argmax(Y_one_hot,
1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,
dtype=tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for
step in
range(2000):
sess.run(train, feed_dict={X:
x_data, Y:
y_data})
if
step % 200
== 0:
loss,
accu = sess.run([cost,
accuracy], feed_dict={X: x_data, Y: y_data})
print("step: {:5}\t cost: {:3f}\t
accuracy: {:2%}".format(step, loss,
accu))
pred = sess.run(prediction, feed_dict={X:
x_data, Y:
y_data})
for
p,
y in zip(pred,
y_data.flatten()):
print("[{}] prediction: {}, label: {}".format(p == int(y), p,
y))
해당 소스에서 특이한 점은 데이터를 불러와 int32로 타입을 정의한 부분과, one hot 함수를 사용한 부분, 그리고 softmax_cross_entropy함수를 사용한 부분, 마지막으로 argmax이다.
각각에 대해 설명하면, 우선 int32로 타입을 정의한 이유는, one hot 함수를 사용하기 위함이다. One hot의 함수는 각 숫자(자연수)를 배열의 형태로 나타내주는 함수이다. 예를 들어 2를 one hot 함수로 만들면 [0, 0, 1]와 같은 배열의 형태로 만들어준다. 그런데 해당 부분을 float로 정의를 하게 되면, 2.5, 3.5와 같은 소수의 값이 나타날 수 있기 때문에 배열로 정의하기가 힘들 것 이다.
다음 으로 one_hot 함수를 사용한 후, reshape를 해주는 부분이다. 해당 부분을 쉽게 설명하기 위해, 각각을 호출한 값을 나타내면 아래와 같다.
-- Y
[[0]
[0]
[3]
...]
-- OneHot
[[[ 1. 0. 0. 0. 0. 0. 0.]]
[[ 1. 0. 0. 0. 0. 0. 0.]]
[[ 0. 0. 0. 1. 0. 0. 0.]]
...]
-- OneHot > Reshape
[[ 1. 0. 0. 0. 0. 0. 0.]
[ 1. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 1. 0. 0. 0.]
...]
랭크가 2였던 배열(Y)이 OneHot함수를 사용하여, 랭크가 3으로 변형되었다. 우리가 원하는 배열(답)의 형태는 랭크가 2인 형태이므로, reshape함수를 사용하여, 랭크가 2인 배열로 만들어 준다.
그리고 기존의 방식과는 달리 softmax_cross_entropy_with_logits을 사용하여, cost 함수를 구한다.
마지막으로 argmax는 최대값의 위치를 찾아주는 함수이다. 예를 들어 [0, 0, 1] 을 argmax를 사용하면 2라는 값이 나오게 된다. 가장 큰 값의 위치가 2번째에 있는 1이기 때문이다.
해당 소스를 돌려보면 다음과 같은 결과를 확인할 수 있다.
'AI > Tensorflow' 카테고리의 다른 글
[모두의딥러닝] 딥러닝의 기본 개념과, 문제, 그리고 해결 (0) | 2017.09.03 |
---|---|
[모두의딥러닝] ML의 실용과 몇가지 팁 (0) | 2017.08.23 |
[모두의딥러닝] Logistic (Regression) Classification (0) | 2017.07.29 |
[모두의딥러닝] 여러개의 입력(feature)의 Linear Regression_4 (0) | 2017.07.29 |
[모두의딥러닝] Linear Regression cost함수 최소화_3 (0) | 2017.07.22 |
- 파이썬
- spring
- NIO
- 점프투파이썬
- web
- API
- executor
- python
- serverless
- TDD
- Error
- 머신러닝
- 텐서플로우
- Configuration
- Docker
- 모두의딥러닝
- Gradle
- BigData
- Maven
- memory
- Java
- mysql
- javascript
- AI
- AWS
- ML
- tensorflow
- 중앙정보처리학원
- mybatis
- spark
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |