728x90
1. Logistic Regression (로지스틱 회귀 개요)
선형 회귀 방식(선형 모델)을 분류 문제에 적용한 알고리즘
- 로지스틱 회귀는 분류에 사용됨
- 분류 문제들은 클래스 Y를 직접 예측하기 보다는 Y가 특정 Class일 확률 pr[Y=k|X] ~ f(X)를 예측하고자 함
- 선형회귀와 다른점은 선형 함수의 회귀 최적선을 찾은 것이 아니라, sigmoid 함수의 최적선을 찾고 이 sigmoid 함수의 반환 값을 확률로 간주해 확률에 따라 분류를 결정한다는 것
주로 Binary Classification(이진 분류)에 사용됨 (Multi-Class Classification: 다중 클래스 분류에도 사용가능)
- 로지스틱 회귀에서 예측 값은 예측 확률을 의미하며, 예측 값 즉 예측 확률이 0.5 이상이면 1로, 0.5 이하이면 0으로 예측함
- 로지스틱 회귀의 예측 확률을 시그모이드 함수의 출력값으로 계산됨
로지스틱 회귀는 학습을 통해 Sigmoid 함수의 Model Parameter(W)를 최적화하여 예측하는 것
Logistic Regression의 장단점
- Logistic Regression은 가볍고, 빠르며, 이진 분류 예측 성능도 뛰어남
- 희소한 데이터 세트 분류에서 성능이 좋아서 텍스트 분류에 자주 활용
2. Logistic Regression @ Scikit - Learn
Scikit - Learn은 Logistic Regression을 LogisticRegression Class로 구현함
- LogisticRegression의 주요 하이퍼파라미터: penalty, C, solver
- penalty: 규제 유형을 설정 ('l2' - L2 규제, 'l1' - L1 규제)
- C: 규제 강도를 조절하는 alpha의 역수 값 ($C = \frac {1} {\alpha}$)
- inverse regularization
- C가 작을수록 규제 강도가 크다
- solver: 회귀 계수 최적화를 위한 다양한 최적화 방식
LogisticRegression의 solver 유형
- lbfgs
- L1 규제를 지원하지 않음
- liblinear
- newton-cg
- sag
- saga
-> 성능이 solver 유형 차이로 인해 크게 나지는 않는다
Code 실습 - LogisticRegression w/ 위스콘신 암 예측 모델
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
cancer = load_breast_cancer()
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# StandardScaler( )로 평균이 0, 분산 1로 데이터 분포도 변환
scaler = StandardScaler()
data_scaled = scaler.fit_transform(cancer.data)
X_train , X_test, y_train , y_test = train_test_split(data_scaled, cancer.target, test_size=0.3, random_state=0)
from sklearn.metrics import accuracy_score, roc_auc_score
# 로지스틱 회귀를 이용하여 학습 및 예측 수행.
# solver인자값을 생성자로 입력하지 않으면 solver='lbfgs'
lr_clf = LogisticRegression() # solver='lbfgs'
lr_clf.fit(X_train, y_train)
lr_preds = lr_clf.predict(X_test)
# accuracy와 roc_auc 측정
print('accuracy: {0:.3f}, roc_auc:{1:.3f}'.format(accuracy_score(y_test, lr_preds),
roc_auc_score(y_test , lr_preds)))
# accuracy: 0.977, roc_auc:0.972
solvers = ['lbfgs', 'liblinear', 'newton-cg', 'sag', 'saga']
# 여러개의 solver값 별로 LogisticRegression 학습 후 성능 평가
for solver in solvers:
lr_clf = LogisticRegression(solver=solver, max_iter=600)
lr_clf.fit(X_train, y_train)
lr_preds = lr_clf.predict(X_test)
# accuracy와 roc_auc 측정
print('solver:{0}, accuracy: {1:.3f}, roc_auc:{2:.3f}'.format(solver,
accuracy_score(y_test, lr_preds),
roc_auc_score(y_test , lr_preds)))
# solver:lbfgs, accuracy: 0.977, roc_auc:0.972
# solver:liblinear, accuracy: 0.982, roc_auc:0.979
# solver:newton-cg, accuracy: 0.977, roc_auc:0.972
# solver:sag, accuracy: 0.982, roc_auc:0.979
# solver:saga, accuracy: 0.982, roc_auc:0.979
- solver = 'lbfgs'가 L1 규제를 지원하지 않아서 오류 발생
from sklearn.model_selection import GridSearchCV
params={'solver':['liblinear', 'lbfgs'],
'penalty':['l2', 'l1'],
'C':[0.01, 0.1, 1, 1, 5, 10]}
lr_clf = LogisticRegression()
grid_clf = GridSearchCV(lr_clf, param_grid=params, scoring='accuracy', cv=3 )
grid_clf.fit(data_scaled, cancer.target)
print('최적 하이퍼 파라미터:{0}, 최적 평균 정확도:{1:.3f}'.format(grid_clf.best_params_,
grid_clf.best_score_))
# 최적 하이퍼 파라미터:{'C': 0.1, 'penalty': 'l2', 'solver': 'liblinear'}, 최적 평균 정확도:0.979
3. CART (Classification and Regression Tree)
Scikit - Learn의 결정 트리 및 결정 트리 기반의 앙상블 알고리즘은 분류 뿐만 아니라 회귀도 가능
이는 트리가 CART를 기반으로 만들어졌기 때문임 (CART는 분류 뿐만 아니라 회귀도 가능한 트리 분할 알고리즘)
CART Regression Tree는 분류와 유사하게 분할을 하며
최종 분할이 완료된 후에 각 분할 영역에 있는 데이터 결정값들의 평균 값으로 학습 / 예측
- 각 분할 영역에서 MSE를 최소화하는 y는 sample space에 있는 데이터 결정값들의 평균이기 때문
- Regression Tree: RBS를 이용하여 Sample Space를 분할 + 최적의 분할 지점 평가 by MSE(RSS)를 최소화
- Classification Tree: RBS를 이용하여 Sample Space를 분할 + 최적의 분할 지점을 평가 by 분류 오류, 지니 불순도, Cross-Entropy
CART
Scikit - Learn의 RegressionTree 지원
RegressionTree Overfitting
4. Regression Tree @ Scikit - Learn
Regression Tree를 이용한 보스턴 주택 가격 예측
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestRegressor
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore') #사이킷런 1.2 부터는 보스턴 주택가격 데이터가 없어진다는 warning 메시지 출력 제거
# 보스턴 데이터 세트 로드
# boston 데이타셋 로드
X_data, y_target = datasets.fetch_openml('boston', return_X_y=True)
X_data = X_data.astype(float)
rf = RandomForestRegressor(random_state=0, n_estimators=1000)
neg_mse_scores = cross_val_score(rf, X_data, y_target, scoring="neg_mean_squared_error", cv = 5)
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)
print(' 5 교차 검증의 개별 Negative MSE scores: ', np.round(neg_mse_scores, 2))
print(' 5 교차 검증의 개별 RMSE scores : ', np.round(rmse_scores, 2))
print(' 5 교차 검증의 평균 RMSE : {0:.3f} '.format(avg_rmse))
# 5 교차 검증의 개별 Negative MSE scores: [ -7.88 -13.14 -20.57 -46.23 -18.88]
# 5 교차 검증의 개별 RMSE scores : [2.81 3.63 4.54 6.8 4.34]
# 5 교차 검증의 평균 RMSE : 4.423
def get_model_cv_prediction(model, X_data, y_target):
neg_mse_scores = cross_val_score(model, X_data, y_target, scoring="neg_mean_squared_error", cv = 5)
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)
print('##### ',model.__class__.__name__ , ' #####')
print(' 5 교차 검증의 평균 RMSE : {0:.3f} '.format(avg_rmse))
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
dt_reg = DecisionTreeRegressor(random_state=0, max_depth=4)
rf_reg = RandomForestRegressor(random_state=0, n_estimators=1000)
gb_reg = GradientBoostingRegressor(random_state=0, n_estimators=1000)
xgb_reg = XGBRegressor(n_estimators=1000)
lgb_reg = LGBMRegressor(n_estimators=1000)
# 트리 기반의 회귀 모델을 반복하면서 평가 수행
models = [dt_reg, rf_reg, gb_reg, xgb_reg, lgb_reg]
for model in models:
get_model_cv_prediction(model, X_data, y_target)
# ##### DecisionTreeRegressor #####
# 5 교차 검증의 평균 RMSE : 5.978
# ##### RandomForestRegressor #####
# 5 교차 검증의 평균 RMSE : 4.423
# ##### GradientBoostingRegressor #####
# 5 교차 검증의 평균 RMSE : 4.269
# ##### XGBRegressor #####
# 5 교차 검증의 평균 RMSE : 4.251
# ##### LGBMRegressor #####
# 5 교차 검증의 평균 RMSE : 4.646
import seaborn as sns
%matplotlib inline
rf_reg = RandomForestRegressor(n_estimators=1000)
# 앞 예제에서 만들어진 X_data, y_target 데이터 셋을 적용하여 학습합니다.
rf_reg.fit(X_data, y_target)
feature_series = pd.Series(data=rf_reg.feature_importances_, index=X_data.columns)
feature_series = feature_series.sort_values(ascending=False)
sns.barplot(x= feature_series, y=feature_series.index)
import matplotlib.pyplot as plt
%matplotlib inline
bostonDF_sample = bostonDF[['RM','PRICE']]
bostonDF_sample = bostonDF_sample.sample(n=100,random_state=0)
print(bostonDF_sample.shape)
plt.figure()
plt.scatter(bostonDF_sample.RM , bostonDF_sample.PRICE,c="darkorange")
import numpy as np
from sklearn.linear_model import LinearRegression
# 선형 회귀와 결정 트리 기반의 Regressor 생성. DecisionTreeRegressor의 max_depth는 각각 2, 7
lr_reg = LinearRegression()
rf_reg2 = DecisionTreeRegressor(max_depth=2)
rf_reg7 = DecisionTreeRegressor(max_depth=7)
# 실제 예측을 적용할 테스트용 데이터 셋을 4.5 ~ 8.5 까지 100개 데이터 셋 생성.
X_test = np.arange(4.5, 8.5, 0.04).reshape(-1, 1)
# 보스턴 주택가격 데이터에서 시각화를 위해 피처는 RM만, 그리고 결정 데이터인 PRICE 추출
X_feature = bostonDF_sample['RM'].values.reshape(-1,1)
y_target = bostonDF_sample['PRICE'].values.reshape(-1,1)
# 학습과 예측 수행.
lr_reg.fit(X_feature, y_target)
rf_reg2.fit(X_feature, y_target)
rf_reg7.fit(X_feature, y_target)
pred_lr = lr_reg.predict(X_test)
pred_rf2 = rf_reg2.predict(X_test)
pred_rf7 = rf_reg7.predict(X_test)
- 학습(정답) 데이터 scatter, 예측 데이터 'linear' or 'tree'
fig , (ax1, ax2, ax3) = plt.subplots(figsize=(14,4), ncols=3)
# X축값을 4.5 ~ 8.5로 변환하며 입력했을 때, 선형 회귀와 결정 트리 회귀 예측 선 시각화
# 선형 회귀로 학습된 모델 회귀 예측선
ax1.set_title('Linear Regression')
ax1.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax1.plot(X_test, pred_lr,label="linear", linewidth=2 )
# DecisionTreeRegressor의 max_depth를 2로 했을 때 회귀 예측선
ax2.set_title('Decision Tree Regression: \n max_depth=2')
ax2.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax2.plot(X_test, pred_rf2, label="max_depth:2", linewidth=2 )
# DecisionTreeRegressor의 max_depth를 7로 했을 때 회귀 예측선
ax3.set_title('Decision Tree Regression: \n max_depth=7')
ax3.scatter(bostonDF_sample.RM, bostonDF_sample.PRICE, c="darkorange")
ax3.plot(X_test, pred_rf7, label="max_depth:7", linewidth=2)
728x90