Codong's Development Diary RSS 태그 관리 글쓰기 방명록
2021-06-23 16:16:23

개요


딥 러닝을 이용한 자연어 처리 입문

저번 글에서 머신러닝을 간략하게 살펴보았고, 딥러닝을 이해하기 위한 요소들에 대해 좀 더 자세하게 알아보도록 하자.

1. 선형 회귀(Linear Regression)


딥러닝을 이해하기 위해서는 선형 회귀(Linear Regression)와 로지스틱 회귀(Logistic Regression)를 이해할 필요가 있다. 뿐만 아니라 머신 러닝에서 쓰이는 용어인 가설(Hypothesis), 손실 함수(Loss Function) 그리고 경사 하강법(Gradient Descent)에 대한 개념과 선형 회귀에 대해서 이해합니다.

1.1 선형 회귀란?

시험 공부하는 시간을 늘리면 늘릴 수록 성적이 잘 나온다. 하루에 걷는 횟수를 늘릴 수록, 몸무게는 줄어든다. 집의 평수가 큰 수록, 집의 매매 가격은 비싼 경향이 있다. 이는 수학적으로 생각해보면 어떤 요이의 수치에 따라서 특정 요인의 수치가 영향을 받고 있다고 말할 수 있다. 좀 더 수학적인 표현을 써보면 어떤 변수의 값에 따라 특정 변수의 값이 영향을 받고 있다고 볼 수 있다.

이와 같이 다른 변수의 값을 변하게하는 변수를 x, 변수 x에 의해서 값이 종속적으로 변하는 변수 y라고 해봅시다. 선형 회귀는 한 개 이상의 독립 변수 X와 종속 변수 y의 선형 관계를 모델링한다. 만약 독립 변수 x가 1개라면 단순 선형 회귀라고 한다.

1️⃣ 단순 선형 회귀 분석(Simple Linear Regression Analysis)

$y = Wx + b$

위 수식은 단순 선형 회귀의 수식을 보여준다. 여기서 독립 변수 x와 곱해지는 값 W를 머신 러닝에서는 가중치(weight), 별도로 더해지는 값 b를 편향(bias)이라고 한다. 직선의 방정식에서 각각 직선의 기울기와 절편을 의미한다. W와 B가 없이 y와 x란 수식은 y는 x와 같다는 하나의 식밖에 표현하지 못하므로, W와 b의 값을 적절히 찾아내면 x와 y의 관계를 적절히 모델링한 것이 된다.

2️⃣ 다중 선형 회귀 분석(Multiple Linear Regression Analysis)

$y = W_1x_1 + W_2x_2 + W_3x_3 + ... + W_nx_n + b$

잘 생각해보면 집의 매매 가격은 단순히 집의 평수가 크다고 결정되는 것이 아니라 집의 층 수, 방의 개수, 지하철 역과의 거리와도 영향이 있는 것 같다. 이제 이러한 다수의 요소를 가지고 집의 매매 가격을 예측해보고 싶다. y는 여전히 1개이지만 이제 x는 1개가 아니라 여러 개가 되었다. 이와 같이 여러 독립 변수들을 가지고 회귀 분석을 하는 것을 다중 선형 회귀 분석이라 한다.

1.2 가설(Hypothesis) 세우기

단순 선형 회귀를 이용하여 문제를 풀어보자. 어떤 학생의 공부 시간에 따라 다음과 같은 점수를 얻었다고 가정하고, 좌표 평면에 그려보자.

알고있는 데이터로부터 x와 y의 관계를 유추하고, 이 학생이 6시간, 7시간, 8시간을 공부하였을 때의 성적을 예측해보고 싶다. x와 y의 관계를 유추하기 위해서 수학적으로 식을 세워보게 되는데 머신 러닝에서는 이러한 식을 가설(Hypothesis)이라고 한다. 사실 선형 회귀의 가설은 이미 아래와 같이 널리 알려져있다.

위 그림은 W와 b의 값에 따라서 천차만별로 그려지는 직선의 모습을 보여준다. W는 직선의 기울기고, b는 절편으로 직선을 표현함을 알 수 있다. 결국 선형 회귀는 주어진 데이터로부터 y와 x의 관계를 가장 잘 나타내는 직선을 그리는 일을 말한다.

그러면 어떻게 가장 최적의 직선을 그릴 수 있을까?

1.3 비용 함수(Cost function) : 평균 제곱 오차(MSE)

머신 러닝은 W와 b를 찾기 위해서 실제값과 가설로부터 얻은 예측값의 오차를 계산하는 식을 세우고, 이 식의 값을 최소화하는 최적의 W와 b를 찾아낸다. 이 때 실제값과 예측값에 대한 오차에 대한 식을 목적 함수(Objective function) 또는 비용 함수(Cost function) 또는 손실 함수(Loss function)라고 한다.

비용 함수는 단순히 실제값과 예측값에 대한 오차를 표현하면 되는 것이 아니라, 예측값의 오차를 줄이는 일에 최적화 된 식이어야 한다. 즉, 다양한 문제들에 적합한 비용 함수들이 있다는 것이다. 회귀 문제의 경우에는 주로 평균 제곱 오차(Mean Squared Error, MSE)가 사용된다.

위 그래프에서 그린 직선은 임의로 그린 직선으로 정답이 아니다. 이제 이 직선을 서서히 W와 b의 값을 바꾸면서 정답인 직선을 찾아내야 한다. y와 x의 관계를 가장 잘 나타내는 직선을 그린다는 것은 위의 그림에서 모든 점들과 위치적으로 가장 가까운 직선을 그린다는 것과 같다.

자 그럼 오차를 구해보자. 오차는 주어진 데이터에서 각 x에서의 실제 값 y와 위의 직선에서 예측하고 있는 H(x) 값의 차이를 말한다. 즉 위의 그림에서 빨간 화살표가 각 점에서 오차의 크기를 보여준다. 즉, 이 오차를 줄여가면서 W와 b의 값을 찾아내기 위해 전체 오차의 크기를 구해야 한다.

오차의 크기를 측정하기 위한 가장 기본적인 방법은 각 오차를 모두 더하는 방법이다. 그런데 수식적으로 단순히 '오차 = 실제값 - 예측값'이라 정의한 후에 모든 오차를 더하면 음수 오차도 있고, 양수 오차도 있으므로, 오차의 절대적인 크기를 구할 수가 없다. 그래서 모든 오차를 제곱하여 더하는 방법을 사용한다. 여기서 데이터 개수 만큼 나누어 평균을 구한다. 그리하여 평균 제곱 오차를 구할 수 있다. 수식으로 보면 다음과 같다.
$cost(W,b)=\frac{1}{n}\sum^{n}_{i=1}[y^{(i)}-H(x^{(i)})]^2$

모든 점들과의 오차가 클 수록 이 값은 커지고, 오차가 작을 수록 평균 제곱 오차는 작아진다. 결과적으로 이 Cost(W,b)가 최소가 되게 만드는 W와 b를 구하면 y와 x의 관계를 가장 잘 나타내는 직선을 그릴 수 있다.

1.4 옵티마이저(Optimizer) : 경사하강법(Gradient Descent)

선형 회귀를 포함한 수많은 머신 러닝, 딥 러닝의 학습은 결국 비용 함수를 최소화하는 매개 변수인 W와 b를 찾기 위한 작업을 수행한다. 이때 사용되는 알고리즘을 옵티마이저(Optimizer) 또는 최적화 알고리즘이라고 부른다.

이 옵티마이저를 통해 적절한 W와 b를 찾아내는 과정을 머신 러닝에서 학습(traning)이라고 부른다. 가장 기본적인 옵티마이저 알고리즘인 경사 하강법(Gradient Descent)에 대해 알아보자. 그전에 cost와 기울기 W와의 관계를 살펴보면, 아래 그래프를 통해 W가 지나치게 높거나 낮을 때 어떻게 오차가 커지는지 보여준다.

주황색 선은 기울기 W가 20일 때, 초록색 선은 1일 때를 보여준다. 설명의 편의를 위해 편향 b가 없이 단순히 가중치 W만을 사용한 가설을 가지고 경사 하강법을 수행한다고 해보자. 이런 기울기 W와 cost 함수와의 관계를 그래프로 표현하면 아래와 같다.

기울기 W가 무한대로 커지거나 작아진다면 cost 값 또한 무한대로 커진다. 위 그래프에서 cost가 가장 작을 때는 볼록한 부분의 맨 아래 부분이다. 기계는 이 cost가 가장 최소값을 가지게 하는 W를 찾는 일이다.

기계는 임의의 랜덤 W값을 정한 뒤, 맨 아래 볼록한 부분을 향해 점차 W의 값을 수정해 나간다. 이를 가능하게 하는 것이 경사 하강법(Gradient Descent)이며, 수행하기 위해서는 미분을 이해해야 한다. 미분의 개념 중 한 점에서의 순간 변화율 또는 접선에서의 기울기의 개념을 이용한다.

위 그림에서 초록색 선은 W가 임의의 값을 가지게 되는 네 가지의 경우에 대해서, 그래프 상으로 접선의 기울기를 보여준다. 주목할 것은 맨 아래의 볼록한 부분으로 갈수록 접선의 기울기가 점차 작아진다는 점이다. 그렇게 점차 작아지다가 cost가 최소가 되는 지점에서 접선의 기울기가 0이 된다. 즉, 경사하강법의 아이디어는 비용 함수(cost function)를 미분하여 현재 W에서 접선의 기울기를 구하고, 접선의 기울기가 낮은 방향으로 W의 값을 변경하고 이 과정을 접선의 기울기가 0인 곳을 향해 W의 값을 변경하는 작업을 반복하는 것에 있다.

$W := W- \alpha \frac{\partial}{\partial W} cost(W)$

위의 식은 현재 W에서의 접선의 기울기와 $\alpha$를 곱한 값을 현재 W에서 빼서 새로운 W의 값으로 정한다는 것(update)을 의미한다. 여기서 $\alpha$는 학습률(learning rate)이라고 하는데, 우선은 현재 W에서 현재 W의 접선의 기울기를 뺴는 행위가 어떤 의미인지 보자.

위 그림에서 접선의 기울기가 음수일 때, 0일 때, 양수일 때의 경우를 보여준다. 위에서 W 값을 update하는 식을 사용하면 식이 아래와 같이 변형 될 수 있다.

$W := W - \alpha \times (-기울기) = W + \alpha \times (기울기)$

W의 값이 더해지면서 0에 가까운 방향으로 수정됨을 알 수 있다. 반대의 경우는 어떨까? 기울기가 양수일 경우면 다음과 같이 된다.

$W := W - \alpha \times (기울기)$

양수일 때에는 W값이 매우 컷기 때문에 빼준다. 결과적으로 기울기가 0인 방향으로 W값이 조정된다.
그렇다면 여기서 학습률(learning rate)는 무슨 의미일까? 학습률 $\alpha$는 W의 값을 변경할 때, 얼마나 크게 변경할지를 결정한다. 또는 W를 그래프의 한 점으로보고 접선의 기울기가 0일 때까지 경사를 따라 내려간다는 관점에서는 얼마나 큰 폭으로 이동할지를 결정한다.

직관적으로 생각하기에 학습률 $\alpha$의 값을 무작정 크게 하면 금방 기울기가 0이 되는 W를 찾을 수 있을 것 같지만 그렇지 않다.

위 그림은 학습률 $\alpha$가 지나치게 높은 값을 가질 때, 접선의 기울기가 0이 되는 W를 찾아가는 것이 아니라 W의 값이 발산하는 상황을 보여준다. 반대로 학습률이 지나치게 낮은 값을 가지면 학습 속도가 느려지므로 적당한 $\alpha$값을 찾아내는 것도 중요하다.

2. 로지스틱 회귀(Logistic Regression)


일상 속 풀고자하는 많은 문제 중 두 개의 선택지 중에서 정답을 고르는 문제가 많다. 이렇게 둘 중 하나를 결정하는 문제를 이진 분류(Binary Classification)라고 한다. 그리고 이런 문제를 풀기 위한 대표적인 알고리즘으로 로지스틱 회귀(Logistic Regression)가 있다.

2.1 이진 분류(Binary Classification)

앞서 설명한 선형 회귀 챕터에서 공부 시간과 성적 간의 관계를 직성의 방정식으로 표현을 했다. 하지만 이번 문제는 직선으로 표현하는 것이 적절하지 않다.

학생들이 시험 성적에 따라 합격, 불합격이 기재된 데이터가 있다고 가정해보자. 시험 성적이 x라면 합불 결과는 y다. 이 시험의 커트라인은 공개되지 않았는데 이 데이터로부터 특정 점수를 얻었을 때의 합격, 불합격 여부를 판정하는 모델을 만든다고 하자.

이러한 점들을 표현하는 그래프는 알파벳의 S자 형태로 표현된다. 이런 x,y 관계를 표현하기 위해서는 S자 형태로 표현할 수 있는 함수가 필요하다. 또한 실제값 y가 0또는 1이라는 두 가지 값밖에 가지지 않으므로 이 문제를 풀기 위해서 예측값이 0과 1사이의 값을 가지도록 하는 것이 보편적이다. 이 값을 확률로 해석하면 문제를 풀기가 훨씬 용이해진다. 최종 예측값이 0.5보다 작으면 0으로 예측했다고 판단하고, 0.5보다 크면 1로 예측했다고 판단할 수 있기 때문이다.

이 조건들을 충족하는 함수가 있다. 그것은 바로.. 시그모이드 함수(Sigmoid function)이다.

2.2 시그모이드 함수(Sigmoid function)

시그모이드 함수의 방정식부터 살펴보자. 종종 $\sigma$로 축약해서 표현하기도 한다. 이는 위 문제를 풀기 위한 가설식이기도 한다.
$H(X) = \frac{1}{1+e^{-(Wx+b)}} = sigmoid(Wx+b) = \sigma(Wx+b)$

여기서 e는 자연 상수다. 여기서 구해야할 것은 여전히 주어진 데이터에 가장 적합한 가중치 W(Weight)와 편향 b(Bias)이다.
matplotlib을 이용하여 시그모이드 함수 그래프를 쉽게 그려볼 수 있다.

%matplotlib inline
import numpy as np # 넘파이 사용
import matplotlib.pyplot as plt # 맷플롯립 사용

def sigmoid(x):
    return 1/(1+np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)

plt.plot(x, y, 'g')
plt.plot([0,0],[1.0,0.0], ':') # 가운데 점선 추가
plt.title('Sigmoid Function')
plt.show()

위의 그래프는 가중치(W)는 1, 편향(b)은 0임을 가정한 그래프입니다.

여기서 구해야할 가중치 W와 편향 b가 어떤 의미를 가지는지 한 번 그래프를 통해 알아보자.

def sigmoid(x):
    return 1/(1+np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y1 = sigmoid(0.5*x)
y2 = sigmoid(x)
y3 = sigmoid(2*x)

plt.plot(x, y1, 'r', linestyle='--') # W의 값이 0.5일때
plt.plot(x, y2, 'g') # W의 값이 1일때
plt.plot(x, y3, 'b', linestyle='--') # W의 값이 2일때
plt.plot([0,0],[1.0,0.0], ':') # 가운데 점선 추가
plt.title('Sigmoid Function')
plt.show()

위 그래프는 W의 값이 0.5일때 빨간색선, 1일때 초록색선, 2일때 파란색선이 나오도록 했다. 그 결과 W 값의 변화를 통해 경사도가 변하는 것을 알 수 있다. 즉 W의 값이 커지면 경사가 커지고, 작아지면 완만해짐을 알 수 있다.

b 값의 변화에도 그래프가 어떻게 변하는지 확인해보자.

def sigmoid(x):
    return 1/(1+np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y1 = sigmoid(x+0.5)
y2 = sigmoid(x+1)
y3 = sigmoid(x+1.5)

plt.plot(x, y1, 'r', linestyle='--') # x + 0.5
plt.plot(x, y2, 'g') # x + 1
plt.plot(x, y3, 'b', linestyle='--') # x + 1.5
plt.plot([0,0],[1.0,0.0], ':') # 가운데 점선 추가
plt.title('Sigmoid Function')
plt.show()

b의 값이 0.5 일때 빨간색, 1일 때 초록색, 1.5일때 파란색이다. 중심을 기준으로 봤을 때 좌우로 움직이는 것을 볼 수 있다. 즉 W와 b를 변경하면서 최적의 x와 y의 값을 표현하는 S자 그래프를 찾아가는 것이다. 시그모이드 함수는 입력값이 커지면 1에 수렴하고, 입력값이 작아지면 0에 수렴한다. 그리고 0부터 1까지의 값을 가지므로 출력값이 0.5 이상이면 1(True), 0.5이하면 0(False)로 만들면 이진 분류 문제로 사용할 수 있다. 이를 확률이라고 생각하면 해당 범주에 속할 확률이 50%가 넘으면, 해당 범주라고 판단하고 낮으면, 아니라고 판단한다고도 볼 수 있다.

2.3 비용 함수(Cost Function)

로지스틱 회귀 또한 경사 하강법을 사용하여 가중치 W를 찾아내지만, 비용 함수로는 평균 제곱 오차를 사용하지 않는다. 시그모이드 함수에 비용함수를 평균 제곱 오차로 하여 그래프를 그리면 다음과 비슷한 형태가 되기 때문이다.

로지스틱 회귀에서 평균 제곱 오차를 비용 함수로 사용하면, 경사 하강법을 사용할 때 자칫 잘못하면 찾고자 하는 최소값이 아닌 잘못된 최소값에 빠진다. 이를 전체 함수에 걸쳐 최소값인 글로벌 미니멈(Global minimum)이 아닌 특정 구역에서의 최소값인 로컬 미니멈(Local minimum)에 도달했다고 한다. 이는 cost가 최소가 되는 가중치 W를 찾는다는 비용 함수의 목적에 맞지 않다.

그렇다면 어떻게 하면 좋을까?

$J(W) = \frac{1}{n}\sum_{i=1}^{n}cost(H(x^{(i)}),y^{(i)}))$

우리의 목표는 위의 미완성 식을 가중치를 최소화하는 적절한 목적 함수를 만드는 것이다. 여기서 J는 목적 함수(objective function)이고, H(x)는 예측값, y는 실제값이다. 시그모이드 함수는 0과 1사이의 y값을 반환한다. 이는 실제값이 0일 때 예측값이 반대인 1에 가까워 질 때 오차가 커짐을 할 수 있다. 이를 반영할 수 있는 함수는 로그 함수를 통해 표현이 가능하다.

👆 log x는 x의 값이 0에 가까울 수록 음의 무한대 값으로 발산하고, 1에 가까울 수록 0에 수렴한다.

$if y = 1 -> cost(H(x),y) = - log(H(x))$
$if y = 0 -> cost(H(x),y) = - log(1-H(x))$

즉 실제값이 1일 때의 예측값인 H(X)의 값이 1이면 오차가 0이므로 당연히 cost는 0이 된다.
반면, H(X)가 0으로 수렴하면 cost는 무한대로 발산한다. 이는 다음과 같이 하나의 식으로 표현할 수 있다.

$cost(H(x),y) = -[ylogH(x) + (1-y)log(1-H(x))]$

자세히 보면 y와 (1-y)가 식 중간에 들어갔고, 두 개의 식을 -로 묶은 것 외에는 기존의 두 식이 들어가 있는 것을 볼 수 있다.

  1. y가 0이면 $ylogH(x)$가 없어지고,
  2. y가 1이면 $(1-y)log(1-H(x))$가 없어진다.

이는 앞서 본 식을 모두 포괄하는 식이 된다.

결과적으로 로직스틱 회귀의 목적 함수를 정리하면 아래와 같다.

$J(W) = - \frac{1}{n}\sum_{i=1}^n[y^{(i)}logH(x^{(i)}+(1-y^{(i)})log(1-H(x^{(i)}))]$

이때 로지스틱 회귀에서 찾아낸 비용함수를 크로스 엔트로피(Cross Entropy)함수라고 한다.
즉, 결론적으로 로지스틱 회귀는 비용 함수로 크로스 엔트로피 함수를 사용하며, 가중치를 찾기 위해서 크로스 엔트로피 함수의 평균을 취한 함수를 사용한다. 크로스 엔트로피 함수는 소프트맥스 회귀의 비용 함수이기도 하다.

➕ cross entropy에 대해..

우선 entropy는 정보량을 의미한다. 불확실성(랜덤성)이 클수록 entropy 값이 커진다고 한다. (+모든 사건이 같은 확률로 일어나는 것이 가장 불확실하다고 한다.)

그럼 cross entropy는 두 가지의 경우에 entropy를 비교하는 것이 아닐까 라는 추측을 조심스래 해본다.
수식으로 먼저 보자. $H(p,q) = \sum_{i} p_i log_2\frac{1}{q_i} = -\sum_{i} p_i log_2 q_i$
대개 머신러닝에서 cross entropy를 사용할 때, $p_i$ 가 특정 확률에 대한 참값 또는 목표 확률이고, $q_i$가 우리가 예측한 확률 값이 된다. 즉, $q_i$를 학습하고 있는 상태라면 $p_i$에 가까워질수록 cross entropy의 값은 작아지게 된다.

cross entropy는 log loss로 불리기도 한다. cross entropy를 최소화하는 것은 log likeihood를 최대화하는 것과 같기 때문이다. ->아직 이 말이 왜 그런지 이해하진 못했다.
어떤 데이터가 0 또는 1로 predict될 확률은 $\hat{y}, 1-\hat{y}$ 이므로 y가 0과 1의 값만 가질 때 likelihood식을 이렇게 세울 수 있다고 한다.
$\hat{y}^y(1-\hat{y})^{(1-y)}$

y=1일 때 $\hat{y}$ 최대화 시켜야하고, y=0일 때는 $(1-\hat{y})$를 최대화시켜야 한다. 여기에 log를 씌우면 다음과 같이 정리 된다.
$maximize : y log \hat{y} + (1-y)log(1-\hat{y}) = minimize : -y log \hat{y} + (1-y)log(1-\hat{y})$
최소화 해야 하는 식은 우리가 방금 살펴본 cross entropy와 똑같은 식이다. 이러한 이유로 log loss라고 부르기도 한다. 또 나아가 자연스럽게 cross entropy는 negative log likelihood로 불리기도 한다.

  • 요약
    1. binary classification에 나오는 logistic regression cost function은 cross entropy 식과 같다.
    2. cross entropy와 log loss, negative log likelihood 다 유사하게 쓰이는 것 같다.
    3. 결국 훈련시 cross entropy로 두 확률 분포간의 차이를 loss 값으로 이용하여 파라미터를 수정하는 것 같다.

위 내용은 현재까지 내가 이해한 것이며, 답이 아님을 말하고 싶다. 아직 정확히 내가 이해하지 못하고 적은 것이라 제대로 알게 될 때마다 수정하려고 한다. 잘못된 것이 있다면 참고링크나, 알려주시면 감사하겠습니다~~

reference