2022.07.05 - [Studying/Machine Learning] - [머신러닝] python 지구 온도 변화 분석
[머신러닝] Linear Regression - 지구 온도 변화 분석
2022.07.05 - [Studying/Machine Learning] - [머신러닝] Linear regression(선형 회귀) 구현 [머신러닝] Linear regression(선형 회귀) 구현 저번 포스트까지 Numpy 모듈에 대해 정리를 마쳤다. 이번 포스트에서..
gm-note.tistory.com
저번 포스트가 feature가 하나인 single linear regression 이였으니
이번에는 multiple linear regression을 해보겠다.
여러 feature가 나와서 처리하게 되는 프로세스들이 추가된다.
이번에도 데이터를 먼저 다운로드해보겠다.
import pandas
import seaborn #시각화를 위해 사용
seaborn.set()
from urllib.request import urlretrieve
URL = 'https://go.gwu.edu/engcomp6data3'
urlretrieve(URL, 'auto_mpg.csv')
받은 파일을 열어서 데이터를 확인해보겠다.
mpg_data = pandas.read_csv('/content/auto_mpg.csv')
mpg_data.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 392 entries, 0 to 391
# Data columns (total 9 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 mpg 392 non-null float64
# 1 cylinders 392 non-null int64
# 2 displacement 392 non-null float64
# 3 horsepower 392 non-null float64
# 4 weight 392 non-null float64
# 5 acceleration 392 non-null float64
# 6 model year 392 non-null int64
# 7 origin 392 non-null int64
# 8 car name 392 non-null object
# dtypes: float64(5), int64(3), object(1)
# memory usage: 27.7+ KB
총 392개의 데이터가 있고 9개의 정보들이 있다.
이 데이터 중에 연비에 영향이 가지 않는 origin, car_name은 제외하고 linear regression을 해보려고 한다.
y_col = 'mpg'
x_cols = mpg_data.columns.drop(['car name', 'origin', 'mpg'])
print(x_cols)
# Index(['cylinders', 'displacement', 'horsepower', 'weight', 'acceleration', 'model year'],
# dtype='object')
car_name과 origin과 예측할 mpg 컬럼을 drop 시킨 결과이다.
linear regression을 하기 전에 자동차의 스펙들과 연비의 상관관계를 시각화해서 알아보자
seaborn.pairplot(data=mpg_data, height=5, aspect=1,
x_vars=x_cols,
y_vars=y_col);
데이터는 이렇게 보인다.
acceleration과 model year과 양의 상관관계, 나머지는 음의 상관관계에 있는 것을 볼 수 있다.
이러한 상관관계이기 때문에 연비를 예측하는데 linear regression이 충분하다는 것을 알 수 있다.
입력변수가 d개일 때 우리가 찾아야 하는 모델은 다음과 같다.
$$\hat{y} = w_0 + w_1x_1 + w_2x_2 + ... + w_dx_d$$
여기서 y hat은 우리가 예측한 값이다.
여기서 연산의 편의 상 x_0=1을 추가해서 위의 식을 정리하면 다음과 같다.
$$\hat{y} = \sum_{i=0}^d w_ix_i = \mathbf{x}^\top \mathbf{w}$$
위에서 392개의 데이터를 받았는데 이를 N개라 하고 식을 나열해보면 다음과 같다.
$$\hat{y}^{(1)} = w_0x_0^{(1)} + w_1x_1^{(1)} + w_2x_2^{(1)} + ... + w_dx_d^{(1)}$$ $$\hat{y}^{(2)} = w_0x_0^{(2)} + w_1x_1^{(2)} + w_2x_2^{(2)} + ... + w_dx_d^{(2)}$$ $$\vdots$$ $$\hat{y}^{(N)} = w_0x_0^{(N)} + w_1x_1^{(N)} + w_2x_2^{(N)} + ... + w_dx_d^{(N)}$$
위의 식을 한 번에 행렬로 표현하면 다음과 같다.
$$\hat{\mathbf{y}} = \begin{bmatrix} \hat{y}^{(1)} \\ \hat{y}^{(2)}\\ \vdots \\ \hat{y}^{(N)} \end{bmatrix} = \begin{bmatrix} x_0^{(1)} & x_1^{(1)} & \cdots & x_d^{(1)} \\ x_0^{(2)} & x_1^{(2)} & \cdots & x_d^{(2)} \\ \vdots & \vdots & \ddots & \vdots \\ x_0^{(N)} & x_1^{(N)} & \cdots & x_d^{(N)} \end{bmatrix} \begin{bmatrix} w_0 \\ w_1\\ \vdots \\ w_d \end{bmatrix} = \mathbf{X}\mathbf{w}$$
이제 이것들을 코드로 표현해보자
from autograd import numpy
from autograd import grad
X = mpg_data[x_cols].values
X = numpy.hstack((numpy.ones((X.shape[0], 1)), X)) #연산의 편의를 위해 x_0=1
y = mpg_data[y_col].values
print("X.shape = {}, y.shape = {}".format(X.shape, y.shape))
# X.shape = (392, 7), y.shape = (392,)
이제 cost function을 정의해 보자
mean squared error(MSE)를 사용해보겠다.
$$L(\mathbf{y}, \hat{\mathbf{y}}) = \frac{1}{N} \sum_{i=1}^N (y^{(i)} - \hat{y}^{(i)})^2$$
위의 식을 코드로 나타내면 다음과 같다.
numpy.mean( numpy.sum((y-y_pred)**2) )
그러면 linear regression과 cost function을 코드로 나타내 보겟다.
def linear_regression(params, X):
return numpy.dot(X, params)
def cost_function(params, model, X, y):
y_pred = model(params, X)
return numpy.mean( numpy.sum((y-y_pred)**2) )
이제 gradient descent로 cost function을 최소로 하는 계수를 찾아보겠다.
autograd.grad함수를 사용해서 기울기를 구하고 랜덤한 값을 넣어서 기울기 값이 잘 구해지는지 알아보자
gradient = grad(cost_function)
gradient(numpy.random.rand(X.shape[1]), linear_regression, X, y)
# array([1.89156671e+06, 1.12205854e+07, 4.23341815e+08, 2.16679469e+08,
# 6.10689089e+09, 2.87049061e+07, 1.43051715e+08])
기울기 값이 너무 크게 나오는 걸 볼 수 있다.
이것은 입력변수들 중에 특정 값들이 너무 커서 발생한 것이다.
이를 보정하기 위해 모든 값들을 0~1사이로 scaling해주겠다.
사용할 방법은 min-max scaling으로 scikit-learn패키지에서 가져오겠다.
이 normalization의 변환식은 다음과 같다.
$$x' = \frac{x - \min(x)}{\max(x)-\min(x)}$$
이제 앞의 포스트와 같이 gradient descent를 진행해보겠다.
max_iter = 1000
alpha = 0.001
params = numpy.zeros(X.shape[1])
for i in range(max_iter):
descent = gradient(params, linear_regression, X_scaled, y)
params = params - descent * alpha
loss = cost_function(params, linear_regression, X_scaled, y)
if i%100 == 0:
print("iteration {}, loss = {}".format(i, loss))
학습이 완료된 후의 param은 다음과 같다.
params
# array([ 27.56342896, -1.24000064, 1.70706502, -0.2853682 ,
# -23.08358717, 1.06664226, 8.99271696])
아까 위의 식 처럼 우리는 예측 값을 params와 X의 곱으로 나타낼 수 있다.
y_pred_gd = X_scaled @ params
이제 이 모델이 얼마나 정확한지 알아보겠다.
regression 문제에서는 주로 두 개의 지표가 있다.
MAE(mean absolute error), RMSE(root mean squared error)
두 지표의 식은 다음과 같다.
$$\text{MAE}(\mathbf{y}, \hat{\mathbf{y}}) = \frac{1}{N} \sum_{i=1}^N \left\vert y^{(i)} - \hat{y}^{(i)}\right\vert$$ $$\text{RMSE}(\mathbf{y}, \hat{\mathbf{y}}) =\sqrt{ \frac{1}{N} \sum_{i=1}^N (y^{(i)} - \hat{y}^{(i)})^2}$$
이 지표들도 scikit-learn 패키지를 통해 사용해보겠다.
from sklearn.metrics import mean_absolute_error, mean_squared_error
mae = mean_absolute_error(y, y_pred_gd)
rmse = mean_squared_error(y, y_pred_gd, squared=False)
print("mae = {}".format(mae))
print("rmse = {}".format(rmse))
# mae = 2.613991601156043
# rmse = 3.40552056741184
예측이 어느 정도 잘 된 것을 확인할 수 있다.
지금 하는 것은 이해를 위해 기능들을 하나하나 직접 구현하는 것인데
이 부분을 이해한 후에 나중에는 코드 3줄 이하로 이 모든 것을 할 수 있게 된다.
'Studying > Machine Learning' 카테고리의 다른 글
[머신러닝] Logistic Regression - 타이타닉 탑승자 사망여부 예측 (0) | 2022.07.11 |
---|---|
[머신러닝] Logistic Regression (0) | 2022.07.07 |
[머신러닝] Linear Regression - 지구 온도 변화 분석 (0) | 2022.07.05 |
[머신러닝] Linear regression(선형 회귀) 구현 (0) | 2022.07.05 |
[머신러닝] 파이썬 Numpy 연산 - Numpy dot, matmul, transpose (1) | 2022.06.25 |
댓글