화요일!
오늘은 어제 배운 Simple Linear Regression(단순 선형 회귀)을 코드로 구현한다.
< 순서 >
1. Training Data Set 준비 : Data pre-processing(데이터 전처리). 사용할 수 있는 형태로 준비
2. Linear Regression Model을 정의 : y = Wx+b(예측 모델). hypothesis(가설)
3. 최적의 W(weight, 가중치), b(bias, 편차)를 구하려면 loss function(손실함수)/cost function(비용함수) → MSE
4. Gradient Descent Algorithm(경사하강법) : loss function을 편미분(W, b) × learning rate
5. 반복학습 진행
1. Training Data Set의 matrix를 행렬곱 연산으로 한 번에 계산하고 예측치 수식을 2차원으로 바꿔준다. y = XW+b

Python으로 단순 선형 회귀를 구현해보자
import numpy as np
# Training Data Set 준비. x_data -> 독립변수(공부시간)
x_data = np.array([1, 2, 3, 4, 5], dtype=np.float64).reshape(5,1) # (5,-1) 앞의 행이 정해지면 열을 알아서 계산하라 (-1,5)
# t_data -> 정답데이터(시험점수)
t_data = np.array([3, 5, 7, 9, 11], dtype=np.float64).reshape(5,1)
# Weight & Bias 정의
W = np.random.rand(1,1) # 1행 1열짜리(값은 1개) ndarray를 만들고 0과 1 사이의 균등분포에서 실수 난수를 추출
b = np.random.rand(1)
# predict function(예측 함수, 모델, hypothesis)
def predict(x):
y = np.dot(x,W) + b
return y
# loss function
def loss_func(input_data): # loss 함수는 W와 b의 함수
input_W = input_data[0].reshape(1,1) # input_data -> [W b]
input_b = input_data[1]
y = np.dot(x_data, input_W) + input_b # 예측값. dot 메서드는 행렬곱연산. y = XW+b
return np.mean(np.power(t_data - y, 2)) # MSE(평균제곱오차)를 구하자(v). t_data - y -> 오차. power 제곱
# 다변수 함수의 수치미분 코드. input_value = [x y] ndarray로 값이 2개 넘어온다
def numerical_derivative(f,x):
delta_x = 1e-4
derivative_x = np.zeros_like(x) # derivative_x : [0.0 0.0]. x의 shape과 같도록 ndarray 만듦
# iterator를 이용해서 입력변수 x에 대한 편미분을 수행
it = np.nditer(x, flags=['multi_index']) # iterator 객체를 얻어 변수 넣고 flags라는 속성으로 차원 정해주고 반복~
while not it.finished:
idx = it.multi_index
tmp = x[idx]
x[idx] = tmp + delta_x
fx_plus_delta = f(x)
x[idx] = tmp - delta_x
fx_minus_delta = f(x)
derivative_x[idx] = (fx_plus_delta - fx_minus_delta) / (2 * delta_x)
x[idx] = tmp
it.iternext()
return derivative_x
# learning rate의 값을 설정. 초기에는 1e-4 or 1e-3 정도로 설정
learning_rate = 1e-4
# 학습과정을 진행
for step in range(300000):
input_param = np.concatenate((W.ravel(), b.ravel()), axis=0) # [W b] Numpy array. 1차원을 열 방향으로 붙여라
derivative_result = learning_rate * numerical_derivative(loss_func, input_param) # 편미분한 값에 learning_rate를 곱함
W = W - derivative_result[0].reshape(1,1) # 새로운 W'
b = b - derivative_result[1] # 새로운 b'
if step % 30000 == 0: # loss 값이 실제로 줄어드는지 10번만 출력해서 확인하자
input_param = np.concatenate((W.ravel(), b.ravel()), axis=0) # loss 값 구하기 위해
print('W : {}, b:{}, loss:{}'.format(W, b, loss_func(input_param)))
# 6시간 공부하면 몇 점일지를 예측해보자
predict_date = predict(np.array([[6]])) # 인자를 2차원으로 줘야 행렬곱연산이 일어남
print('6시간 공부했을 때 점수 : ', predict_date)
2. 사이킷런(Scikit-Learn) 라이브러리로 단순 선형 회귀를 구현해보자
Anaconda Prompt
conda activate machine
pip install scikit-learn
from sklearn import linear_model
x_data = np.array([1, 2, 3, 4, 5], dtype=np.float64).reshape(5,1) # Training Data Set
t_data = np.array([3, 5, 7, 9, 11], dtype=np.float64).reshape(5,1)
model = linear_model.LinearRegression() # model 생성
model.fit(x_data, t_data) # model 학습
print('W : {}, b:{}'.format(model.coef_, model.intercept_)) # W : [[2.]], b:[1.]. W, b 구해보자
print(model.predict(np.array([[6]]))) # [[13.]]. model을 이용한 예측
3. 만약 독립변수가 많아 loss 함수가 2차원 포물선으로 그려지지 않을 경우, W를 어떻게 구할까?
경사하강법(Gradient Descent Alogrithm)을 이용하면, Global Minima를 구하는 것이 아닌 Local Minima에 갇힐 수 있음 → loss 함수는 특정한 형태(볼록 함수, convex function)를 가져야 함!

4. Ozone량 예측하는 모델
Python으로 단순 선형 회귀를 구현해보자
# Ozone량 예측하는 모델을 만들어 보자
import numpy as np
import pandas as pd
# 다변수 함수의 수치미분 코드
def numerical_derivative(f,x):
delta_x = 1e-4
derivative_x = np.zeros_like(x)
# iterator를 이용해서 입력변수 x에 대한 편미분을 수행
it = np.nditer(x, flags=['multi_index'])
while not it.finished:
idx = it.multi_index
tmp = x[idx]
x[idx] = tmp + delta_x
fx_plus_delta = f(x)
x[idx] = tmp - delta_x
fx_minus_delta = f(x)
derivative_x[idx] = (fx_plus_delta - fx_minus_delta) / (2 * delta_x)
x[idx] = tmp
it.iternext()
return derivative_x
# Raw Data Set Loading
df = pd.read_csv('./data/ozone.csv')
# display(df.head())
# Ozone(오존량) : 종속변수
# Solar.R(태양광세기), Wind, Temp : 독립변수. Linear Regression으로 하나의 독립변수만 사용함
training_data = df[['Ozone', 'Temp']]
# display(training_data)
# print(training_data.shape) # (153, 2)
# training_data.info() # 결치값이 존재함. 데이터가 충분히 많다면 삭제 or 대체
training_data.dropna(how='any', inplace=True) # 결치가 존재하는 행을 삭제
# training_data.info()
x_data = training_data['Temp'].values.reshape(-1,1) # Training Data Set
t_data = training_data['Ozone'].values.reshape(-1,1)
# Weight, bias
W = np.random.rand(1,1)
b = np.random.rand(1)
# loss function
def loss_function(input_data):
W = input_data[0].reshape(1,1)
b = input_data[1]
y = np.dot(x_data, W) + b
return np.mean(np.power(t_data-y,2))
# predict
def predict(x):
y = np.dot(x, W) + b
return y
# learning_rate
learning_rate = 1e-4
# 반복 학습
for step in range(300000):
input_param = np.concatenate((W.ravel(), b.ravel()), axis=0)
derivative_result = learning_rate * numerical_derivative(loss_func, input_param)
W = W - derivative_result[0].reshape(1,1)
b = b - derivative_result[1]
if step % 30000 == 0:
input_param = np.concatenate((W.ravel(), b.ravel()), axis=0)
print('W : {}, b : {}, loss : {}'.format(W, b, loss_func(input_param)))

# 학습종료 후 예측
predict_data = predict(np.array([[62]]))
print('온도가 62일 때 오존량 : {}'.format(predict_data)) # [[16.90439304]]
# 그래프로 표현해보자
import matplotlib.pyplot as plt
plt.scatter(x_data.ravel(), t_data.ravel())
plt.plot(x_data.ravel(), x_data.ravel()*W.ravel() + b, color='r')
plt.show()

5. 사이킷런 라이브러리로 단순 선형 회귀를 구현해보자
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import linear_model
import warnings
warnings.filterwarnings('ignore')
# Raw Data Set Loading
df = pd.read_csv('./data/ozone.csv')
# Linear Regression으로 하나의 독립변수만 사용함
training_data = df[['Ozone', 'Temp']]
training_data.dropna(how='any', inplace=True) # 결치가 존재하는 행을 삭제
x_data = training_data['Temp'].values.reshape(-1,1) # Training Data Set
t_data = training_data['Ozone'].values.reshape(-1,1)
# model 생성
model = linear_model.LinearRegression()
# model 학습
model.fit(x_data, t_data)
# 예측
result = model.predict(np.array([[62]]))
print('sklearn으로 구한 온도가 62도 일 때의 오존량 : {}'.format(result)) # [[3.58411393]]
# 그래프 표현
plt.scatter(x_data.ravel(), t_data.ravel())
plt.plot(x_data.ravel(),
x_data.ravel()*model.coef_.ravel() + model.intercept_, color='g')
plt.show()

6. 왜 Python으로 구현한 것과 사이킷런 라이브러리로 구현한 것의 모양이 다를까? Data 처리가 잘 되지 않았기 때문에!

1. 3/15 화 | 2. 3/16 수 | 3. 3/17 목 | 4. 3/18 금 | 5. 3/21 월 |
ML 환경 설정 (아나콘다, 주피터 노트북), Pandas, Numpy, ndarray |
ML Numpy, 행렬곱연산, 전치행렬, iterator, axis, Pandas, Series, DataFrame |
ML Pandas, DataFrame, 함수들 |
ML Pandas, 데이터 분석, 데이터 전처리 |
ML Pandas, 데이터 전처리, 수행평가 |
6. 3/22 화 | 7. 3/23 수 | 8. 3/24 목 | 9. 3/25 금 | 10. 3/28 월 |
ML 데이터 시각화, Matplotlib, 기술통계 |
ML 기술통계 |
ML 기술통계, 머신러닝 |
ML 미분, Regression |
ML 머신러닝 기법들, Regression |
11. 3/29 화 | 12. 3/30 수 | 13. 3/31 목 | 14. 4/1 금 | 15. 4/4 월 |
ML Regression 구현 (Python, Scikit-Learn) |
ML Outlier, Tensorflow, Zscore |
* Python 코드로 모델을 구현할 줄 알아야, 라이브러리를 개선하고 응용할 수 있다!