프로그래밍 공부
카테고리
작성일
2024. 6. 13. 12:23
작성자
WDmil
728x90

머신러닝의 프로세스는 다음 3가지 과정을 거친다.

 

  1. 학습하고자 하는 가설(Hypothesis) h(세타)을 수학적 표현식으로 표현
  2. 가설의 성능을 측정할 수 있는 손실함수(LossFunction) J(세타)을 정의한다.
  3. 손실함수 J(세타)를 최소화(Minimize)할 수 있는 학습 알고리즘을 설계한다.

 

선형 회귀 모델에 대입하여 생각하면 다음과 같다.

선형 회귀 모델은 선형 함수를 이용해서 회귀를 수행하는 기법.

 

다음 가설로 표현한다.

 

$ y = Wx + b $

이 때 x 와 y는 데이터로부터 주어지는 인풋데이터, 타겟데이터 이고 W와 b는 파라미터 세타 라고 부르며, 트레이닝데이터 로부터 학습을 통해 적절한 값을 내야하는값.


손실함수

여러가지 형태로 정의될 수 있지만, 그중 가장 대표적인 손실 함수 중 하나는 평균 제곱 오차이다.

 

MSE는 다음 수식으로 나타낸다.

$ MSE = \frac{1}{2n}\sum_{n}^{i=1}(\hat{y}_{i}-\hat{y}_{i})^{2} $

 

예를들어 정답이 y = [1, 10, 13, 7] 이고,

모델이 y = [10, 3, 1, 4] 와 같이 잘못된 값을 예측하면

MSE 손실 함수는 35.375라는 큰 값을 도출한다.

 

$ MSE = \frac{1}{2 * 4}{((10 - 1)^{2} + (3 - 10)^{2} + (1 - 13)^{2} + (4 - 7)^{2})} = 1.5 $

 

하지만, 예측값이 [ 2, 10, 11, 6 ] 와 같이 유사하다면, 손실함수는 다음과 같은 결과가 나타난다.

$ MSE = \frac{1}{2 * 4}{((2 - 1)^{2} + (10 - 10)^{2} + (11 - 13)^{2} + (6 - 7)^{2})} = 1.5 $

 

손실함수는 목적에 가까운 형태로 파라미터가 최적화되었을 때, 더 작은 값을 갖는 특성을 가져야 한다.

 

이러한 손실함수를 다른말로 비용 함수 라고 부른다.

 

그냥 임의의 함수로, 오차가 나타난다는걸 표현할 수 있는 수식이면 전부다 손실함수로 기용할 수는 있기는 하다.


선형회귀 직접 구현작업 해보기

import tensorflow as tf
import matplotlib.pyplot as plt

# 선형회귀 모델 (Wx + b)을 위한 tf.Variable을 선언
W = tf.Variable(tf.random.normal(shape=[1]))
b = tf.Variable(tf.random.normal(shape=[1]))

# 가설 정의 함수 생성
@tf.function
def linear_model(x):
    return W * x + b

# 손실 함수 정의
# MSE 손실 함수 \mean{(y' - y)^2}
@tf.function
def mse_loss(y_pred, y):
    return tf.reduce_mean(tf.square(y_pred - y))

# 최적화를 위한 그라디언트 디센트 옵티마이저를 정의
optimizer = tf.optimizers.SGD(0.01) # 가장 기본적인 옵티마이저

# 최적화를 위한 function을 정의
@tf.function
def train_step(x, y):
    with tf.GradientTape() as tape:
        y_pred = linear_model(x)
        loss = mse_loss(y_pred, y)
    gradients = tape.gradient(loss, [W, b])
    optimizer.apply_gradients(zip(gradients, [W, b]))

# 트레이닝을 위한 입력값과 출력값을 준비
x_train = [1, 2, 3, 4]  # 인풋으로 1, 2, 3, 4 를 넣으면
y_train = [2, 4, 6, 8]  # 아웃풋 으로 2, 4, 6, 8 이 나와야 한다.

# numpy array로 변환
x_train = tf.constant(x_train, dtype=tf.float32)
y_train = tf.constant(y_train, dtype=tf.float32)

# 학습 과정 실행
for i in range(1000):
    train_step(x_train, y_train)

# 테스트 입력값 준비
x_text = [3.5, 5, 5.5, 6]

# 테스트 데이터를 이용해 학습된 선형회귀 모델이 데이터의 경향성 (y = 2x)인지 
# 확인

# 학습 후 결과 출력
print(linear_model(x_text).numpy())
# 예상참값. [7, 10, 11, 12]

# 학습된 모델 시각화
plt.scatter(x_text, x_text, label='Input Point')
plt.scatter(x_text, linear_model(x_text).numpy(), label='Result Point')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

 

Visual Code로 구현하여 작업한다.

 

우리가 찾으려는 값은 W, b이다.

y = W * x + b 라는 수식이기 때문에, 아직 정의되어있지 않은 W와 b를 찾아가는 과정.

 

랜덤한 임의의 W와 b로 값을 도출하고, 도출된 결과값에 loss값을 확인, loss에 따라 W와 b를 재조정 한 후 다시 반복한다.

 

이걸 for문으로 1000번 반복하여 결과를 수렴시키면 원하는 W와 b값이 나타나게 된다.

그리고 이 결과가 제곱승이 되는것.

결과는 위와같이 나타난다. 3.5가 인풋으로 들어가면 7이 나타나는걸 확인할 수 있다.

 

물론, 직접 구현할수는 있다. 선형회귀 임으로, 수식값에 W와 b에 수렴하도록 수식을 수정하면 된다. 값의 고저차에 따른 수정값은 약 0.01이나 0.1정도로 넣는편.

 

728x90