두 달 전쯤 처음 데이콘을 접하며 접근하기 쉬운 초급대회를 선정하여 내 수준을 알아보고, 복습도 할 겸 참여해봤다.
그저 아는 만큼만 하려니 어렵지 않았지만 결과는 형편없었다.
그 이후 전처리나 EDA에서 한 과정씩만 추가해보자 라는 다짐을 하게 되었다.
이전의 전처리나 EDA를 돌아보니 너무 대충한 느낌이 있었기 때문이고, 이 것이 결과와 직결되는 문제로 작용되었다.
물론, 한번 두번으로 다 안다는 착각을 하는 어리석은 자가 되기 싫었던 이유일까
매번 새로운 데이터를 볼 때마다 새로운 감상을 느낄 수 있었다.
목적 : 주어진 데이터를 활용하여 와인 품질을 분류하는 것.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
#경고 메시지 숨기기
import warnings
warnings.filterwarnings(action='ignore')
train = pd.read_csv('C:/Users/k1560/Desktop/와인품질분류/data/train.csv')
test = pd.read_csv('C:/Users/k1560/Desktop/와인품질분류/data/test.csv')
submission = pd.read_csv('C:/Users/k1560/Desktop/와인품질분류/data/sample_submission.csv')
# index 구분자
# quality 품질
# fixed acidity 산도
# volatile acidity 휘발성산
# citric acid 시트르산
# residual sugar 잔당 : 발효 후 와인 속에 남아있는 당분
# chlorides 염화물
# free sulfur dioxide 독립 이산화황
# total sulfur dioxide 총 이산화황
# density 밀도
# pH 수소이온농도
# sulphates 황산염
# alcohol 도수
# type 종류
print(train.shape, test.shape, submission.shape)
|
cs |
각각의 데이터셋의 shape을 찍어본 결과로 컬럼 개수와 데이터 개수를 확인한다.
1
2
|
train = train.drop(['index'], axis=1)
test = test.drop(['index'], axis=1)
|
cs |
우선 전처리에 필요하지 않은 구분자를 제거한다.
1
|
train.head()
|
cs |
train 데이터셋을 확인.
1
|
test.head()
|
cs |
test 데이터셋을 확인.
1
2
3
4
5
6
7
|
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
cols = ["fixed acidity","volatile acidity","citric acid","residual sugar","chlorides",
"free sulfur dioxide","total sulfur dioxide","density","pH","sulphates","alcohol"]
train[cols] = scaler.fit_transform(train[cols])
test[cols] = scaler.fit_transform(test[cols])
|
cs |
수치형 변수에 대해서 데이터들을 가우시안 정규분포(평균 : 0, 분산 : 1)로 조정해주는 StandardScaler를 사용.
1
2
|
train['type'] = train['type'].replace("white",0).replace("red",1)
test['type'] = test['type'].replace("white",0).replace("red",1)
|
cs |
범주형 변수는 0또는 1로 변환.
1
2
3
4
5
6
7
|
from scipy import stats
print("기존 왜도 :", train['free sulfur dioxide'].skew())
print("로그 변환 후 왜도 :", np.log(train['free sulfur dioxide']).skew())
print("루트 변환 후 왜도 :", np.sqrt(train['free sulfur dioxide']).skew())
# 박스-콕스 변환은 변수의 수치가 모두 양수여야함
|
cs |
1
2
3
|
기존 왜도 : 1.3106310382401294
로그 변환 후 왜도 : -0.9174079478635516
루트 변환 후 왜도 : 0.5138510308081303
|
cs |
변환해준 변수들에 대해서 왜도를 한번 확인해본다.
1
2
3
4
5
|
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(train.drop(['quality'], axis=1),
train['quality'], test_size=0.15, random_state=2022)
print(X_tr.shape, X_val.shape, y_tr.shape, y_val.shape)
|
cs |
모델 학습을 위해 train_test_split으로 데이터를 분리해준다.
1
2
3
4
5
6
7
8
|
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
rf_clf = RandomForestClassifier(random_state=2022)
rf_clf.fit(X_tr, y_tr)
pred = rf_clf.predict(X_val)
accuracy = accuracy_score(y_val, pred)
print('랜덤 포레스트 정확도: {:.4f}'.format(accuracy))
|
cs |
1
|
랜덤 포레스트 정확도: 0.6897
|
cs |
모델은 RandomForesetClassifier를 사용했고, 정확도로 성능을 검증하였다.
정확도는 약 0.69로 그저 그런 정확도였다.
1
2
|
train_x = train.drop(['quality'], axis = 1)
train_y = train['quality']
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from sklearn.model_selection import GridSearchCV
params = { 'n_estimators' : [10, 100, 200],
'max_depth' : [6, 8, 10, 12],
'min_samples_leaf' : [8, 12, 18],
'min_samples_split' : [8, 16, 20]
}
# RandomForestClassifier 객체 생성 후 GridSearchCV 수행
rf_clf = RandomForestClassifier(random_state = 2022)
grid_cv = GridSearchCV(rf_clf, param_grid = params, cv = 3)
grid_cv.fit(train_x, train_y)
print('최적 하이퍼 파라미터: ', grid_cv.best_params_)
print('최고 예측 정확도: {:.4f}'.format(grid_cv.best_score_))
|
cs |
좀 더 좋은 모델을 만들기 위해 하이퍼파라미터를 조정해서 만들어보기로 했다.
GridSearchCV를 활용해서 최적의 하이퍼 파라미터를 찾는 과정을 거친다.
1
2
|
최적 하이퍼 파라미터: {'max_depth': 12, 'min_samples_leaf': 8, 'min_samples_split': 8, 'n_estimators': 200}
최고 예측 정확도: 0.6027
|
cs |
하지만 하이퍼파라미터를 조정하지 않았을 때 보다 낮은 정확도를 가져온다.
그럼에도 train데이터셋으로 학습한 것이니 기대를 걸어본다.
1
2
3
4
|
rf_clf = RandomForestClassifier(random_state=2022, max_depth= 12, min_samples_leaf = 8,
min_samples_split = 8, n_estimators = 200)
rf_clf.fit(train_x, train_y)
y_pred = rf_clf.predict(test)
|
cs |
최적의 하이퍼파라미터를 가지고 다시 학습을 시키고, 예측된 값을 가져온다.
1
2
|
submission['quality'] = y_pred
submission.to_csv('pymoon_wine.csv', index=False)
|
cs |
데이콘에서 제공해주는 제출용 파일에 예측값을 넣고는 저장해서 제출한다.
'내가 하는 데이터분석 > 내가 하는 정형 분류' 카테고리의 다른 글
[DACON] - 타이타닉 생존 예측(분류) with Python (0) | 2022.12.31 |
---|