[ML] HAR (DT, GridSearch, RF 실습)

svenskpotatis·2023년 11월 12일

앙상블 기법

  • voting: 전체 dataset, 다른 algorithm
    • hard voting, soft voting
  • bagging: dataset에서 랜덤하게 샘플링
    • bootstrapping 분할
    • random forest: bagging의 대표적인 방법
  • cf. 비정형 데이터: 딥러닝이 훨씬 좋음 but 정형 데이터(table, excel ..): 머신러닝이 나음

HAR, Human Activity Recognition

  • 사람 행동 예측
  • UCI HAR 데이터셋

머신러닝을 이용한 행동 인식 연구

  • 센서신호(row sensor signa)
  • 특징추출(feature extraction)
  • 모델학습(model training)
  • 행동추론(activity inference)
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/HAR_dataset/features.txt'

feature_name_df = pd.read_csv(url, sep='\s+', header=None, names=['column_index', 'column_name'])

X_train_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/HAR_dataset/train/X_train.txt'
X_test_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/HAR_dataset/test/X_test.txt'

X_train = pd.read_csv(X_train_url, sep='\s+', header=None)
X_test = pd.read_csv(X_test_url, sep='\s+', header=None)
X_train.info()

>>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7352 entries, 0 to 7351
Columns: 561 entries, 0 to 560
dtypes: float64(561)
memory usage: 31.5 MB
X_test.info()

>>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2947 entries, 0 to 2946
Columns: 561 entries, 0 to 560
dtypes: float64(561)
memory usage: 12.6 MB

--> 대용량 데이터이다.

X_train.shape, X_test.shape, y_train.shape, y_test.shape

>>>
((7352, 561), (2947, 561), (7352, 1), (2947, 1))

DT

# DT
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

dt_clf = DecisionTreeClassifier(random_state=13, max_depth=4)
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
accuracy_score(y_test, pred)

--> 0.8096369189005769

GridSearch

max_depth 바꿔보기

from sklearn.model_selection import GridSearchCV

params = {
    'max_depth': [6, 8, 10, 12, 16, 20, 24]
}

grid_cv = GridSearchCV(dt_clf, param_grid=params, 
                       scoring='accuracy', 
                       cv=5, 
                       return_train_score=True)

grid_cv.fit(X_train, y_train)

--> 오래 걸림...


  • best score, best params 물어보기
grid_cv.best_score_, grid_cv.best_params_

(0.8543335321892183, {'max_depth': 8})
--> max_depth 8이 좋다고 함.

# max depth 별로 표로 성능 정리

cv_results_df = pd.DataFrame(grid_cv.cv_results_)
cv_results_df[['param_max_depth', 'mean_test_score', 'mean_train_score']]

max_depth = [6, 8, 10, 12, 16, 20, 24]

for depth in max_depth:
    dt_clf = DecisionTreeClassifier(max_depth=depth, random_state=13)
    dt_clf.fit(X_train, y_train)

    pred = dt_clf.predict(X_test)
    accuracy = accuracy_score(y_test, pred)

    print('Max_Depth: ', depth, ', Accuracy: ', accuracy)

>>>
Max_Depth: 6 , Accuracy: 0.8554462164913471
Max_Depth: 8 , Accuracy: 0.8734306073973532
Max_Depth: 10 , Accuracy: 0.8615541228367831
Max_Depth: 12 , Accuracy: 0.8595181540549711
Max_Depth: 16 , Accuracy: 0.8669833729216152
Max_Depth: 20 , Accuracy: 0.8652867322701052
Max_Depth: 24 , Accuracy: 0.8652867322701052


  • best model
best_dt_clf = grid_cv.best_estimator_
pred1 = best_dt_clf.predict(X_test)

accuracy_score(y_test, pred1)

0.9205972175093315

랜덤 포레스트 적용

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier

params = {
    'max_depth': [6, 8, 10],
    'n_estimators': [50, 100, 200],
    'min_samples_leaf': [8, 12],
    'min_samples_split': [8, 12]
}
rf_clf = RandomForestClassifier(random_state=13, n_jobs=-1)
grid_cv = GridSearchCV(rf_clf, param_grid=params, cv=2, n_jobs=1)
grid_cv.fit(X_train, y_train)

--> DT보다 빠름


  • 결과 정리
cv_results_df = pd.DataFrame(grid_cv.cv_results_)
cv_results_df.columns
>>>
Index(['mean_fit_time', 'std_fit_time', 'mean_score_time', 'std_score_time',
       'param_max_depth', 'param_min_samples_leaf', 'param_min_samples_split',
       'param_n_estimators', 'params', 'split0_test_score',
       'split1_test_score', 'mean_test_score', 'std_test_score',
       'rank_test_score'],
      dtype='object')

target_col = ['rank_test_score', 'mean_test_score', 'param_n_estimators', 'param_max_depth']
cv_results_df[target_col].sort_values('rank_test_score').head()

--> 공동 1위, 공동 3위, 5위
--> 나무 많다고 좋은 거 아님 - param_n_estimators: 나무 수
--> mean_test_score: traning data의 validation score


best model

grid_cv.best_params_

>>>
{'max_depth': 10,
 'min_samples_leaf': 8,
 'min_samples_split': 8,
 'n_estimators': 100}
grid_cv.best_estimator_

>>>
RandomForestClassifier(max_depth=10, min_samples_leaf=8, min_samples_split=8,
                       n_jobs=-1, random_state=13)
grid_cv.best_score_

>>>
0.9144450489662677

# test 데이터에 적용
rf_clf_best = grid_cv.best_estimator_
rf_clf_best.fit(X_train, y_train)

pred1 = rf_clf_best.predict(X_test)
accuracy_score(y_test, pred1)

0.9205972175093315

중요 특성 확인

best_cols_values = rf_clf_best.feature_importances_
best_cols = pd.Series(best_cols_values, index=X_train.columns)

# 중요한 거 20개만 갖고옴
top20_cols = best_cols.sort_values(ascending=False)[:20]
top20_cols
>>>
angle(X,gravityMean)               0.034635
tGravityAcc-max()-Y                0.032518
tGravityAcc-energy()-X             0.031309
tGravityAcc-mean()-X               0.029513
tGravityAcc-min()-X                0.027775
tGravityAcc-max()-X                0.027662
angle(Y,gravityMean)               0.026550
tGravityAcc-mean()-Y               0.026048
tGravityAcc-min()-Y                0.023037
tGravityAcc-energy()-Y             0.018678
tGravityAcc-mean()-Z               0.015688
angle(Z,gravityMean)               0.012831
fBodyAcc-mad()-X                   0.012558
tBodyAcc-max()-X                   0.011970
fBodyAccJerk-bandsEnergy()-1,24    0.011803
tBodyAccJerk-entropy()-X           0.011647
tGravityAccMag-std()               0.011451
tBodyAccJerk-energy()-X            0.011333
tGravityAcc-arCoeff()-Z,1          0.011281
fBodyAccJerk-max()-X               0.011040
dtype: float64

  • 주요 특성 관찰
import seaborn as sns

plt.figure(figsize=(8, 8))
sns.barplot(x=top20_cols, y=top20_cols.index)
plt.show()

  • 20 개 특성만 가지고 다시 성능 확인

    • 561개 특성보다 20개의 특성만 보면 연산속도 빠를 것임.
X_train_re = X_train[top20_cols.index]
X_test_re = X_test[top20_cols.index]

rf_clf_best_re = grid_cv.best_estimator_
rf_clf_best_re.fit(X_train_re, y_train.values.reshape(-1,))

pred1_re = rf_clf_best_re.predict(X_test_re)
accuracy_score(y_test, pred1_re)

0.8184594502884289

0개의 댓글