로지스틱 회귀 : 참과 거짓 중에 하나를 판단하는 것을 만들어 주어진 입력 값의 특징을 추출.
이를 저장해 모델(model)을 만듦. 새 질문이 오면, 그 모델을 꺼내 답을 함.
=> 딥러닝의 원리
1. 로지스틱 회귀의 정의
합격을 1, 불합격을 0이라 함. 이를 좌표 평면으로 표현해보자
S자 형태여야 이들의 데이터를 구분할 수 있음.
로지스틱 회귀는 선형 회귀와 마찬가지로 적절한 선을 그려가는 과정.
선형 회귀와 다른 점은 직선이 아니라, 참(1)과 거짓(0) 사이를 구분하는 S자 형태의 선을 그어주는 작업
2. 시그모이드 함수
e : 자연 상수라고 불리는 무리수, 값은 2.71828...
우리가 구해야 하는 값 : ax + b
a : 그래프의 경사도
b : 그래프의 좌우 이동
a와 b의 값이 클수록 오차가 생긴다.
a 값이 작아지면 오차가 무한대로 커진다. 그러나 a 값이 커진다고 오차가 무한대로 커지지는 않음. 0 으로 수렴한다.
b 값은 너무 작거나 커도 오차가 무한대로 커진다. 이차 함수로 표현이 가능하다.
3. 오차 공식
실제값이 1일 때, 예측 값이 0이면 오차가 커져야 한다. 반대로 실제값이 0일 때, 예측 값이 1이면 오차카 커져야 한다. 이를 공식으로 표현할 수 있게 해주는 함수는 로그(log) 함수다.
4. 로그 함수
위 함수에 해당되는 함수는, -log(h)와 -log(1-h) 함수다. y의 실제 값이 1일 때 -log(h) 그래프를 쓴다. 0일 때 -log(1-h) 그래프를 써야 한다. 이를 식으로 표현하면 다음과 같다.
실제 값 y가 1이면, 뒤 식인 (1-y)log(1-h) 부분이 없어진다. 반대로 0이면 앞 ylog(h) 부분이 없어진다.
5. 코딩으로 확인하는 로지스틱 회귀
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 29 30 31 32 | import tensorflow as tf import numpy as np # x, y의 데이터 값 data = [[2, 0], [4, 0], [6, 0], [8, 1], [10, 1], [12, 1], [14, 1]] x_data = [x_row[0] for x_row in data] y_data = [y_row[1] for y_row in data] # a와 b의 값을 임의로 정한다. a = tf.Variable(tf.random_normal([1], dtype=tf.float64, seed=0)) b = tf.Variable(tf.random_normal([1], dtype=tf.float64, seed=0)) # y 시그모이드 함수의 방정식을 세운다. y = 1/(1 + np.e**(a * x_data + b)) # loss를 구하는 함수 loss = -tf.reduce_mean(np.array(y_data) * tf.log(y) + (1 - np.array(y_data)) * tf.log(1 - y)) # 학습률 값 learning_rate = 0.5 # loss를 최소로 하는 값 찾기 gradient_decent = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss); # 학습 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(60001): sess.run(gradient_decent) if i % 6000 == 0: print("Epoch: %.f, loss = %.4f, 기울기 a = %.4f, y 절편 = %.4f" % (i, sess.run(loss), sess.run(a), sess.run(b))) | cs |
1 2 3 4 5 6 7 8 9 10 11 | Epoch: 0, loss = 1.2676, 기울기 a = 0.1849, y 절편 = -0.4334 Epoch: 6000, loss = 0.0152, 기울기 a = -2.9211, y 절편 = 20.2982 Epoch: 12000, loss = 0.0081, 기울기 a = -3.5637, y 절편 = 24.8010 Epoch: 18000, loss = 0.0055, 기울기 a = -3.9557, y 절편 = 27.5463 Epoch: 24000, loss = 0.0041, 기울기 a = -4.2380, y 절편 = 29.5231 Epoch: 30000, loss = 0.0033, 기울기 a = -4.4586, y 절편 = 31.0675 Epoch: 36000, loss = 0.0028, 기울기 a = -4.6396, y 절편 = 32.3346 Epoch: 42000, loss = 0.0024, 기울기 a = -4.7930, y 절편 = 33.4086 Epoch: 48000, loss = 0.0021, 기울기 a = -4.9261, y 절편 = 34.3406 Epoch: 54000, loss = 0.0019, 기울기 a = -5.0436, y 절편 = 35.1636 Epoch: 60000, loss = 0.0017, 기울기 a = -5.1489, y 절편 = 35.9005 | cs |
오차(loss) 값이 점차 줄어들고 a와 b의 최적값을 찾아간다.
6. 여러 입력 값을 갖는 로지스틱 회귀
변수가 x에서 x1, x2로 추가된다. 따라서 각각의 기울기 a1, a2도 계산해야 한다.
ax => a1x1 + a2x2 으로 바뀐다. a1x1 + a2x2는 행렬곱을 이용해 [a1, a2] ✻ [x1, x2]로도 표현할 수 있다.
텐서플로에서는 matmul() 함수를 이용한다.
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import tensorflow as tf import numpy as np # 실행할 때마다 같은 결과를 출력하기 위한 seed 값 설정 seed = 0 np.random.seed(0) tf.set_random_seed(seed) # x, y의 데이터 값 x_data = np.array([[2, 3,], [4, 3], [6, 4], [8, 6], [10, 7], [12, 8], [14, 9]]) y_data = np.array([0, 0, 0, 1, 1, 1, 1]).reshape(7, 1) # 입력 값을 플레이스 홀더에 저장 X = tf.placeholder(tf.float64, shape=[None, 2]) Y = tf.placeholder(tf.float64, shape=[None, 1]) # 기울기 a와 바이어스 b의 값을 임의로 정함 a = tf.Variable(tf.random_uniform([2, 1], dtype=tf.float64)) # [2, 1] 의미 : 들어오는 값은 2개, 나가는 값은 1개 b = tf.Variable(tf.random_normal([1], dtype=tf.float64, seed=0)) # y 시그모이드 함수의 방정식을 세운다. y = tf.sigmoid(tf.matmul(X, a) + b) # loss를 구하는 함수 loss = -tf.reduce_mean(Y * tf.log(y) + (1 - Y) * tf.log(1 - y)) # 학습률 값 learning_rate = 0.1 # loss를 최소로 하는 값 찾기 gradient_decent = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss); predicted = tf.cast(y > 0.5, dtype=tf.float64) accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float64)) # 학습 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(3001): a_, b_, loss_, _ = sess.run([a, b, loss, gradient_decent], feed_dict={X: x_data, Y: y_data}) if (i+1) % 300 == 0: print("step=%d, a1=%.4f, a2=%.4f, b=%.4f, loss=%.4f" % (i + 1, a_[0], a_[1], b_, loss_)) new_x = np.array([7, 6]).reshape(1, 2) # [7, 6]은 각각 공부한 시간과 과외 수업 횟수 new_y = sess.run(y, feed_dict={X: new_x}) print("공부한 시간: %d, 과외 수업 횟수: %d" % (new_x[:, 0], new_x[:, 1])) print("합격 가능성: %6.2f %%" % (new_y*100)) | cs |
오차(loss) 값이 점차 줄어들고, a1, a2와 b가 각각 최적값을 찾아간다.
7. 실제 값 적용하기
1 2 3 4 5 | new_x = np.array([7, 6]).reshape(1, 2) # [7, 6]은 각각 공부한 시간과 과외 수업 횟수 new_y = sess.run(y, feed_dict={X: new_x}) print("공부한 시간: %d, 과외 수업 횟수: %d" % (new_x[:, 0], new_x[:, 1])) print("합격 가능성: %6.2f %%" % (new_y*100)) | cs |
1 2 | 공부한 시간: 7, 과외 수업 횟수: 6 합격 가능성: 86.16 % | cs |
8. 로지스틱 회귀에서 퍼셉트론으로
입력 값을 통해 출력 값을 구하는 함수 y는 다음과 같이 표현한다.
입력값 x1, x2 값을 가지고 있다. 출력값 y를 구해야 한다. 이 때 a 값과 b 값이 필요하다. 이를 그림으로 표현하면 다음과 같다.
x1, x2 가 입력됨. 가중치 a1, a2를 만남. 여기에 b 값을 더해 시그모이드 함수를 거쳐 1또는 0의 출력 값 y를 출력. 이 개념을 '퍼셉트론(perceptron)' 이라는 이름을 붙임.
이는 인공 신경망, 오차 역전파 등의 발전을 거쳐 지금의 딥러닝으로 이어지게 됨
'인공지능 > 딥 러닝' 카테고리의 다른 글
[모두의 딥러닝] 06. 퍼셉트론 (0) | 2018.05.06 |
---|---|
[모두의 딥러닝] 04. 오차 수정하기: 경사 하강법 (0) | 2018.05.06 |
[모두의 딥러닝] 03. 가장 훌륭한 예측선 긋기: 선형회귀 (1) | 2018.04.05 |
[모두의 딥러닝] 02. 처음 해 보는 딥러닝 (0) | 2018.04.05 |
[모두의 딥러닝] 01. 파이썬과 텐서플로, 케라스 설치하기 (0) | 2018.03.27 |
댓글