project:eve
23.01.24 Classification 분류분석 본문
오늘은 저번에 못다한 분류분석을 이어서 하려고 한다.
sklearn dataset 중 붓꽃 데이터를 가지고 간단한 분류분석을 해보기로 했다.
분석 모델은 의사결정나무를 사용!
1) 데이터 가져오기
from sklearn.datasets import load_iris
iris = load_iris()
df_iris = pd.DataFrame(iris.data, columns=iris.feature_names)
df_iris['result'] = iris.target
여기까지는 이제 뚝딱이다.
가장 간단하게 하려면 여기에서 훈련/검증 데이터 나눠서 fit-predict하면 되는데, 책에서는 데이터 수가 적기 때문에 교차검증 과정을 거쳐야 한다고 한다.
2) 교차검증 정의하기
교차검증이란 전체 데이터를 n개로 나누고, 이 데이터 중 각각 1개씩 돌아가며 검증 데이터가 되고 나머지는 훈련 데이터가 되어 총 n번 예측 테스트를 거치는 것이다. 그러면 각 테스트의 정확도가 나오는데 이 값이 높으면 높을수록 좋은 모델이다.
from sklearn.model_selection import KFold
kf = KFold(n_splits=6, shuffle=True, random_state=156)
교차검증을 위한 데이터 분할 함수로 KFold가 있다. train_test_split과 달리 데이터를 총 n개로 나눌 수 있고, 분할 작업을 도와주는 속성들도 많다. shuffle은 분할하기 전에 데이터를 섞을 건지 여부.
3) 분석모델 정의하기
의사결정나무 불러놓기. 아직 튜닝을 배우기 전이라서 수동으로 속성을 3개만 정의해 봤다.
from sklearn.tree import DecisionTreeClassifier
Dt_1 = DecisionTreeClassifier(max_depth=1, random_state=100)
Dt_3 = DecisionTreeClassifier(max_depth=3, random_state=100)
Dt_5 = DecisionTreeClassifier(max_depth=5, random_state=100)
4) 분석하기(1)
kfold와 의사결정나무를 이용해 분석하는 방법 첫번째는 일일이 n번 데이터를 쪼개서 함수에 넣고 정확도를 구하는 것이다.
split() 함수를 쓰면 인수 데이터에서 훈련용 데이터와 테스트 데이터의 index를 나눠준다. 이 index를 가지고 역으로 독립, 종속 데이터에서 구분해주어야 하기 때문에 처음부터 데이터를 np.array 형식으로 저장해 두면 훨씬 편하게 분석할 수 있다.
from sklearn.metrics import accuracy_score # 정확도 측정 함수
X = df_iris.drop(columns=['result']).values
Y = df_iris['result'].values
acc = []
for train_index, test_index in kf.split(X):
train_x, test_x = X[train_index], X[test_index]
train_y, test_y = Y[train_index], Y[test_index]
dt_1 = DecisionTreeClassifier(max_depth=1, random_state=100)
dt_1.fit(train_x, train_y)
pred = dt_1.predict(test_x)
acc.append(accuracy_score(test_y, pred))
print(np.mean(acc)) # 0.62 출력
두번째는 이런 코드 노가다를 안할 수 있는 좋은 함수를 쓰는 것이다.
cross_val_score 함수에 사용할 데이터와 분석모델, 회차(cv)를 넣으면 회차만큼 정확도를 구해준다.
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
X = df_iris.drop(columns=['result'])
Y = df_iris['result']
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=0, stratify=Y)
scores_5 = cross_val_score(Dt_5, x_train, y_train, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_5)
print('평균 정확도 : ', np.mean(scores_5))
scores_3 = cross_val_score(Dt_3, x_train, y_train, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_3)
print('평균 정확도 : ', np.mean(scores_3))
scores_1 = cross_val_score(Dt_1, x_train, y_train, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_1)
print('평균 정확도 : ', np.mean(scores_1))

첫번째 방법으로 한 것과 정확도는 비슷한 것 같다(Dt_1 참고). 정확도를 보니 max_depth가 3인 모델을 쓰면 될 것 같다.
그리고 첫번째 방법과 달리 전체 데이터에 train_test_split으로 훈련/ 검증 데이터를 나눠놓고 훈련 데이터로만 교차검증을 시행했다. 회귀분석 때 설명했던 것처럼 검증 데이터는 완전히 새로운 데이터여야 하기 때문!
(근데 다시 생각해보니 교차검증 때는 어차피 정확도만 추출하는 거고 정확도 가장 높은 모델로 다시 적합, 예측할 건데 굳이 그 전부터 나눠야 하나 싶기도 하다. 이건 두가지 경우를 모두 구해서 비교해봐야 알 것 같다??)
그래서 바로 비교해보기로 했다🤓
scores_5 = cross_val_score(Dt_5, X, Y, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_5)
print('평균 정확도 : ', np.mean(scores_5))
scores_3 = cross_val_score(Dt_3, X, Y, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_3)
print('평균 정확도 : ', np.mean(scores_3))
scores_1 = cross_val_score(Dt_1, X, Y, scoring='accuracy', cv=kf)
print('교차검증 정확도 : ', scores_1)
print('평균 정확도 : ', np.mean(scores_1))

위의 정확도와 비교해 보면 max_depth 1, 3인 값은 비슷한데 5인 모델은 조금 차이가 있다. 이렇게 보니까 전체 데이터를 교차검증 하는게 더 좋은 것 같기도 하다.
어쨌든, max_depth 5 모델이 제일 성능이 좋으니 그것으로 적합한 뒤 예측을 해보겠다.
Dt_5.fit(x_train, y_train)
y_pred = Dt_5.predict(x_test)
from sklearn.metrics import accuracy_score
acc = round(accuracy_score(y_test, y_pred), 3)
print(acc) # 0.967
정확도는 96.7%로 엄청 좋은 모델인 것을 알 수 있다.
'Daily' 카테고리의 다른 글
| 23.01.28 SVM 서포트 벡터 머신 (0) | 2023.01.29 |
|---|---|
| 23.01.28 Logistic Regression로지스틱 회귀 (0) | 2023.01.29 |
| 23.01.27 Lasso, Elasticnet 라쏘, 엘라스틱넷 (0) | 2023.01.28 |
| 23.01.25 Linear Regression, Ridge 경사하강법, 릿지 회귀 (0) | 2023.01.25 |
| 23.01.18 Regression 회귀분석 (0) | 2023.01.18 |