Lab - Gradient descent Copyright 2018 by teamlab.gachon@gmail.com Introduction [PDF 파일다운로드 ]() 이번랩은우리가강의를통해들은 Gradient descent 을활용하여 LinearRegression 모듈을구현하는것을목표로합니다. 앞서 우리가 Normal equation lab 을수행하였듯이, LinearRegression 모듈의구현을위해서는 numpy 와 Python OOP 의기본적인개념이 해가필요합니다. 실제 Tensorflow 의 optimizer 나 scikit-learn SGDRegressor 의가장기본적인형태로이해하면좋겠습니다. backend.ai 설치 숙제를제출하기앞서, 레블업의 backend.ai 를여러분의파이썬에설치하셔야합니다. 설치하는과정은매우쉽습니다. 아래처럼 터미널또는 cmd 창에서입력을하시면됩니다. pip install backend.ai-client 숙제파일 (lab_normal_equation.zip) 다운로드 먼저해야할일은숙제파일을다운로드받는것입니다. 아래링크를다운로드하거나 Chrome 또는익스플로러와같은웹브라우 저주소창에아래주소를입력합니다. 링크 lab_gradient_descent.zip https://s3.ap-northeast-2.amazonaw s.com/teamlab-gachon/mooc_pic/lab_gradient_descent.zip 또는 Mac OS 에서는아래명령을쓰셔도됩니다. wget https://s3.ap-northeast-2.amazonaws.com/teamlab-gachon/mooc_pic/lab_gradient_descent.zip 다운로드된 lab_gradient_descent.zip 파일을작업폴더로이동한후압축해제후작업하시길바랍니다. 압축해제하면폴더가 linux_mac 과 windows 로나눠져있습니다. 자신의 OS 에맞는폴더로이동해서코드를수정해주시기바랍니다. linear_model.py 코드구조 본 Lab 은 LinearRegressionGD class 를만들기위해 linear_model.py 라는 template 파일을제공합니다. 앞서 normal equation lab 가모듈명은동일하나생성하는클래스명이 LinearRegressionGD 으로차이가납니다. 제공하는 template 파일은아래와같은구조 를가지며각변수와함수의역할은아래테이블과같습니다. 이름 종류 개요 fit predict function function Linear regression 모델을적합한다. Matrix X와 Vector Y가입력값으로들어오면 Grdient descent를활용하여, w eight값을찾는다. 적합된 Linear regression 모델을사용하여입력된 Matrix X의예측값을반환한다. 이때, 입력된 Matrix X는별도의전처리가없는상태로입력되는걸로가정한다. cost function Matrix X 와 Hypothesis function 을활용해 Vector Y 와차이를구한다.
hypothesis_function function Matrix X 와 Weight vector 를활용하여 Y 의예측치를구한다. gradient function Matrix X 와 Error(Y^hat - Y), 그리고 theta 값을활용하여 gradient 를구한다. coef property normal equation 의결과생성된계수 (theta, w eight) 값들을 numpy array 로저장한 다. intercept property normal equation 의결과생성된절편 (theta_0, w eight_0) 값을 scalar 로저장한다. w eights_history property 100 번씩 Gradient update 가될때마다 w eight 값을 list 로저장한다. cost_history property 100 번씩 Gradient update 가될때마다 cost 값을 list 로저장한다. import numpy as np class LinearRegressionGD(object): def init (self, fit_intercept=true, copy_x=true, eta0=0.001, epochs=1000, weight_decay=0.9): self.fit_intercept = fit_intercept self.copy_x = copy_x self._eta0 = eta0 self._epochs = epochs self._cost_history = [] self._coef = None self._intercept = None self._new_x = None self._w_history = None self._weight_decay = weight_decay def cost(self, h, y): pass def hypothesis_function(self, X, theta): pass def gradient(self, X, y, theta): pass def fit(self, X, y): # Write your code for epoch in range(self._epochs): # 아래코드를반드시활용할것 gradient = self.gradient(self._new_x, y, theta).flatten() # Write your code if epoch % 100 == 0: self._w_history.append(theta) cost = self.cost( self.hypothesis_function(self._new_x, theta), y) self._cost_history.append(cost) self._eta0 = self._eta0 * self._weight_decay # Write your code def predict(self, X): pass @property def coef(self): return self._coef @property def intercept(self): return self._intercept
@property def weights_history(self): return np.array(self._w_history) @property def cost_history(self): return self._cost_history Mission 이번랩의목적은 Gradient descent 를직접구현해보는것이다. 물론우리가수업을통해 Gradient descent 를어떻게구현하는지 설명하였기때문에쉽게느낄수도있으나, 이번랩은한번에여러개의 변수가있을때손쉽게 graident 를구하는문제를풀것이다. fit 함수만들기 fit 함수는 Linear regression 모델을적합하는함수이다. 본함수는 Matrix X 와 Vector Y 가입력값으로들어오면 Gradient descent 을활용하여, w eight 값을찾는다. 이때, fit_intercept 설정에따라다른방식으로적합이실행이달라진다. 또한 fit 을할때는입력 되는 X 의값은반드시새로운변수 (self._new _X) 에저장한후실행되어야한다. fit_intercept 가 True 일경우 : Matrix X 의 0 번째 Column 에값이 1 인 column vector 를추가한다. 단 fit_intercept 가 False 일경우 의 Matrix X 의변수는 2 개이상일것이라고가정한다. Gradient descent 를할때몇가지고려해야하는변수가있다. self._eta0 : Learning rate를의미한다. 초기값은 0.001으로설정한다. self._epochs : 전체 Training data를몇번학습할것인지를결정한다. 초기값은 1000이다. self._w eight_decay : 1번 Training data를학습할때마다, Learning rate인 self._eta0을 w eight_decay 비율로줄인다. 초기값은 0.9이다. self._w _history : 전체데이터를 100번학습할때마다현재의 w eight 값을저장한다. self._cost_history : 전체데이터를 100번학습할때마다현재의 cost 값을저장한다. fit 을할때는아래의 Gradient descent 의공식을활용한다. Gradient descent 할때반드시아래코드를사용해야한다. 아래코드에서 self.gradient 함수가 gradient 를구하는함수이다. Gradient 를구하는공식은아래와같다. gradient = self.gradient(self._new_x, y, theta).flatten() 학습을할때매 100 번마다 w eight 값과 cost 값을 self._w_history, self._cost_history 에저장한다. 적합이종료된후각변수의계수 (coefficient 또는 w eight 값을의미 ) 는 self._coef 와 self._intercept_coef 에저장된다. 이때 self._coef 는 numpy array 을각변수항의 w eight 값을저장한 1 차원 vector 이며, self._intercept_coef 는상수항의 w eight 를저장한 scalar(float) 이다. 입력되는 parameter 와리턴은아래정보를참고한다.
X : numpy array, 2 차원 matrix 형태로 [n_samples,n_features] 구조를가진다 y : numpy array, 1 차원 vector 형태로 [n_targets] 의구조를가진다. self : 현재의인스턴스가리턴된다 predict 함수만들기 적합된 Linear regression 모델을사용하여입력된 Matrix X 의예측값을반환한다. 이때, 입력된 Matrix X 는별도의전처리가없는 상태로입력되는걸로가정한다. fit_intercept 가 True 일경우 : Matrix X 의 0 번째 Column 에값이 1 인 column vector 를추가한다. predict 함수는다음수식을사용한다. 입력되는 parameter 와리턴은아래정보를참고한다. X : numpy array, 2 차원 matrix 형태로 [n_samples,n_features] 구조를가진다 y : numpy array, 예측된값을 1 차원 vector 형태로 [n_predicted_targets] 의구조를가진다. cost 함수만들기 본함수는예측치 y_hat 과실제값 y 값간의차이를 cost 함수를구하는공식으로산출한다. 산출하는공식은아래와같다. 본함수는반드시 return 을포함하여한줄로함수를만들어야합니다. 함줄코딩의예시는다음과같다. 주석등도줄로치니중의 바랍니다. def cost(self, h, y): return np.sum((h-y).flatten()) h : numpy array, 2 차원 matrix 형태로 [-1, n_predicted_targets] 의구조를가진다. y : numpy array, 실제 y 값을 1 차원 vector 형태로 [n_real_values] 의구조를가진다. cost_value : float 형태의 scalar 값을반환함
hypothesis_function 함수만들기 본함수는 theta 값과 X 의값이주어지면예측치인 Y_hat 을반환하는함수이다. 함수에서사용되는공식은아래와같으며, 리턴되 는값의형태는 2 차원 matrix 형태이다. 본함수는반드시 return 을포함하여한줄로함수를만들어야합니다. 함줄코딩의예시는다음과같다. 주석등도줄로치니중의 바랍니다. def hypothesis_function(self, h, y): return np.sum((h-y).flatten()) X : numpy array, 2 차원 matrix 형태로 [n_samples,n_features] 구조를가진다 theta : numpy array, 가중치 weight 값을 1 차원 vector 로입력한다. y_hat : numpy array, 예측된값을 2 차원 matrix 형태로 [-1, n_predicted_targets] 의구조를가진다. gradient 함수만들기 w eight 값을업데이트하기위한 Gradient 를생성하는함수이다. 함수의반환값은 Vector 형태로반환한다. 본함수는반드시 return 을포함하여한줄로함수를만들어야합니다. 함줄코딩의예시는다음과같다. 주석등도줄로치니중의 바랍니다. def gradient(self, h, y): return np.sum((h-y).flatten()) X : numpy array, 2 차원 matrix 형태로 [n_samples,n_features] 구조를가진다 y : numpy array, 실제 y 값을 1 차원 vector 형태로 [n_real_values] 의구조를가진다. theta : numpy array, 가중치 weight 값을 1 차원 vector 로입력한다. gradient : numpy array, 공식에의해산출된 gradient vector 를반환함. 이때 gradient vector 는 weight 의갯수만큼 element 를가진다. 반환되는형태는 [weight_gradient] 로반환하므로반드시 flatten 함수를사용한다. 구현모듈테스트하기 여러분이만들모듈이잘작동하는지테스트하기위해서이제 ipynb 파일을만들어쥬피터노트북에서실행해보겠습니다.
모듈호출하기 먼저우리가사용할모듈을호출한다. 기본적으로 pandas 와 numpy 를호출한다. linear_model 모듈을호출하기위해서는 import linear_model 명령을사용한다. 단여기서 linear_model.py 파일이자주바꾸니 imp 모듈을활용하여, 파일이바뀌고다시저장될 때 reload 할수있도록하여야한다. import pandas as pd import numpy as np import linear_model import imp imp.reload(linear_model) 데이터불러하기 첫번째데이터는 one variable 의형태를 test.py 파일이다. 파일을 pandas 로호출하면아래와같은구조를확인할수있다. df = pd.read_csv("./train.csv") df.head() x y 0 24 21.549452 1 50 47.464463 2 15 17.218656 3 38 36.586398 4 87 87.288984 numpy data 구성하기 pandas 로부터필요한데이터를구성한다. X = df["x"].values.reshape(-1,1) y = df["y"].values Model 생성하기 LinearRegression 클래스를사용해서모델을생성한다. lr = linear_model.linearregressiongd(eta0=0.0001, epochs=500000, weight_decay=1) lr.fit(x, y) lr.intercept # -0.12015404827836433 lr.coef # array([ 1.00077823]) lr.predict(x)[:10] array([ 23.89852337, 49.91875724, 14.89151934, 37.90941853, 86.9475516, 35.90786208, 11.88918466, 80.94288225, 24.8993016, 4.88373708]) import matplotlib.pyplot as plt plt.plot(lr.cost_history[1000:2000]) plt.show()
M odel Validation 구현한 LinearRegression 클래스와 scikit-learn 의 linear regression 클래스로만든결과물을비교한다. from sklearn import linear_model sk_lr = linear_model.linearregression(normalize=false) sk_lr.fit(x, y) sk_lr.intercept_ # -0.1201555318131966 sk_lr.coef_ # array([ 1.00077825]) np.isclose(lr.coef, sk_lr.coef_) #True lr.predict(x_test)[:5] # array([ 23.88223775, 50.25495698, 14.75321955, 38.08293272, 87.78536512]) M ultiple variable 동일한과정으로다변수일경우에도작동할수있는지확인한다. df = pd.read_csv("./mlr09.csv") df.head() height_in_feet w eight_in_pounds successful_field_goals percent_of_successful_free_throw 0 6.8 225 0.442 0.672 1 6.3 180 0.435 0.797 2 6.4 190 0.456 0.761 3 6.2 180 0.416 0.651 4 6.9 205 0.449 0.900 y = df["average_points_scored"].values X = df.iloc[:,:-1].values mu_x = np.mean(x, axis=0) std_x = np.std(x, axis=0) rescaled_x = (X - mu_x) / std_x # RESCALED
Fitting 실행하기 lr.fit(rescaled_x, y) lr.coef # array([-1.67758077, 0.28337482, 2.68587788, 1.12815751]) lr.intercept # 11.790740740731859 sk_lr.fit(rescaled_x, y) sk_lr.coef_ # array([-1.67779283, 0.28359762, 2.68586629, 1.12816882]) sk_lr.intercept_ # 11.790740740740736 숙제 template 파일제출하기 ( 윈도우의경우 ) 1. windows + r 를누르고 cmd 입력후확인을클릭합니다. 2. 작업을수행한폴더로이동합니다. 3. 밑에명령어를 cmd 창에입력합니다. install.bat submit.bat [YOUR_HASH_KEY] 숙제 template 파일제출하기 (Mac or Linux) 1. 터미널을구동합니다. 2. 작업을수행한디렉토리로로이동합니다. 3. 밑에 bash 창을입력합니다. bash install.sh bash submit.sh [YOUR_HASH_KEY] backend.ai 서비스의업데이트에의해실행전반드시 bash install.sh 또는 install.bat 수행을바랍니다. Next Work 고생했습니다. 현대머신러닝에있어가장핵심이되는알고리즘중하나인 Gradient descent 를구현해보았습니다. Noraml equation 과달리진짜프로그래밍을하는기분도많이들고 Handling 하기상당히어려우셨을거같습니다. 하지만이제시작입니다. 다음시간에는좀더복잡한 Linear regression 구현코드를작성해보겠습니다!! Human know ledge belongs to the w orld - from movie 'Passw ord' -