1. 경사하강법(Gradient Descent) ?
머신러닝, 딥러닝 알고리즘 학습 시 사용되는 최적화 방법(Optimizer) 중 하나이다.
알고리즘 학습의 목표는 예측값과 실제값간의 차이인 손실함수의 크기를 최소화시키는 파라미터를 찾는것이다.
학습데이터 입력을 변경할 수 없으니까, 손실함수값의 변화에 따라 가중치(weight) 혹은 편향(bias)를 업데이트해야한다.
ex) 가장 간단한 모델인 선형 회귀에서 cost를 최소화하기 위해 아래와 같이 코드를 작성 할 수 있다.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
1-1. 경사하강법 그래프
- step1 : w1,w0를 임의의 값으로 설정하고 첫 비용 함수의 값을 계산
- step2 : w1,w0 각 편미분 결과값을 이전 w에서 마이너스해서 새로운 w값 구한다.
- step3 : 비용함수가 감소하는 방향성으로 주어진 횟수만큼 step2반복하면서 w1,w0업데이트
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 회귀식인 y=4X+6을 근사하기위해 100개의 데이터셋을 만들고, 경사하강법으로 회귀계수 w0(편향),w1(기울기,가중치)을 도출
np.random.seed(0)
# y=4X+6을 근사(w1=4, w0=6). 임의의 값은 노이즈를 위해 만듦.
X = 2*np.random.rand(100,1) # 0~1 사이의 random 소수
y = 6+4 * X+np.random.randn(100,1)
#X,y 데이터 셋 산점도로 시각화
plt.scatter(X,y)
# 비용함수로 정의. 실제값y, 예측값y_pred로 받아서 수식에 넣기
def get_cost(y, y_pred):
N = len(y)
cost = np.sum(np.square(y - y_pred))/N
return cost
# w1, w0을 업데이트할 w1_update, w0_update를 반환
# 입력배열X에 대한 예측배열y_pred는 np.dot(X,w1.T)+w0으로 구한다.
# 100개의 X(1,2,..,100)이 있다면 예측값은 w0+X(1)*w1+X(2)*w1+..+X(100)*w1이며, X와 w1배열의 내적과 동일하다.
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
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
# 경사하강법 함수 생성 : w1,w0모두 0으로 초기화해서 iters 갯수만큼 반복해서 업데이트
# 업데이트는 새로운 w1=이전w1+편미분한 수식을 반복하는것.(w0도 동일)
def gradient_descent_stpes(X, y, iters=10000):
# 초기값 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
# gradient_descent_steps 호출해서 w1,w0구하기
# 최종적으로 예측값과 실제값의 RSS차이구하는 get_cost함수 생성
def get_cost(y, y_pred):
N = len(y)
cost = np.sum(np.square(y - y_pred))/N
return cost
w1, w0 = gradient_descent_stpes(X,y, iters=1000)
print(f"w1 : {w1[0,0]:.3f}, w0 : {w0[0,0]:.3f}")
y_pred = w1[0, 0]*X + w0
print("GD Total Cost", round(get_cost(y, y_pred),4))
=>
w1 : 4.022, w0 : 6.162
GD Total Cost 0.9935
# 시각화
plt.scatter(X,y)
plt.plot(X,y_pred,'r')
2. Stochastic 경사하강법 (SGD)
확률적 경사하강법(SGD;Stochastic Gradient Descent)은 추출된 데이터 한개에 대해서 그래디언트를 계산하고, 경사 하강 알고리즘을 적용하는 방법이다.
- 매 step에서 한개의 샘플을 무작위로 선택하고 그 샘플에 대한 gradient를 계산하기때문에 한 step당 계산하는 속도가 매우 빠르다.
- 반면 확률적으로 샘플링하기때문에, 이 알고리즘은 불안정하다. cost function이 최솟값에 다다를 때까지 smooth하게 감소하지 않고 요동치며 감소한다. 시간이 지나면 최솟값에 매우 근접하겠지만 fluctuation이 지속되면서 minimum에 안착하지 못할 수 있다.
def stochastic_gradient_descent_steps(X,y,batch_size=10, iters=1000):
w0 = np.zeros((1,1))
w1 = np.zeros((1,1))
prev_cost = 100000
iter_index = 0
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
w1,w0 = stochastic_gradient_descent_steps(X,y,iters=1000)
print('w1:', round(w1[0,0],3), 'w0:', round(w0[0,0],3))
y_pred = w1[0,0]*X +w0
print('SGD Total Cost:{0:.4f}'.format(get_cost(y,y_pred)))
=>
w1: 4.028 w0: 6.156
SGD Total Cost:0.9937
💡 확률적 경사하강법을 사용해본 결과
w1,w0은 경사하강법의 결과와 큰 차이가 없으며, 예측오류비용 또한 0.9937로 경사하강법으로 구한 예측오류비용0.9935보다 아주 조금 높을뿐으로 큰 예측성능상의 차이가 없음을 알 수 있다.
따라서 큰 데이터를 처리할 경우에는 경사하강법은 매우 시간이 오래 걸리므로 일반적으로 확률적 경사하강법을 이용한다.
2022.11.07 - [DataAnalytics/MachineLearning] - [ML]LinearRegression을 이용한 보스턴 주택가격 예측 / knn 모델과 비교해보기
[ML]LinearRegression을 이용한 보스턴 주택가격 예측 / knn 모델과 비교해보기
column 설명 더보기 CRIM: 지역별 범죄 발생률 ZN: 25,000평방피트를 초과하는 거주 지역의 비율 NDUS: 비상업 지역 넓이 비율 CHAS: 찰스강에 대한 더미 변수(강의 경계에 위치한 경우는 1, 아니면 0) NOX:
dataanalysisdot.tistory.com
'Data Analytics > MachineLearning' 카테고리의 다른 글
[ML]LinearRegression을 이용해서 보스턴 주택가격 예측해보기 / knn 모델과 비교해보기 (0) | 2022.11.07 |
---|---|
[ML] 머신러닝 모델의 성능을 향상시키는 방법 GridSearchCV (0) | 2022.11.07 |
[ML] 머신러닝 지도학습의 회귀(regression)의 종류와 실습해보기 (0) | 2022.11.07 |
[ML] 추천 시스템 개발을 위한 surprise 라이브러리 - 컨텐츠 기반 필터링 (0) | 2022.10.02 |
[ML] DecisionTree모델 이용해서 붓꽃 품종 예측 / 사용자 행동 인식 Dataset (0) | 2022.10.02 |
댓글