처음 배우는 사람이고, 정확하지 않겠지만, 과제를 수행하고 스스로 kaggle에 도전하기 위해 (즉, 내가 보려고) 기본적인 스텝을 한 번 정리해보겠다.
<지도학습
의 분류문제
의 경우>
1. 전처리
2. 타겟, 피쳐 분리
3. train, (validation set), test set 분리
4. Baseline 설정 및 성능확인
5. train set으로 모델 학습
6. 모델 성능 확인
7. 모델 성능 개선
8. test set으로 확인
1. 전처리
⭕⭕⭕
null값, 이상치, 정보 누수, 범주형/수치형 데이터 처리, 로그 변환 등의 정리를 잘 해줘야 성능이 좋아지기 때문에 신경써서 할 것!
⭕⭕⭕
2,3. 타겟, 피쳐 분리 + train/val/test set 분리
def get_train_test_dataset(df=None):
from sklearn.model_selection import train_test_split
target = '타겟'
y_target = df[target]
X_features = df.drop(columns=target)
# train, test 분할
X_train, X_test, y_train, y_test = train_test_split(X_features, y_target, test_size=0.2, stratify=y_target)
# train, val 분할
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, stratify=y_train)
return X_train, X_val, X_test, y_train, y_val, y_test
X_train, X_val, X_test, y_train, y_val, y_test = get_train_test_dataset(df)
print(X_train.shape, X_val.shape, X_test.shape, y_train.shape, y_val.shape, y_test.shape)
4. Baseline 설정 및 성능확인 + target의 클래스 비율 확인
from sklearn.metrics import accuracy_score
#기준모델 설정
major = y_train.mode()[0]
y_pred_base = [major] * len(y_train)
#기준모델 성능 확인
print("baseline의 정확도: ", accuracy_score(y_train, y_pred_base))
#target의 클래스 비율 확인
1_cnt = df['타겟'].value_counts()[1]
total_cnt = df['타겟'].count()
print('맞추고 싶은 클래스의 비율은 {0:.2f}'.format((1_cnt / total_cnt)))
5. train set으로 모델 학습
모델을 잘 선택해야함. 그 데이터가 가지고 있는 성질을 확인해서 아래 중에서 잘 선택해서 해 볼 것.
로지스틱 회귀
lr_clf = LogisticRegression()
lr_clf.fit(X_train , y_train)
pred = lr_clf.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print('로지스틱 회귀 정확도: {0:.4f}'.format(accuracy))
결정 트리
dt_clf = DecisionTreeClassifier(n_estimators=100, random_state=0, max_depth=8)
dt_clf.fit(X_train , y_train)
pred = dt_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy))
랜덤 포레스트
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0, max_depth=8)
rf_clf.fit(X_train , y_train)
pred = rf_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy))
XGB
xgb_wrapper = XGBClassifier(n_estimators=400, learning_rate=0.05, max_depth=3, eval_metric='logloss')
xgb_wrapper.fit(X_train, y_train, verbose=True)
pred = xgb_wrapper.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('XGB 정확도: {0:.4f}'.format(accuracy))
LGBM
lgbm_wrapper = LGBMClassifier(n_estimators=400, learning_rate=0.05)
lgbm_wrapper.fit(X_tr, y_tr, early_stopping_rounds=50, eval_metric="logloss",
eval_set=evals, verbose=True)
pred = lgbm_wrapper.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('LGBM 정확도: {0:.4f}'.format(accuracy))
6. 모델 성능 확인
데이터의 성질과 타겟값의 비율 등을 고려해서 아래 중에서 어떤 걸 중요하게 볼 것인가를 신경쓸 것.
from sklearn.metrics import accuracy_score, precision_score , recall_score, f1_score, from sklearn.metrics import roc_auc_score
confusion = confusion_matrix(y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test , pred)
roc_score = roc_auc_score(y_test, pred_proba)
(교차검증)
- KFold
- Stratifiedflod
- cross_val_score() *거의 stratifiedfold 하는 경우가 많음
7. 모델 성능 개선
적당한 모델을 선택했으면, 각각의 하이퍼 파라미터를 최적화해서 성능을 더 끌어올려야 한다. 쓸 수 있는 방법은 아래와 같다.
RandomSearchCV
dists = {
'모델 인스턴스__n_estimators': randint(50, 500),
'모델 인스턴스__max_depth': [4, 5, 6, 8, 10, 15],
'모델 인스턴스__max_features': [3,5,8,10,15]
}
clf = RandomizedSearchCV(
pipe,
param_distributions=dists,
n_iter=50,
cv=3,
scoring='f1',
refit=True,
verbose=1,
n_jobs=-1
)
clf.fit(X_train, y_train)
print('RandomizedSearchCV 최적 하이퍼파라미터: ', clf.best_params_)
print('RandomizedSearchCV 최고 정확도: {0:.4f}'.format(clf.best_score_))
#쓸 수 있는 Attribute
clf.best_score_
clf.best_params_
clf.cv_results_
clf.best_estimator_
GridSearchCV
params = {
'모델 인스턴스__max_depth': [8, 16, 24],
'모델 인스턴스__min_samples_leaf' : [1, 6, 12],
'모델 인스턴스__min_samples_split' : [2, 8, 16]
}
grid_cv = GridSearchCV('모델 인스턴스', param_grid=params, scoring='accuracy', cv=5, verbose=1) #refit=True는 주의해서!
grid_dtree.fit(X_train, y_train)
print('GridSearchCV 최적 파라미터:', grid_dtree.best_params_)
print('GridSearchCV 최고 정확도: {0:.4f}'.format(grid_dtree.best_score_))
#쓸 수 있는 Attribute
grid_cv.best_score_
grid_cv.best_params_
grid_cv.cv_results_
grid_cv.best_estimator_
특성 중요도를 확인하고 특성을 제거해주는 것도 방법임.
특성 중요도 확인
- featureimportance
- permutationimportance
feature importance
(pipe line 썼을 때)
tree_feature_importances = (rf.named_steps['classifier'].feature_importances_)
sorted_idx = tree_feature_importances.argsort()
#시각화
y_ticks = np.arange(0, len(feature_names))
fig, ax = plt.subplots()
ax.barh(y_ticks, tree_feature_importances[sorted_idx])
ax.set_yticklabels(feature_names[sorted_idx])
ax.set_yticks(y_ticks)
ax.set_title("Random Forest Feature Importances (MDI)")
fig.tight_layout()
plt.show()
#다른 방법
model_dt = pipe.named_steps['decisiontreeclassifier']
enc = pipe.named_steps['onehotencoder']
encoded_columns = enc.transform(X_val).columns
importances = pd.Series(model_dt.feature_importances_, encoded_columns)
plt.figure(figsize=(10,30))
importances.sort_values().plot.barh();
permulation importance
(pipe line 안 썼을 때)
result = permutation_importance(rf, X_test, y_test, n_repeats=10, random_state=42, n_jobs=2)
sorted_idx = result.importances_mean.argsort()
#시각화
fig, ax = plt.subplots()
ax.boxplot(result.importances[sorted_idx].T,
vert=False, labels=X_test.columns[sorted_idx])
ax.set_title("Permutation Importances (test set)")
fig.tight_layout()
plt.show()
인코더 바꾸기
- TargetEncoder
- LabelEncoder
- OnehotEncoder
- OrdinalEncoder
기본문법
from sklearn.preprocessing import LabelEncoder
# 라벨인코더 선언 및 Fitting
le = LabelEncoder()
le.fit(categorical_data)
# 인코딩한 데이터로 변환
le_encoded = le.transform(categorical_data)
데이터 스케일링
Train Data에만 해야함!
Standard Scaling
from sklearn.preprocessing import StandardScaler
# StandardScaler 선언 및 Fitting
sdscaler = StandardScaler()
sdscaler.fit(numeric_data)
# 데이터 변환
sdscaled_data = sdscaler.transform(numeric_data)
# 데이터 프레임으로 저장
sdscaled_data = pd.DataFrame(sdscaled_data)
Min-Max Scaling
from sklearn.preprocessing import MinMaxScaler
# MinMaxScaler 선언 및 Fitting
mMscaler = MinMaxScaler()
mMscaler.fit(numeric_data)
# 데이터 변환
mMscaled_data = mMscaler.transform(numeric_data)
# 데이터 프레임으로 저장
mMscaled_data = pd.DataFrame(mMscaled_data)
결측치 처리
SimpleImputer
(strategy='대체할 값')
'mean', 'median' -> 수치형 데이터
'most_frequent'-> 범주형 데이터
from sklearn.impute import SimpleImputer
# 평균으로 Imputer 선언
imputer_mean = SimpleImputer(strategy='mean')
imputer_mean.fit(numeric_data)
# 데이터 변환 (array로 반환하기 때문에 필요에 맞는 형태로 변환 후 사용)
numeric_data = imputer_mean.transform(numeric_data)
이상치 제거
#함수 쓸 때
def get_outlier(df=None, column=None, weight=1.5):
'타겟 1값' = df[df['타겟']==1][column]
quantile_25 = np.percentile('타겟 1값'.values, 25)
quantile_75 = np.percentile('타겟 1값'.values, 75)
iqr = quantile_75 - quantile_25
iqr_weight = iqr * weight
lowest_val = quantile_25 - iqr_weight
highest_val = quantile_75 + iqr_weight
outlier_index = '타겟 1값'[('타겟 1값' < lowest_val) | ('타겟 1값' > highest_val)].index
return outlier_index
df.drop(outlier_index, axis=0, inplace=True)
#함수 안 쓰면
q1_a=df['타겟'].quantile(0.25)
q3_a=df['타겟'].quantile(0.75)
iqr=q3_a-q1_a
condition=(df['타겟'] > q3_a + 1.5*iqr) | (df['타겟'] < q1_a + 1.5*iqr)
a=df[condition].index
df.drop(a,inplace=True)