Gradient Discent
어떤 함수 f(x)가 있을 때, f(x)가 최소가 되는 x 값을 찾는 방법으로, f(x)의 gradient의 반대방향으로 x값을 변화시키는 방법이다. (gradient의 방향이 f(x)를 최대화시키는 방향을 나타내는데, 우리는 f(x)가 최소가 되는 x값을 찾고 싶으므로 반대방향으로 움직여야 한다.)
Linear Regression
Feature ϕ(x)로 부터 y를 예측하는 선형회귀 모델에서 input x로부터의 예측값 fw(x)는 다음과 같이 주어진다.
fw(x)=→w⋅ϕ(x)

출처 : https://blog.paperspace.com/content/images/2018/05/fastlr.png
위의 그림은, z 값이 fw(x)가 되며, x가 2차원으로 (x,y)로 주어지는 경우로, 우리는 점이 찍혀있는 fw(x) 값이 가장 낮은 점의 (x,y)값을 찾기를 원하는 것이다.
Loss
본강의에서는 Loss를 위의 예측값과 실제 값 y의 차의 제곱, 즉 residual의 제곱으로 한다. 즉, 최소제곱법 기반의 최적화를 한다.
Loss(→w)=1|Dtrain|∑(→w⋅ϕ(x)−y)2
따라서 Loss의 gradient는 다음과 같다.
▽→wLoss(→w)=2∑(→w⋅ϕ(x)−y)⋅ϕ(x)
Training
위의 Loss를 최소화하는 방향으로 →w를 최소화 시키기 위해, gradient의 반대 방향으로 →w를 갱신해 주면 된다.
→w=→w−η▽→wLoss(→w)=→w−2η∑(→w⋅ϕ(x)−y)⋅ϕ(x)
여기서 η는 gradient를 따라 얼마나 이동할 것인지를 정하는 값으로, 너무 작으면 학습이 느리고 너무 크면 너무 크게 움직이며 궤도 밖에서 빙빙 돌 수 있으므로 적절한 값을 정해야 한다.
def F(w, data):
return sum(w.dot(x) - y for x,y in data)/len(data)
def dF(w, data):
return sum(2*(w.dot(x) - y) * x for x,y in data)/len(data)
def gradient_discent(true_w,data,w):
eta = 0.01
for i in range(10000):
w -= eta * dF(w,sample)
w = np.random.randn(d)
gradient_discent(true_w,sample,w)
F가 loss값이고, dF가 gradient 값이다. 위의 코드에서 true_w는 정답이 되고, sample은 학습시킬 데이터가 되며, w를 학습시키게 되며, 학습이 진행됨에 따라 w가 true_w값에 가까워진다.
Stochastic Gradient Discent
위의 GD에서의 gradient는 모든 데이터값의 gradient의 평균이었다면, SGD에서는 각각의 데이터(임의의 선택된 데이터)에 대하여 학습을 진행한다. 얼핏 개개의 데이터에 대하여 학습을 진행하면, 결과가 좋지 않을 것 같지만 많은 경우 SGD가 GD보다 더 좋은 결과를 보여준다.
위의 GD의 경우 각 스텝마다 모든 데이터에 대하여 학습하므로 속도가 굉장히 느리다.
SGD에서의 Training
Loss(→w)=1|Dtrain|∑(x,y)∈|D|(→w⋅ϕ(x)−y)2
으로 GD와 같지만,
모든 (x,y)에 대해서 각각 학습을 진행해준다.
→w=→w−η▽→wLoss(→w,y,w)=→w−2η(→w⋅ϕ(x)−y)⋅ϕ(x)
def sF(w,data):
x,y = data
return w.dot(x) - y
def sdF(w,data):
x,y = data
return w*(w.dot(x)-y)*x
def stochastic_gradient_discent(true_w,data,w):
eta = 0.03
for i in range(10000):
for x, y in data:
w -= eta*sdF(w,(x,y))
w2 = np.random.rand(d)
stochastic_gradient_discent(true_w,sample,w2)
* 본 포스트는 Stanford의 CS221 강의를 보고 요약 정리한 것입니다.