머신러닝 #1 - 모델링 개요 & Linear Regression 2022/08/22~2022/08/29
지난 1주일동안 미니 프로젝트 2개를 진행하고 머신러닝을 배우게 되었다. 나는 학교에서 배운 머신러닝 이론을 실무에서 어떻게 적용하는지 에이블스쿨을 수강하기 이전부터 궁금했다. 드디어 실무의 머신러닝을 배우게 된다고 생각하니 너무 기대가 되었다. 역시나 강의는 훌륭했으며 잊어버리기 전에 정리를 통해 배운 지식을 내 것으로 만들고자 한다.
1. 모델링
모델이란 데이터로부터 패턴을 찾아 정리한 수학식이다. 모델링은 오차를 줄이는 방향으로 모델을 만드는 과정을 의미한다. 여기서 패턴이란 feature X와 target y의 관계를 의미한다. 따라서 패턴을 찾아 정리한 수학식인 모델은 y = a * X + b와 같은 수식이 될 수 있다. (이것은 간단한 예시이고 실제로는 모델을 이렇게 간단한 수학식으로 적어내기 힘들 수도 있음에 유의하자.)
이때 target y의 값의 존재 여부에 따라 모델링의 학습 방법이 달라진다. y의 값이 존재하는 경우 답을 알려주면서 패턴을 찾도록 하는 Supervised Learnig(지도학습)을 사용하고, y의 값이 존재하지 않는 경우 데이터 안에서 알아서 패턴을 찾도록하는 Unsupervised Learnig(비지도학습)을 사용한다. 또한 Supervised Learnig의 y의 데이터 형식에 따라 머신러닝 알고리즘이 달라진다. y가 수치형 데이터라면 Regression(회귀) 알고리즘을 범주형 데이터(클래스)라면 Classification(분류) 알고리즘을 사용한다.
2. 모델링 코드 익히기
기본적인 모델링 코드를 사용하는 방법은 정형화 되어 있기 때문에 먼저 코드 작성법을 익히는 것이 중요하다. 어떤 모델을 쓸지 hyper parameter는 어떤 값을 지정할지와 같은 선택은 비즈니스와 데이터에 따라 또 모델링 과정에 따라 수정하도록 하자. 과정은 다음과 같다.
- 모델 클래스 불러오기
- 클래스 선언을 통해 모델 객체 생성
- 모델 학습
- 예측과 평가를 통해 모델 검증
간단하게 코드로 구현하자면 다음과 같다.
from sklearn.metrics import mean_absolute_error # MAE 모델 평가 함수 import
from sklearn.model_selection import train_test_split # 데이터 분할 함수
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) # 데이터 준비 (feature: X, target: y)
"1. 모델 클래스 불러오기"
from sklearn.linear_model import LinearRegression # LinearRegression 모델 클래스 import
"2. 클래스 선언을 통해 모델 객체 생성"
model = LinearRegression()
"3. 모델 학습"
model.fit(X_train, y_train)
"4. 예측과 평가를 통해 모델 검증"
pred = model.predict(X_test) # x_test에 대해 예측
mean_absolute_error(pred, y_test) # 예측값과 실제값에 대해 MAE를 통해 모델 평가
3. Linear Regression (선형 회귀)
모델은 실제값 = 모델값 + 오차의 식으로 정리된다. 따라서 우리는 오차를 최소화하는 방향으로 모델링을 진행한다. Linear Regression(선형 회귀)도 마찬가지인데 Linear Regression은 오차를 조금씩 줄여가며 반복적으로 직선 혹은 평면을 찾아가는 알고리즘 모델이다. Linear Regression은 Feature 개수에 따라 Simple Linear Regression(단순 회귀)과 Multiple Linear Regression(다중 회귀)으로 나눌 수 있다.
4. Simple Linear Regression (단순 회귀)
Simple Linear Regression(단순 회귀) 알고리즘 모델은 하나의 feature로 하나의 target을 예측하는 알고리즘 모델이다. 수학식으로 y = ax + b의 형태를 지니고 오차를 조금씩 줄여가며 전체 오차가 가장 적은 직선 한 개를 선정하는 알고리즘이다. 앞선 모델링 코드 익히기의 절차를 통해 예시를 들도록 하겠다.
print(data.head()) # 보스턴 집값 데이터
# crim indus nox rm dis rad tax ptratio lstat medv
# 0 0.00632 2.31 0.538 6.575 4.0900 1 296 15.3 4.98 24.0
# 1 0.02731 7.07 0.469 6.421 4.9671 2 242 17.8 9.14 21.6
# 2 0.02729 7.07 0.469 7.185 4.9671 2 242 17.8 4.03 34.7
# 3 0.03237 2.18 0.458 6.998 6.0622 3 222 18.7 2.94 33.4
# 4 0.06905 2.18 0.458 7.147 6.0622 3 222 18.7 5.33 36.2
target = 'medv'
X = data.drop(target, axis=1) # feature
y = data.loc[:, target] # target
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size = .3, random_state = 2022) # 데이터 분할
# 학습에 사용할 변수를 지정
features = ['lstat']
# 지정된 변수로 데이터셋을 만들기. (x는 2차원이상이어야 함)
X_train_1 = X_train[features]
X_val_1 = X_val[features]
"1. 모델 클래스 불러오기"
# 모델링용
from sklearn.linear_model import LinearRegression
# 회귀모델 평가용
from sklearn.metrics import mean_absolute_error
"2. 클래스 선언을 통해 모델 객체 생성"
model_1 = LinearRegression()
"3. 모델 학습"
model_1.fit(X_train_1, y_train)
"4. 예측과 평가를 통해 모델 검증"
pred_1 = model_1.predict(X_val_1) # x_test에 대해 예측
print(mean_absolute_error(pred_1, y_val)) # 예측값과 실제값에 대해 MAE를 통해 모델 평가
# 4.138380487348265
위 예제는 보스턴 집값 데이터로부터 lstat(인구 중 하위 계층 비율) feature로 medv(타운별 집값(중위수))를 예측하는 과정이다. 이때 모델의 .coef_ 속성을 통해 회귀계수를 .intercept_ 속성을 통해 Y 절편을 알 수 있다. 그러므로 모델의 수학식을 알 수 있다. 과정은 다음과 같다.
print('회귀계수 : ', model_1.coef_)
# 회귀계수 : [-0.9568563]
print('절편 : ', model_1.intercept_)
# 절편 : 34.676249051494665
따라서 보스턴 집값 데이터로부터 lstat(인구 중 하위 계층 비율) feature로 medv(타운별 집값(중위수))를 예측하는 Simple Linear Regression 모델의 수식은 medv = -0.9568563 * lstat + 34.676249051494665이다. lstat은 백분율 단위이고 medv는 1,000 달러 단위이므로 lstat이 1%가 늘어난다면 medv는 약 960 달러가 줄어든다는 것을 의미한다. 이처럼 Simple Linear Regression 모델을 통해 단순히 두 변수를 통한 예측뿐 아니라 두 변수간의 관계 또한 알 수 있다.
5. Multiple Linear Regression (다중 회귀)
Multiple Linear Regression(다중 회귀) 알고리즘 모델은 feature가 2개 이상인 Linear Regression 알고리즘 모델이다. Linear Regression 알고리즘의 수학식은 직선식이었던것에 비해 Multiple Linear Regression 알고리즘의 수학식은 다차원식이라는 것을 제외하고 두 모델의 구현과정은 때문에 구현은 넘어가도록 하겠다.
중요한 것은 Multiple Linear Regression 모델은 feature가 2개 이상이기 때문에 feature들 간에 독립성을 가정하고 모델을 생성해야 한다는 것이다. 이것은 다중 공선성(Multi-Collineartiy)과 관련이 있다. 다중 공선성이란 하나의 독립변수가 다른 여러 개의 독립변수들로 잘 예측되는 경우를 의미한다. 다중 공선성이 있다면 계수 추정이 잘 되지 않거나 불안정해져서 데이터가 약간만 바뀌어도 추정치가 크게 달라질 수 있고 따라서 계수가 통계적으로 유의미하지 않은 것처럼 나올 수 있다. 예를 들어, y = 3 * x1 - 2 * x2 + 5일 때, x1과 x2간에 x2 = 2 * x1 - 1이라는 공선성이 있다면 y = 3 * x1 - 2 * (2 * x1 - 1) + 5 = -1 * x1 + 7이 되어 초기 x1과 y는 3이라는 관계를 가졌지만 공선성으로 인해 -1이라는 관계를 가지게 될 수 있다.
다중 공선성을 확인하기 위해 분산 팽창 지수 (VIF, Variance Inflation Factor) 를 사용한다. VIF 값이 5 이상이면 다중 공선성이 존재한다고 보고 10 이상이면 강하다고 보고 주의해야한다. 그러나 다중 공선성이 성능에 항상 문제가 되는 것은 아닐 수 있으므로 실험을 통해 확인을 해보는 과정이 필요하다.
6. 회귀 모델 평가
회귀 모델은 오차 비, 오차의 양, 오차율을 통해 평가할 수 있다. 구분은 다음과 같다.
[y의 평균] 모델의 오차 vs [regression] 모델의 오차 | R2 score | 오차의 비 |
[실제값] vs [regression 모델의 예측 값] | MSE, RMSE, MAE | 오차의 크기 |
MAPE | 오차율 |
R2 score (R2-squared)는 평균 모델의 오차 대비 회귀모델이 해결한 오차의 비율이다. regression이 얼마나 오차를 해결했는지를 나타내는 지표로 결정계수, 설명력이라 부르기도 한다. R2 score가 1에 가까울수록 오차가 적음을 의미한다.
그러나 실전에서 많이 쓰이는 오차는 오차의 양과 율로 평가하는 MSE, RMSE, MAE, MAPE이다. 4가지 오차를 설명하기 위해 간단한 예를 들도록 하겠다.
실제값 | 예측값 |
6 | 4 |
5 | 6 |
12 | 9 |
2 | 2 |
위 예시에서 SSE (Sum Squared Error)는 오차제곱합으로 (6 - 2)^2 + (5 - 6)^2 + (12 - 9)^2 + (2 - 2)^2 = 14이다. MSE는 Mean SSE로 오차제곱합의 평균을 의미한다. 따라서 위 예시에서 MSE는 14 / 4 = 3.5이다. RMSE는 Root MSE를 의미하므로 MSE를 root한 값을 의미한다. 즉 위 예시에서 RMSE는 sqrt(3.5)를 의미한다. MAE는 Mean Absolute Error를 의미한다. 절대치 오차의 평균을 의미하는데 따라서 위 예시에서 MAE는 |6 - 4| + |5 - 6| + |12 - 9| + |2 - 2| / 4= 6 / 4 = 1.5이다. MAPE는 Mean Absolute Percentage Error의 약어로 절대치 오차율을 의미한다. 이는 절대치 오차를 실제값으로 나눈 값을 의미하는데 즉 위 예시에서 MAPE는 (|6 - 4| / 6 + |5 - 6| / 5 + |12 - 9| / 12 + |2 - 2| / 2) / 4를 의미한다.
위 다섯가지 평가 방법 모두 sklearn.metrics에 내재되어 있으며 모두 (실제값, 예측값)을 내부 parameter로 입력하여 오차율을 구할 수 있다. 모델을 평가하는 과정은 다음과 같다.
"regression 모델 평가하기"
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error, mean_absolute_percentage_error
print(r2_score(y_test, pred))
# 0.8432104549903816
print(mean_squared_error(y_test, pred))
# 7.279675858978578
print(mean_squared_error(y_test, pred, squared=False))
# 2.6980874446501133
print(mean_absolute_error(y_test, pred))
# 2.2077970304011867
print(mean_absolute_percentage_error(y_test, pred))
# 0.09506480079266404
추가적으로 MSE은 모든 오차를 양수로 바꾸어주는 기능뿐 아니라 큰 오차를 더 크게 만들어줌으로써 튀는 오차를 더 도드라지게 할 수 있다는 장점이 있고 MAE는 오차를 평준화함으로써 고객에게 설명하기 유리하다는 장점이 있다.