선형 모형
딥러닝, 머신 러닝 등에서 가장 기본적은 선형 모형(linear model)입니다. 데이터가 직선 형태를 이루고 있을 것이라고 가정하기 때문에 선형 모형이라고 합니다. 선형 모형을 수식으로 나타내면 다음과 같은 직선의 방정식 형태가 됩니다.
$$ y = wx + b $$
$x$와 $y$는 데이터입니다. $w$는 직선의 기울기입니다. 가중치(weight)나 계수(coefficient)라고도 합니다.
$w$와 $b$는 모형의 형태를 결정하는 값으로 파라미터(parameter)라고 합니다.
$b$는 $x = 0$일 때 $y$의 값으로 $y$ 절편(intercept)이라 하고, 그냥 절편이라고 하거나 또는 편향(bias)이라고도 합니다.
예제 데이터
파이썬 시각화 라이브러리인 seaborn
에 내장된 예제 데이터로 선형 모형을 학습시켜보겠습니다.
import seaborn as sns
seaborn
내장 데이터 중에 tips
데이터를 사용합니다.
tips = sns.load_dataset("tips")
tips.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
이 데이터에는 영수증에 찍힌 가격(total_bill
)과 고객이 준 팁(tip
)이 기록되어 있습니다. 이 두 변수의 관계를 시각화해보면 대체로 선형적인 관계가 있음을 확인할 수 있습니다.
sns.regplot('total_bill', 'tip', tips)
<matplotlib.axes._subplots.AxesSubplot at 0x2038cb751c8>
텐서플로를 이용해 선형 모형 만들기
텐서플로를 이용해서 선형 모형을 만들어보겠습니다.
먼저 텐서플로를 임포트합니다.
import tensorflow as tf
텐서플로에서 keras
는 다양한 모형을 쉽게 만들 수 있는 방법을 제공합니다. 먼저 Sequential
을 이용해 빈 모형을 만듭니다.
model = tf.keras.models.Sequential()
다음으로 레이어(layer)를 만듭니다. 레이어는 어떤 $x$를 입력 받아, $y$를 출력하는 형태의 계산을 표현합니다. 선형 모형은 $y = wx + b$ 형태의 계산인데, 이런 계산은 Dense
레이어를 사용합니다.
출력하는 $y$도 하나이므로 Dense
의 첫 번째 인자는 1
이라고 써줍니다.
입력하는 $x$도 하나이므로 input_shape
에는 (1, )
라고 해줍니다. 그냥 1
이라고 하지 않고 (1, )
이라고 하는 이유는 나중에 다른 강의에서 자세히 설명할 것입니다. 여기서는 일단 (1, )
라고 한다고 알아둡시다.
layer = tf.keras.layers.Dense(1, input_shape=(1,))
모형에 레이어를 추가하면 선형 모형이 완성됩니다.
model.add(layer)
선형 모형 학습시키기
이제 앞서 만들어둔 데이터로 선형 모형을 학습시켜보겠습니다. 여기서 모형을 학습시킨다는 것은 데이터를 통해 $w$와 $b$의 적절한 값을 알아낸다는 것입니다. 현재는 우리가 손으로 만든 데이터이기 때문에 $w$와 $b$가 각각 2, 1이라는 것을 알고 있지만 실제 데이터의 경우에는 학습을 통해 알아내야 합니다.
학습시키기 전에 먼저 모형을 설정해야 합니다. optimizer
는 모형을 적합시키는 알고리즘입니다. 여기서는 어떤 알고리즘을 쓰더라도 큰 차이가 없기 때문에 가장 간단한 sgd
를 사용하겠습니다.
loss
는 학습한 $w$와 $b$를 이용해서 $wx + b$를 계산한 값과 실제 $y$의 오차를 구해서 모형의 정확성을 측정하는 방법입니다. $y$가 연속 변수일 경우에는 mse
를 많이 사용한다. mse
는 평균오차제곱(Mean Squared Error)이라는 뜻으로 예측 오차의 제곱을 평균 낸 값입니다.
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.01),
loss='mse')
이제 학습을 시작하겠습니다. 학습은 임의의 파라미터로 시작합니다. 모형에 데이터를 입력하면 오차를 구할 수 있는데, 이때 오차가 줄어드는 방향으로 파라미터를 수정합니다. 샤워기의 온도를 맞출 때 물이 뜨거우면 왼쪽으로 돌리고, 물이 차가우면 오른쪽으로 돌리는 과정을 반복해서 온도를 맞추는 것과 비슷합니다.
학습에서 한 번의 과정을 epoch라고 합니다. epoch를 늘리면 학습을 더 많이 하므로 파라미터가 좀 더 정확하게 추정될 것입니다. 여기서는 30 epoch를 하겠습니다.
verbose=0
을 verbose=1
로 수정하면 진행상황을 실시간으로 확인할 수 있습니다.
x = tips['total_bill'].values
y = tips['tip'].values
result = model.fit(x, y, epochs=30, verbose=0)
학습된 파라미터를 확인합니다. 첫번째 파라미터가 $w$에 해당하는 값이고, 두번째가 $b$에 해당하는 값입니다.
model.weights
[<tf.Variable 'dense_14/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[0.18558289]], dtype=float32)>, <tf.Variable 'dense_14/bias:0' shape=(1,) dtype=float32, numpy=array([-0.92574245], dtype=float32)>]
한 epoch다 loss가 얼마나 감소했는지를 확인합니다. 처음에 빠르게 줄어들다가 0에 가까워지면서 점점 기울기가 완만해집니다. 데이터가 완전히 직선 상에 있는 것은 아니므로 loss가 0이 될 수는 없습니다.
plt.plot(result.history['loss'])
[<matplotlib.lines.Line2D at 0x20388e452c8>]