ML | DL

2. Loss function, Optimization

빠빠담 2023. 8. 9. 01:09
반응형

https://youtu.be/744NMv4w87M

 

Neural Network의 weight를 찾아가는 방법에 대한 내용

Regression 회귀 분석을 통해 Loss function과 Optimization을 알아보자

 

목적은 아래 그림과 같이 점들의 데이터를 최대한 따라가는 직선을 찾는 것

즉 아래와 같은 수식으로 정의된 직선에서 a값과 b값을 구하는 것

Y = a * X + b

이를 위한 가장 첫 번째 단계로 Loss를 정의해주면 된다

이를 위해 직선에서 점들까지의 거리의 제곱의 합을 Loss로 정의함

직선으로부터 점까지의 거리 [ ( a * X + b - Y ) ** 2 ] 를 모두 더해준 뒤 [ ] 이를 점의 갯수 [ 1/N ] 으로 나누어준 값

1/N * ∑ ( a * X + b - Y ) ** 2

 

이 Loss 함수의 정의는 정해진 것이 아닌 직접 정의해주는 방식이 Loss 함수의 정의가 되는것

예시로 위 방식이 아닌 직선과 점의 직각이 되는 거리를 구해도 되고 X좌표와 평행이 되는 점과 직선의 거리로 정해도 된다

 

중요한 것은 Loss가 최소가 되었을 때 직선은 최대한 주어진 점들을 따라간다는 것

 

 

https://github.com/NoCodeProgram/deepLearning/blob/main/nn/loss_fn.ipynb

아래는 더 단순하게 b값을 제외하고 기울기 a값만 판단하는 예시를 보여준다

1/N * ∑ ( a * X - Y ) ** 2

 

 

a값 기울기가 너무 커지면 갈색 그래프를 그리며 Loss 값이 커지고

a값이 너무 작아도 주황색 그래프를 그리며 Loss 값이 커진다

기울기 a는 적절한 값을 가져야 한다

import pandas as pd
import matplotlib.pyplot as plt

# Load CSV file
data = pd.read_csv('./deepLearning/nn/points7.csv')

x = data['x']
y = data['y']

plt.scatter(x=x,y=y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Scatter plot of data')
plt.show()

기울기를 0에서 3사이로 가정하고 이때 각각 Loss값을 구하면 아래와 같은 그래프가 그려진다 (a값에 따른 Loss값)

미분해서 0이 되는 [ dLoss / da = 0 ] 포인트 구하여 a값을 찾으면 된다

하지만 이는 지금과 같이 매우 간단한 수식에만 적용가능

실제 딥러닝은 주어진 데이터 그리고 Loss까지 가는 공식이 매우 복잡하여 이를 수학적으로 전체 미분을 계산하는건 불가능하다

import numpy as np

# a 값들을 0에서 3사이로 둔다
a_values = np.linspace(0, 3, 100)

# Calculate loss for each a value
loss_values = []
for a in a_values:
    # loss 값은 기울기 a와 x를 곱한뒤 포인트 y를 뺀다 이를 제곱해 총 평균을 구함
    loss = np.mean((a * x - y) ** 2)  # Calculate the mean squared loss
    loss_values.append(loss)

# Plot the loss values
plt.plot(a_values, loss_values)
plt.xlabel('a')
plt.ylabel('Loss')
plt.title('Loss as a function of a')
plt.grid(True)
plt.show()

 

한가지 방법은 Iterative한 방법으로 찾을 수 있다

첫 기준점을 3으로 잡고 Loss값을 계산하고 앞선 기준점보다 조금 더 큰 기준과 더 작은 기준의 Loss값을 계산하여 더 작은 Loss값을 갖는 a값을 새로운 기준점으로 잡고 동일한 작업을 반복한다

이를 통해 Loss가 최소가 되는 a값에 수렴하게 된다

이 방법의 문제점은 효율적이지 못하다

import numpy as np

# Loss 함수 정의
def loss_fn(x: np.ndarray, y: np.ndarray, a: float) -> float:
    loss = np.mean((a * x - y) ** 2)
    return loss

# 최초 a 기준점
a = 3.0
# 변화값
h = 0.001

print(loss_fn(x,y,a))
print(loss_fn(x,y,a+h))
print(loss_fn(x,y,a-h))

7.47173131231991
7.4811641554628405
7.462304524732537

 

위 방법의 문제점을 해소하기 위해

a가 3일때 기울기가 급하기 때문에 다음 기준점은 더 작은 곳에서 시작해도 된다

즉 한 점에서 a에 따른 Loss 변화 값을 계산하면 (미분하면 dLoss/da) 다음 a 값은 더 효율적으로 계산할 수 있다

 

a가 3일때 미분값이 9.42이고

다음 a값의 기준은 아래와 같은 방식으로 구할 수 있다 

이를 통해 Loss에 대한 a의 미분값은 점점 0에 수렴하고 주어진 점의 데이터를 따라가는 즉 Loss를 최소화 시킬 수 있는 값을 구한다

3 - 9.42 * 0.1(학습률: learning rate) = 2.06
import torch

# Convert x and y to PyTorch tensors
x_tensor = torch.tensor(x, dtype=torch.float32)
y_tensor = torch.tensor(y, dtype=torch.float32)

# 기울기 a값에 대한 초기값을 3으로 만들어 준다
# requires_grad: a에 대한 미분값을 계산하라는 의미
a_tensor = torch.tensor(3.0, requires_grad=True)

# 10회 반복하여 a값을 찾아나간다
for idx in range(10):
    loss = torch.mean((a_tensor * x_tensor - y_tensor) ** 2)
    # a에 대한 미분값
    grad = loss.backward()
    print(f"a value: {a_tensor.item()}, dl/da :  {a_tensor.grad}" )
    # a값을 업데이트할 때는 gradient(기울기)를 계산하지 않는다
    with torch.no_grad():
        # 새로운 a텐서는 learning rate(학습률)에 a에서의 gradient(기울기)를 곱해서 빼준다
        a_tensor -= 0.1 * a_tensor.grad

    # Reset gradients
    a_tensor.grad.zero_()

a value: 3.0,                dl/da :  9.429816246032715
a value: 2.057018280029297,  dl/da :  3.7195372581481934
a value: 1.6850645542144775, dl/da :  1.4671509265899658
a value: 1.5383495092391968, dl/da :  0.5787095427513123
a value: 1.4804785251617432, dl/da :  0.22826877236366272
a value: 1.4576516151428223, dl/da :  0.09003896266222
a value: 1.4486477375030518, dl/da :  0.03551575168967247
a value: 1.4450961351394653, dl/da :  0.014008680358529091
a value: 1.443695306777954,  dl/da :  0.005526029039174318
a value: 1.4431426525115967, dl/da :  0.0021789169404655695

 

이때 Hyperparameter값 Learning rate 에 대해 생각해볼 수 있다

지금 학습률을 0.1로 두었지만

그 값이 너무 크다면 Loss를 최소화 시킬 수 있는 a값을 찾지 못하고 값이 널뛴다

다음 a값의 설정 스탭이 너무 커지기 때문

반대로 너무 작다면 다음 a값으로의 스탭이 너무 작기 때문에 a값을 찾기위해 오랜 시간이 걸린다

 

정리

7개의 주어진 데이터에 fitting하는 직선을 찾기위해 Loss를 정의하고

Gradient descent 알고리즘을 통해 최소 Loss를 갖는 a를 구하는 법을 시뮬레이션

실제 a 지점에 대한 미분을 계산하는 방법을 Backpropagation이라 함

 

 

cf) Hyperparameter

Parameter (파라미터, 매개변수)

  • Parameter는 모델 내부에서 결정되는 변수, 데이터를 통해서 산출이 가능한 값
  • 모델 내부에서 데이터를 통해 구해진다.
  • 예측을 수행할 때, 모델에 의해 요구되어지는 값
  • 측정되거나 데이터로부터 학습되어진다.
  • 학습된 모델의 일부로 저장되어진다.
  • ex. 인공신경망에서의 가중치 계수(weight coefficient), SVM(서포트 벡터 머신)에서의 서포트 벡터, 선형회귀나 로지스틱회귀분석에서의 결정계수, 편향(bias)

Hyperparameter (하이퍼파라미터, 초매개변수)

  • Hyperparameter는 주로 알고리즘 사용자가 경험에 의해 직접 세팅하는 값. (여러 번 수행하면서 최적의 값을 찾는다.)
  • 정해진 최적의 값이 없다.
  • Hyperparameter는 모델에서 외적인 요소, 데이터 분석을 통해 얻어지는 값이 아님
  • 모델의 parameter값을 측정하기 위해 알고리즘 구현 과정에서 사용
  • 예측 알고리즘 모델링의 문제점을 위해 조절된다.
  • ex. 신경망 학습에서 learing rate(학습률), SVM에서의 코스트 값, KNN에서의 K의 개수, epoch

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'ML | DL' 카테고리의 다른 글

1. Perceptron  (0) 2023.08.09