개발하고 싶어요
경사하강법 본문
회귀 소개¶
독립변수는 feature에 해당되며 종속변수는 결정 값이다
회귀 예측의 핵심은 주어진 feature와 결정 값 데이터 기반에서 학습을 통해 최적의 회귀 계수를 찾는 것
- 일반 선형 회귀 : 예측값과 실제 값의 RSS를 최소화할 수 있도록 회귀 계수를 최적화, 규제X
- 릿지 : 선형 회귀에 L2 규제를 추가
- L2 : 상대적으로 큰 회귀 계수 값의 예측 영향도를 감소시키기 위해 회귀 계수값을 더 작게 만드는 것
- 라쏘 : 선형 회귀에 L1 규제를 추가
- L1 : 예측 영향력이 작은 feature의 회귀 계수를 0으로 만들어 회귀 예측 시 feature가 선택되지 않게 하는 것
- 엘라스틱 : L1, L2를 결합
- 로지스틱 회귀
- 회귀 평가 지표
- MAE : mean absolute error
- MSE : mean squared error
- RMSE : root mean squared error
- R**2 : 분산 기반으로 예측 성능 평가
비용 최소화하기 - 경사하강법¶
경사하강법
- 임의의 파라미터 값을 시작점으로 지정
- 해당 점에서의 목적함수 gradient값을 구함
- 파라미터 값을 업데이트 후 목점 함수 값이 특정 값으로 수렴할 때까지 위 과정을 반복
경사 하강법을 파이썬 코드로 구현하기
간단한 회귀식인 y = 4X + 6을 근사하기 위한 100개의 데이터 세트를 만들고, 여기에 경사하강법을 사용해 회귀 계수 w1, w0을 도출
단순 선형 회귀로 예측할 만한 데이터 세트 만들기
In [4]:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
# y = 4X + 6을 근사(w1 = 4, w0 = 6). 임의의 값은 노이즈를 위해 만듦
X = 2 * np.random.rand(100, 1)
y = 6 + 4 * X + np.random.randn(100, 1)
# X, y 데이터 세트 산점도로 시각화
plt.scatter(X, y);
In [10]:
# 바용 함수 정의
def get_cost(y, y_pred): # (실제갑, 예측값)
N = len(y)
cost = np.sum(np.square(y - y_pred)) / N
return cost
경사 하강법 함수 정의
w1, w0을 모두 0으로 초기화한 뒤 iters 개수만큼 반복하면서 w1, w0을 업데이트
w1, w0의 편미분 결괏값을 반복적으로 보정하면서 w1, w0값을 업데이트 하면 비용 함수 RSS가 최소가 되는 w1, w0의 값을 구할 수 있다ㅣㅣ
위 편미분 값이 너무 클 수 있기 때문에 보정 계수(학습률)를 곱한다
<방법>- w1, w0를 임의의 값으로 설정하고 첫 비용 함수의 값을 계산
- w1, w0을 업데이트 후 다시 비용 함수의 값을 계산
- 비용 함수가 감소하는 방향성으로 주어진 횟수만큼 2단계를 반복하면서 w1, w0을 계속 업데이트
In [18]:
# 경사 하강법 함수 정의
# w1, w0을 업데이트할 w1_update, w0_update를 반환
def get_weight_updates(w1, w0, X, y, learning_rate = 0.01):
N = len(y)
# 먼저 w1_update, w0_update를 각각 w1, w0의 shape와 동일한 크기를 가진 0값으로 초기화
w1_update = np.zeros_like(w1)
w0_update = np.zeros_like(w0)
# 예측 배열 계산하고 예측과 실제 값의 차이 계산
y_pred = np.dot(X, w1.T) + w0 # y_pred - w0 + w1X
diff = y - y_pred
# w0_update를 dot 행렬 연산으로 구하기 위해 모두 1값을 가진 행렬 생성
w0_factors = np.ones((N, 1))
# w1, w0을 업데이트할 w1_update, w0_update(편미분에 학습룰을 곱하여 업데이트) 계산
w1_update = -(2 / N) * learning_rate * (np.dot(X.T, diff))
w0_update = -(2 / N) * learning_rate * (np.dot(w0_factors.T, diff))
return w1_update, w0_update
In [8]:
# 경사하강 방식으로 반복적으로 수행
# 입력 인자 iters로 주어진 횟수만큼 반복적으로 w1, w0을 업데이트 적용
def gradient_descent_steps(X, y, iters = 1000):
# w0, w1을 모두 0으로 초기화
w0 = np.zeros((1, 1))
w1 = np.zeros((1, 1))
# 인자로 주어진 iters 만큼 반복적으로 get_weight_updates()를 호출해 w1, w0 업데이트
for ind in range(iters):
w1_update, w0_update = get_weight_updates(w1, w0, X, y, learning_rate = 0.01)
w1 = w1 - w1_update
w0 = w0 - w0_update
return w1, w0
In [11]:
# w1, w0 값을 구하고 최종적으로 예측값과 실제값의 rss 차이 계산 후 경사 하강법의 예측 오류 계산
w1, w0 = gradient_descent_steps(X, y, iters = 1000)
print('w1 : {:.3f} w0 : {:.3f}'.format(w1[0, 0], w0[0, 0]))
y_pred = w1[0, 0] * X + w0
print('Gradient Descent Total Cost : {:.4f}'.format(get_cost(y, y_pred)))
w1 : 4.022 w0 : 6.162
Gradient Descent Total Cost : 0.9935
In [13]:
# 회귀선 그리기
plt.scatter(X, y);
plt.plot(X, y_pred);
확률적 경사 하강법
- 일부 데이터만 이용해 w가 업데이트 되는 값을 계산
In [16]:
def stochastic_gradient_descent_steps(X, y, batch_size = 10, iters = 1000):
w0 = np.zeros((1, 1))
w1 = np.zeros((1, 1))
for ind in range(iters):
np.random.seed(ind)
# 전체 X, y 데이터에서 랜덤하게 batch_size만큼 데이터 추출해 sample_X, sample_y로 저장
stochastic_random_index = np.random.permutation(X.shape[0])
sample_X = X[stochastic_random_index[0:batch_size]]
sample_y = y[stochastic_random_index[0:batch_size]]
# 랜덤하게 batch_size만큼 추출된 데이터 기반으로 w1_update, w0_update 계산 후 업데이트
w1_update, w0_update = get_weight_updates(w1, w0, sample_X, sample_y, learning_rate = 0.01)
w1 = w1 - w1_update
w0 = w0 - w0_update
return w1, w0
In [17]:
w1, w0 = stochastic_gradient_descent_steps(X, y, iters = 1000)
print('w1 : {:.3f} w0 : {:.3f}'.format(w1[0, 0], w0[0, 0]))
y_pred = w1[0, 0] * X + w0
print('stochastic Gradient Descent Total Cost : {:.4f}'.format(get_cost(y, y_pred)))
w1 : 4.028 w0 : 6.156
stochastic Gradient Descent Total Cost : 0.9937
'ML' 카테고리의 다른 글
릿지, 라쏘, 엘라스틱 (0) | 2024.01.29 |
---|---|
다항회귀 (0) | 2024.01.29 |
보스턴 주택 가격 예측 (0) | 2024.01.29 |
베이지안 최적화 기반 (0) | 2024.01.23 |
lightgbm_분류 (0) | 2024.01.23 |