본문 바로가기
내가 하는 데이터분석/내가 하는 정형 분류

[DACON] - 와인 품질 분류(분류) with Python

by Pymoon 2022. 12. 16.

두 달 전쯤 처음 데이콘을 접하며 접근하기 쉬운 초급대회를 선정하여 내 수준을 알아보고, 복습도 할 겸 참여해봤다. 

그저 아는 만큼만 하려니 어렵지 않았지만 결과는 형편없었다.

 

그 이후 전처리나 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' : [10100200],
           'max_depth' : [681012],
           'min_samples_leaf' : [81218],
           'min_samples_split' : [81620]
            }
 
# 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

 

데이콘에서 제공해주는 제출용 파일에 예측값을 넣고는 저장해서 제출한다.