머신 러닝 - 와인 데이터 분석

◾와인 데이터 분석

1. 와인 데이터 개요

  • Wine : 분류 문제에서 Iris 꽃 데이터만큼 알려지진 않았지만 많이 사요오딘다.
    • 인류 역사상 최초의 술로 알려져있다.
    • 기원전 7000년 무렵 조지아-아르메이나-터키 동북부(코카서스)에서 흔적 발견
    • 플라톤 : '신이 인간에게 내려준 선물 중 포도주만큼 위대한 가치를 지닌 것은 없다.'
    • 와인 맛 분류 : 링크
    • 데이터 : 링크
      • 레드 와인 품질 데이터(다운로드) : 링크
      • 화이트 와인 품질 데이터(다운로드) : 링크
# 데이터 읽기
import pandas as pd

red_wine = pd.read_csv('winequality-red.csv', sep=';')
white_wine = pd.read_csv('winequality-white.csv', sep=';')
  • 두 데이터의 구조는 동일함을 확인
  • 컬럼의 종류
    • fixed acidity : 고정 산도
    • volatile acidity : 휘발성 산도
    • citric acid : 시트르산
    • residual sugar : 잔류 당분
    • chlorides : 염화물
    • free sulfur dioxide : 자유 이산화황
    • total sulfur dioxide : 총 이산화황
    • density : 밀도
    • pH
    • sulphates : 황산염
    • alcohol
    • quality : 0 ~ 10(높을 수록 좋은 품질)
# 레드 와인/화이트 와인 데이터 연결
# color 컬럼 추가하여 구분
red_wine['color'] = 1.
white_wine['color'] = 0.

wine = pd.concat([red_wine, white_wine])
wine.reset_index(drop=True, inplace=True)
wine.info()

# 내용 확인
wine['quality'].unique()

wine['quality'].value_counts()

# quality 히스토그램
import plotly.express as px

fig = px.histogram(wine, x='quality')
fig.show()

  • 화이트 와인의 수가 많은을 확인
  • 레드 와인은 등급이 조금 작은 것을 확인
# 레드/화이트 와인별 등급 Histogram
fig = px.histogram(wine, x='quality', color='color')
fig.show()

2. 레드와인, 화이트 와인 분류

  • 레드 와인인지 화이트 와인인지 맞추기
# 라벨 분리
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)
# y값 확인
np.unique(y_train, return_counts=True)

# 훈련용과 테스트용이 레드/화이트에 따라 어느정도 구분되었는지 확인
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.75)
fig.show()

  • 정확성 측면에서 훈련값과 테스트값이 비슷하다.
# 결정 나무 훈련
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

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)

  • (total sulfur dioxide : 총 이산화황)를 중요하게 판단한다.
  • chlorides : 염화물
# decision tree 그래프
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree

plt.figure(figsize=(12, 8))
plot_tree(wine_tree)
plt.show()

3. 데이터 전처리

# 와인 데이터의 몇 개 항목의 Boxplot 그리기
# 컬럼값의 차이가 심하면 훈련이 제대로 이루어지지 않을 수 있다.
# Scaler를 통해 정리할 수 있다.
#   => 결정 나무에서는 이런 전처리는 의미를 가지지 않는다.
#   => 주로 Cost Function을 최적화할 때 유효하다
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()

# MinMaxScaler, StandardScaler
from sklearn.preprocessing import MinMaxScaler, StandardScaler

MMS = MinMaxScaler()
SS = StandardScaler()

MMS.fit(x)
SS.fit(x)

x_ss = SS.transform(x)
x_mms = MMS.transform(x)

x_ss_pd = pd.DataFrame(x_ss, columns=x.columns)
x_mms_pd = pd.DataFrame(x_mms, columns=x.columns)
# x_mms_pd
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()

# x_ss_pd
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()

  • MinMaxScaler를 이용한 학습
  • 결정나무에는 거의 효과가 없다.
# 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 : {}'.format(accuracy_score(y_train, y_pred_tr)))
print('Train Acc : {}'.format(accuracy_score(y_test, y_pred_test)))

  • StandardScaler를 이용한 학습
  • 결정나무에는 거의 효과가 없다.
# 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 : {}'.format(accuracy_score(y_train, y_pred_tr)))
print('Train Acc : {}'.format(accuracy_score(y_test, y_pred_test)))

  • max_depth를 높이면 수치가 변한다.
# 레드 와인과 화이트 와인을 구분하는 중요 특성
dict(zip(x_train.columns, wine_tree.feature_importances_))

4. 맛의 이진 분류

  • quality 컬럼 이진화
    • 5 이상 : 1(맛있다)
    • 5 미만 : 0(맛있지 않다)
# taste 컬럼 추가
wine['taste'] = [1. if grade > 5 else 0. for grade in wine['quality']]
wine.info()

# 레드/화이트 와인 분류와 동일하게 진행
X = wine.drop(['taste'], 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)
# 훈련 데이터 fit
wine_tree.fit(X_train, y_train)
  • 정확성이 1이 나온다.
  • 왜 1이 나왔을까??
    • quality 컬럼을 사용하여 100%로 구분하였다.
    • quality 컬럼을 사용하여 taste 컬럼을 만들었는데 quality 컬럼을 지우지 않아 정확성이 100%로 나오게 되었다.
    • taste를 만드는데 사용한 quality도 제거한 뒤 수행해야한다.
# 정확성 확인
y_pred_tr = wine_tree.predict(X_train)
y_pred_Test = wine_tree.predict(X_test)

print('Train Acc : {}'.format(accuracy_score(y_train, y_pred_tr)))
print('Test Acc : {}'.format(accuracy_score(y_test, y_pred_Test)))

# Decision Tree 확인
plt.figure(figsize=(12, 8))
plot_tree(wine_tree, feature_names=X.columns)
plt.show()

  • 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)

# 훈련 데이터 fit
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 : {}'.format(accuracy_score(y_train, y_pred_tr)))
print('Test Acc : {}'.format(accuracy_score(y_test, y_pred_Test)))

  • alcohol과 volatile acidity, free sulfur dioxide 컬럼을 사용하였다.
  • alcohol이 높으면 맛잇는 것일까?
# Decision Tree
plt.figure(figsize=(12, 8))
plot_tree(wine_tree, feature_names=X.columns)
plt.show()

좋은 웹페이지 즐겨찾기