2024. 1. 11. 17:40ㆍTIL
데이터 모델링이란?
주어진 데이터에서 사용하고자 하는 x, 알고 싶은 값 y이 있을 때 y = f(x) 라는 함수를 통해서 x와 y의 관계를 설명할 수 있다면 x를 독립변수, y를 종속변수 라고 한다(혹은 x를 feature, y를 label이라고도 부른다). y와 x의 관계를 효과적으로 설명하는 f() 함수를 만드는 일을 모델링이라고 한다. y 값이 존재하는 경우 supervised learning, y 값이 존재하지 않는 경우 unsupervised learning 그리고 y 값이 continuous(연속형) 값인 경우 regression task, y 값이 categorical 값인 경우 classification task이라 한다.
조건부 확률은 어떤 사건이 일어났다는 ‘전제 하에’ 다른 사건이 일어날 확률이다. 두 사건 A, B가 있을 때, 사건 A가 일어났을 때 B가 일어날 확률은 P(B|A) = P(A ∩ B) / P(A)이다. P(A|B) = P(A ∩ B) / P(B)이므로 P(B|A) = P(A|B)P(B) / P(A) 로 표현이 가능하다. 데이터 모델링의 관점에서는 P(θ|X) = P(X|θ)P(θ) / P(X) 로 표현이 가능하다(X: 관측된 데이터, θ: 데이터에 대한 가설, 즉 모델의 parameter값). P(X)는 Marginal probability, 데이터 X 자체의 분포, P(θ)는 Prior probability, 데이터 관측 이전의(사전) Parameter의 확률 분포를 의미한다(보통은 모든 값에 대한 확률이 동일하다고 가정). P(X|θ)는 Likelihood, Parameter가 주어졌을 때 X 데이터가 관측될 확률 분포이고 P(θ|X)는 Posterior probability, Observation (dataset X)가 ‘주어졌을 때’ parameter의 확률분포가 된다. 궁극적인 목적은 P(θ|X)를 최대화 하는 θ를 찾는 것인데,
P(θ)가 일정하다는 가정 하에서는 P(X|θ), Likelihood를 최대화 하는 θ를 추정(MLE)하고 그렇지 않을 때는 P(X|θ)P(θ)를 최대화하는 θ를 추정(MAP)하는 과정이 데이터 모델링이라고 할 수 있다.
데이터 모델링 과정은 먼저 데이터를 전처리 및 분석을 한다. 그다음 데이터를 training set, test set으로 나눈다. training set에 대해서 사용할 모델을 학습시킨다(model.fit(training_set)). test set에 대해서 학습된 모델의 예측값을 통해 모델의 성능을 평가한다(실제값과 예측값의 비교를 통해서). 모델의 성능이 충분히 쓸만하다고 판단될때 새로운 데이터에 대해 학습된 모델을 이용해 y 값을 예측한다(inference 과정).
from sklearn.datasets import make_regression
X,y = make_regression(n_samples=100, n_features=5, noise=50,
random_state=42)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y,
random_state=33)
lr = LinearRegression(normalize=True)
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
print(mean_squared_error(y_test, y_pred))
y_infer = lr.predict(X_infer)
선형회귀
선형회귀는 x와 y 간에 ‘선형의’ 관계(y = b + wx)가 있다고 가정할 때 주로 사용된다. b + wx = y_pred 라는 값에 대해서
y_pred와 실제 y가 최대한 가까워지는 w(weight), b(bias) 값을 찾도록 학습된다.

# Linear Regression
from sklearn.linear_model import LinearRegression
lr = LinearRegression(normalize=True)
# training
lr.fit(X_train, y_train)
# LInear regression evaluation
y_pred = lr.predict(X_test)
# Mean Absolute Error
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
# Mean Squared Error
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
# R² Score
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
Linear regression에서 오차항 ε에 대해 가정하는 5가지가 있다.
- 오차항의 기대치는 0이다
E(ε_i) = 0 - 오차항은 일정한 분산을 가진다
Var(ε_i) = σ2 - i != j일 때 ε_i와 ε_j는 서로 독립이다
Cov(ε_i,ε_j) = 0 if i != j - 독립변수 X와 ε_i는 서로 독립이다
Cov(X,ε_i) = 0 - ε_i는 정규분포 N(0, σ^2)를 따른다
ε_i~ N(0, σ^2)
오차항에 대한 가정을 통해 다음과 같은 가정이 가능하다.
- 회귀모형은 선형성을 가진다.
즉, E(Y_i) = E(b + wX_i+ ε_i) = b + wX_i+ E(ε_i)
이때, E(ε_i)=0 이므로 E(Y_i) = b + wX_i - 종속변수 Y의 분산은 일정한 값 σ^2를 가진다
Var(Y_i) = Var(b + wX_i + ε_i) = Var(ε_i) = σ^2 - ε_i와 ε_j는 서로 독립이며, ε_i는 자기상관성이 없다
→ 시계열 데이터의 경우 자기상관성이 존재할 수 있다 - Y는 정규분포를 따른다
E(Y_i) = b + wX_i, Var(Y_i) = σ^2이므로 Y~N(b + wX , σ^2)
좋은 데이터 모델링을 하기 위해 실제 Y와 Y_pred의 오차를 계산하는 식을 세우고, 이 오차를 최소화하는 w, b를 찾아야 한다. 이 때, 실제값과 예측값의 오차에 대한 식을 손실함수(loss function), 비용함수(cost function), 혹은 목적함수(objective function)이라고 한다. 선형회귀에서는 기본적으로 Residual sum of squares(RSS), 혹은 Mean squared error(MSE)를 cost function으로 사용한다. Cost function이 differentiable(미분가능)하고 convex(아래로 볼록)할 때, cost의 최저점은 cost function을 w, b로 각각 편미분 했을 때 0이 되는 지점이다.
오차 ε를 최소화하는 w, b를 추정하는 방법으로 Ordinary Least Squares(OLS, 최소제곱법)을 사용한다. ε의 제곱의 합이 최소가 되는 점을 찾기 위해서는 ε의 제곱의 합을 w, b로 표현한 뒤 w, b로 각각 편미분 했을 때 0이 되면서 2차 편미분(Jacobian) 값이 Positive definite이 되도록 해야한다(볼록 함수 만족).
변수가 많아지거나 cost function이 복잡해지는 경우, 최소 제곱법을 통해서 한 번에 loss가 최소인 parameter를 추정하기 어렵다. 이러한 경우, 각 parameter에 대해서 cost function을 편미분한 값(gradient)을 learning rate α만큼 여러 번 update 해주는 것을 gradient descent(경사 하강법)라고 한다. Gradient descent를 사용하는 경우에는 보통 데이터가 매우 많으므로, 모든 학습 데이터에 대해서 한번에 gradient descent step을 계산하는 batch gradient descent 보다는 매 스텝에서mini batch 만큼의 데이터를 샘플링해서 학습하는 mini-batch stochastic gradient descent(SGD)방식으로 학습한다.
Ridge, Lasso
Overfitting(과적합, high variance)은 학습데이터에 대해서 과하게 fitting되는 경우를 의미한다. Generalization(일반화)는 학습할 때와 추론할 때의 성능 차이가 많이 나지 않는 경우. 즉, 모델이 여러 inference 상황에서 잘 쓰일 수 있음을 의미한다. Overfitting이 발생하는 경우, test set에서의 loss가 증가할 수 있기 때문에 실제 inference 상황에서 모델이generalization(일반화)되기 어렵게 된다. Overfitting은 보통 데이터에 내재된 복잡도(complexity)보다 모델의 복잡도가 더 과한 경우나, 데이터셋 사이즈가 작은 경우 자주 발생한다. Linear regression의 경우, 고려하는 변수가 많아질수록 overfitting이 발생할 가능성이 높아진다. Overfitting을 해결하는 방법은 크게 두 가지이다.
- 모델의 복잡도 줄이기:
모델이 가질 수 있는 parameter를 줄이거나 (e.g. 딥러닝에서 모델의 사이즈)
모델이 고려하는 feature 중에서 상대적으로 중요한 feature 들만 모델의 input으로 사용해 볼 수 있다 - 정규화(Regularization):
모델이 가지는 복잡도를 제한하는 방법으로 보통 모델의 parameter가 가지는 값의 크기를
cost function에 추가해 주는 방식으로 parameter 값의 크기를 제한한다
Ridge regression는 선형 회귀 모델에 L2 loss를 추가해서 parameter를 정규화해준다. Ridge regression모델의 페널티항은 모델의 weight parameter들의 제곱합이며, lambda hyperparameter를 이용해서 모델에 주어지는 페널티를 조절한다.

# Ridge regression
from sklearn.linear_model import Ridge
rlr = Ridge(alpha=1.0)
# training
rlr.fit(X_train, y_train)
# Ridge regression evaluation
y_pred = rlr.predict(X_test)
# Mean Absolute Error
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
# Mean Squared Error
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
# R² Score
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
Lasso regression은 선형 회귀 모델에 L1 loss를 추가해서 parameter를 정규화해준다. Lasso regression모델의 페널티항은 모델의 weight parameter들의 절댓값의 합이다.

# Lasso regression
from sklearn.linear_model import Lasso
llr = Lasso(alpha=1.0)
# training
llr.fit(X_train, y_train)
# Lasso regression evaluation
y_pred = llr.predict(X_test)
# Mean Absolute Error
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
# Mean Squared Error
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
# R² Score
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
로지스틱 회귀, SVM
Logistic regression은 Linear regression의 output y 값에 ‘Sigmoid function’을 적용해서 output y의 값이 0~1 사이 값이 되도록 만든다. 그래서 Classification에 적합화된 Linear regression model이다.

# Logistic Regression
from sklearn.linear_model import LogisticRegression
lgr = LogisticRegression()
# training
lgr.fit(X, y)
# Logistic regression evaluation
y_pred = lgr.predict(X_test)
from sklearn.metrics import accuracy_score
print('accuracy: ', accuracy_score(y_test, y_pred))
from sklearn.metrics import precision_score
print('precision: ', precision_score(y_test, y_pred))
from sklearn.metrics import recall_score
print('recall: ', recall_score(y_test, y_pred))
from sklearn.metrics import f1_score
print('f1: ', f1_score(y_test, y_pred))
Support Vecter Machine(SVM)은 Linear regression과 비슷하지만, 어느 정도의 허용오차(C) 안에 있는 오차값은
허용해 준다. 허용 오차 C 값을 잘 설정해야 모델이 좋은 성능을 낼 수 있다. kernel= 설정을 통해 모델이 가정하는 x와 y의
관계(선형, 2차 선형, …) 등을 잘 잡아낼 수 있다.
# Support Vector Machines (SVM)
from sklearn.svm import SVR
svr= SVR(kernel='linear', C=10.)
# training
svr.fit(X_train, y_train)
# SVR evaluation
y_pred = svr.predict(X_test)
# Mean Absolute Error
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
# Mean Squared Error
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
# R² Score
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
Random Forest
Decision Tree는 x를 기준 삼아, "해당 기준을 만족/불만족시 y값이 ~값일 것이다”라는 조건(x)-결과(y) 를 나무처럼 발전시킨다. Classification에서는 y값이 클래스, Regression에서는 y값이 평균값이다. RandomForest는 Decision Tree를 무작위로 여러 개 만든 후, 각 tree마다 나온 decision들을 voting(ensemble)을 통해서 최종적인 y 값을 예측한다. n_estimators(트리의 개수), max_depth(각 트리의 길이) 등을 설정하여 모델의 성능을 높일 수 있다. 다만, 무조건 트리 개수나 길이값이 크다고 성능이 좋아지진 않으며, 학습 시간이나 차지하는 메모리가 지나치게 커질 수 있다.
# Random Forest
from sklearn.ensemble import RandomForestRegressor
rfr= RandomForestRegressor(n_estimators=100, max_depth=200)
# training
rfr.fit(X_train, y_train)
# Random forest evaluation
y_pred = rfr.predict(X_test)
# Mean Absolute Error
from sklearn.metrics import mean_absolute_error
print(mean_absolute_error(y_test, y_pred))
# Mean Squared Error
from sklearn.metrics import mean_squared_error
print(mean_squared_error(y_test, y_pred))
# R² Score
from sklearn.metrics import r2_score
print(r2_score(y_test, y_pred))
공부하며 어려웠던 내용
과거 편미분과 선형회귀 과목을 들은 기억을 되살려 스스로 식을 유도해 보고 공부해야겠다.
'TIL' 카테고리의 다른 글
| 1. 데이터 웨어하우스 소개 (1) | 2024.01.22 |
|---|---|
| 데이터 분석 과정 및 시각화 실습(5) (0) | 2024.01.12 |
| 데이터 분석 과정 학습 및 시각화 실습(3)-2 (1) | 2024.01.10 |
| 데이터 분석 과정 학습 및 시각화 실습(3)-1 (1) | 2024.01.10 |
| 데이터 분석 과정 학습 및 시각화 실습(2) (2) | 2024.01.09 |