[ML] Decision Tree를 이용한 와인 데이터 분석

TaeHwi Kang·2022년 12월 20일
0

1. 와인 데이터 받아오기

1) 데이터 받아오기

# 레드 와인 데이터 받아오기 
import pandas as pd

red_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/winequality-red.csv'

red_wine = pd.read_csv(red_url, sep= ';')


# 화이트 와인 데이터 받아오기
white_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/winequality-white.csv'

white_wine = pd.read_csv(white_url, sep= ';')

2) column 설명

  • fixed acidity : 고정 산도
  • volatile acidity : 휘발성 산도
  • citric acid : 시트르산
  • residual sugar : 잔류 당분
  • chlorides : 염화물
  • free sulfur dioxide : 자유 이산화황
  • total sulfur dioxide : 총 이산화황
  • density : 밀도
  • pH
  • sulphates : 황산염
  • alcohol : 도수
  • quality : 0 ~ 10 (높을수록 좋은 품질)
# 레드 와인 : 1.0, 화이트 와인 : 0.0 으로 컬럼을 추가하여 합치기
red_wine['color'] = 1.
white_wine['color'] = 0.

wine = pd.concat([red_wine, white_wine])
# quality의 각 갯수 파악하기
wine['quality'].unique(), wine['quality'].value_counts()

# 
(array([5, 6, 7, 4, 8, 3, 9], dtype=int64),
 6    2836
 5    2138
 7    1079
 4     216
 8     193
 3      30
 9       5
 Name: quality, dtype: int64)

3) 데이터 확인

# quality분포를 histogram으로 그리기
import plotly_express as px

fig = px.histogram(wine, x='quality')
fig.show()
# 레드/화이트 와인별로 quality분포 Histogram
fig = px.histogram(wine, x='quality', color= 'color')
fig.show()

2. 레드 와인 / 화이트 와인 분류기 만들기

1) Decision Tree

# 라벨 분리
X = wine.drop(['color'], axis=1)
y = wine['color']

# 데이터를 훈련용과 테스트용 데이터로 나누기
from sklearn.model_selection import train_test_split
import numpy as np

X_train,X_test,y_train,y_test = train_test_split(X,y, test_size=0.2, random_state=13)
# 훈련용과 테스트용 데이터가 레드/화이트 와인에 따라 어느정도 구분되었는지 확인
import plotly.graph_objects as go

fig = go.Figure()
fig.add_trace(go.Histogram(x=X_train['quality'], name='Train'))
fig.add_trace(go.Histogram(x=X_test['quality'], name='Test'))

fig.update_layout(barmode = 'overlay')
fig.update_traces(opacity = 0.7)

fig.show()

# 결정나무 훈련
from sklearn.tree import DecisionTreeClassifier

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

# 학습 결과
from sklearn.metrics import accuracy_score

y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)

print('Train Acc : ', accuracy_score(y_train, y_pred_tr))
print('Test Acc : ',accuracy_score(y_test, y_pred_test))

# Train Acc : 0.9553588608812776
# Test Acc : 0.9569230769230769**

3. 데이터 전처리

1) 데이터 확인

# 와인 데이터의 몇개의 항목의 Boxplot 그려보자
fig = go.Figure()

fig.add_trace(go.Box(y=X['fixed acidity'], name= 'fixed acidity'))
fig.add_trace(go.Box(y=X['chlorides'], name='chlorides'))
fig.add_trace(go.Box(y=X['quality'], name='quality'))

fig.show()

  • 컬럼들의 최대/최소 범위가 각각 다르고, 평균과 분산이 각각 다르다.
  • 특성(feature)의 편향 문제는 최적의 모델을 찾는데 방해가 될 수도 있다.
    -> 이럴 때 쓰는 것이 MinMaxScaler와 StandardScaler
# MinMaxScaler, StandardScaler 적용
from sklearn.preprocessing import MinMaxScaler, StandardScaler

MMS = MinMaxScaler()
SS = StandardScaler()

MMS.fit(X)
SS.fit(X)

X_mms = MMS.transform(X)
X_ss = SS.transform(X)

X_mms_pd = pd.DataFrame(X_mms, columns=X.columns)
X_ss_pd = pd.DataFrame(X_ss, columns=X.columns)

- 결정나무에서는 이런 전처리는 의미를 가지지 않는다.
- 주로 Cost Function을 최적화할 때 유효할 때가 있다.
- MinMaxScaler와 StandardScaler 중 어떤 것이 좋을지는 해봐야 안다.

2) MinMaxScaler

  • 최대, 최소값을 1과 0으로 맞추는 것

(1) MinMaxScaler 적용된 데이터 확인

fig = go.Figure()

fig.add_trace(go.Box(y=X_mms_pd['fixed acidity'], name= 'fixed acidity'))
fig.add_trace(go.Box(y=X_mms_pd['chlorides'], name='chlorides'))
fig.add_trace(go.Box(y=X_mms_pd['quality'], name='quality'))

fig.show()

(2) MinMaxScaler를 적용해서 다시 학습

X_train,X_test,y_train,y_test = train_test_split(X_mms_pd,y,test_size=0.2,random_state=13)

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)

print('train Acc : ',accuracy_score(y_train, y_pred_tr))
print('test Acc : ',accuracy_score(y_test, y_pred_test))

# train Acc :  0.9553588608812776
# test Acc :  0.9569230769230769

3) StandardScaler

  • 평균을 0으로 표준편차를 1로 맞추는 것

(1) MinMaxScaler 적용된 데이터 확인

fig = go.Figure()

fig.add_trace(go.Box(y=X_ss_pd['fixed acidity'], name= 'fixed acidity'))
fig.add_trace(go.Box(y=X_ss_pd['chlorides'], name='chlorides'))
fig.add_trace(go.Box(y=X_ss_pd['quality'], name='quality'))

fig.show()

(2) StandardScaler를 적용해서 다시 학습

X_train,X_test,y_train,y_test = train_test_split(X_ss_pd,y,test_size=0.2,random_state=13)

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)

print('train Acc : ',accuracy_score(y_train, y_pred_tr))
print('test Acc : ',accuracy_score(y_test, y_pred_test))

#train Acc :  0.9553588608812776
#test Acc :  0.9569230769230769

4) 레드와인과 화이트와인을 구분하는 중요 특성확인

dict(zip(X_train.columns, wine_tree.feature_importances_))

# total sulfur dioxide( 총 이산화황) 중요한 역활을 하는것으로 보인다.
# MaxDepth를 높이면 수치에도 변화가 온다.

{'fixed acidity': 0.0,
 'volatile acidity': 0.0,
 'citric acid': 0.0,
 'residual sugar': 0.0,
 'chlorides': 0.24230360549660776,
 'free sulfur dioxide': 0.0,
 'total sulfur dioxide': 0.7576963945033922,
 'density': 0.0,
 'pH': 0.0,
 'sulphates': 0.0,
 'alcohol': 0.0,
 'quality': 0.0}

4. 와인 맛에 대한 분류 - 이진 분류

1) quality 컬럼을 이진화

wine['taste'] = [1. if grade > 5 else 0. for grade in wine['quality']]
# quality 컬럼으로 taste 컬럼을 만들었으니 quality 컬럼도 같이 제거
X = wine.drop(['taste', 'quality'], axis=1)
y = wine['taste']

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=13)

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)

y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)

print('train Acc : ',accuracy_score(y_train, y_pred_tr))
print('test Acc : ',accuracy_score(y_test, y_pred_test))

# train Acc :  0.7294593034442948
# test Acc :  0.7161538461538461

2) 어떤 와인을 “맛있다”고 할 수 있나?

plt.figure(figsize=(12,8))
tree.plot_tree(
    wine_tree,
    feature_names=X.columns,
    rounded=True,
    filled=True
              );

profile
스터디 노트

0개의 댓글