Wine 데이터를 Scaling 하고 레드 와인과 화이트 와인으로 구별해보자!!
Scaler란?
동일한 범위 내로 데이터를 만들기 위해 사용하는 방법입니다.
종류
1. min-max scaler
- 최소 0 최대 1 이내의 범위에 데이터를 위치 시키는 방법이다.
2. standard scaler
- 각각의 데이터들이 평균이 0, 표준편차가 1이 되도록 만드는 방법이다.
등등...
TIP
데이터 분석을 할 때 중요 특성에 대해서 알고있어야한다. 해당 중요 특성이 그래프나 분석할 때 영향을 많이 주기 때문이다.
그래서 사용하는 함수인 feature_importances_ 함수를 사용하면 됩니다.
이제 본격적으로 Wine Data를 활용하여 Scaling을 하고 레드와인과 화이트 와인을 구별해보겠습니다.
1.우선 데이터를 받아오겠습니다.
import pandas as pd
red_url = 'https://raw.githubusercontent.com/PinkWink/forML_study_data/refs/heads/main/data/winequality-red.csv'
white_url = 'https://raw.githubusercontent.com/PinkWink/forML_study_data/refs/heads/main/data/winequality-white.csv'
red_wine = pd.read_csv(red_url, sep=';')
white_wine = pd.read_csv(white_url, sep=';')
red_wine.head()
이번에는 다른 블로그 글들과는 달리 url을 통해서 csv파일을 가져왔습니다.
원본 파일마다 ' '이 아닌 ';(세미콜론)'으로 구별 되어 있기 때문에 sep=';'을 사용하여 세미콜론을 기준으로 나눠줬습니다.
2. 해당 데이터들을 합치기 전에 해당 데이터가 red와인인지 white와인인지를 구별해주기 위해 color라는 컬럼을 만들고 구별해주겠습니다.
red_wine['color'] = 1
white_wine['color'] = 0
이렇게 red와인은 1로 white와인은 0으로 표현 해주었습니다.(이렇게 보니 이진 분류라는 것을 알 수 있습니다.)
3. 두 개의 데이터를 합쳐 주겠습니다.
wine = pd.concat([red_wine, white_wine])
wine.info()
4. quality 컬럼의 값을 확인 해보니 3~8로만 구성되어있는 것을 확인 할 수 있었습니다. 이제 이 quality가 어떻게 분포되어있는지 확인해보겠습니다.
import plotly.express as px
fig = px.histogram(wine, x='quality')
fig.show()
보아하니 3과 9 정도의 퀄리티를 가진 와인은 매우 적게 분포하고 있으며 중간 정도의 퀄리티를 가진 와인들이 많이 분포하는 것 같습니다.
5. 여기서 저희는 레드와인과 화이트를 구별하여 어떻게 분포되어있는지를 봐보겠습니다.
fig = px.histogram(wine, x='quality', color='color')
fig.show()
보아하니 화이트 와인의 개수가 매우 많은 것으로 확인이 됩니다.(화이트 와인의 데이터가 좀 더 많았던 것 같습니다.)
그리고 레드 와인과 화이트 와인이 비슷하게 분포되어있는 것 같습니다.
6. 이번에는 훈련세트와 테스트 세트를 나누어 주는 작업을 하겠습니다.
from sklearn.model_selection import train_test_split
import numpy as np
import plotly.graph_objects as go
X = wine.drop(['color'], axis=1) # 특성, color는 해당 특성에 대한 답이니 빼주겠습니다.
y = wine['color'] # Label
# 테스트 세트와 훈련 세트로 나누어 주는 작업
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=13)
# 테스트 세트와 훈련 세트가 동일하게 나누어졌는지 확인
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()
위의 사진과 같이 데이터를 훈련 세트와 테스트 세트로 나누어 주고 분포에 대한 그래프를 확인해본 결과 두 그래프의 모양이 거의 똑같은 형태를 가지고 있는 것으로 보아 잘 나눠진 것 같습니다.
7. 이제 특정 컬럼들을 가져와 데이터들이 어느 정도 범위에 있는지 박스플롯을 통해 확인해 보겠습니다.
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'))
확실히 컬럼들 마다 동일한 범위가 아닌 넓은 범위에서 일정하지 않게 분포하는 것을 확인 할 수 있습니다.
이러는 경우 생기는 문제
큰 값이 더 큰 영향력을 미칩니다. 특성 값들이 서로 다른 범위를 가지면, 값이 큰 특성들이 모델의 예측에 더 큰 영향을 줍니다.
그래서 결국 모델 해석에 어려움을 끼치게 됩니다.
해결 방법
위에서 얘기했던 Scaling 방법을 사용하면 됩니다.
8. min-max Scaler와 StandardScaler를 사용해보겠습니다.
from sklearn.preprocessing import MinMaxScaler, StandardScaler
MMS = MinMaxScaler() # max, min
SS = StandardScaler()
SS.fit(X)
MMS.fit(X) # 뭐가 max이고 min인지 찾는 것.
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)
# Box plot 그려보기
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()
이렇게 스케일러를 통해 데이터들을 특정 범위내로 만들어주었습니다. 그래프를 확인 해보겠습니다.
min - max Scaler 답게 그래프의 범위가 0 ~ 1 사이에서 분포하는 것을 확인 할 수 있습니다.
9. 이제 스케일링을 한 데이터를 통해 정확도를 확인해보겠습니다.
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)
accuracy_score(y_train, y_pred_tr), accuracy_score(y_test, y_pred_test)
결과 : (0.9553588608812776, 0.9569230769230769) 정확도가 스케일링을 했을 때와 안했을 때의 차이는 별로 안난 것으로 확인되었습니다.
10. 이번에는 해당 데이터에서 중요한 특성이 무엇인지 찾아보겠습니다. (tree를 이용하여 확인 해보겠습니다.)
import matplotlib.pyplot as plt
from sklearn import tree
fig = plt.figure(figsize=(12, 8))
_ = tree.plot_tree(wine_tree, feature_names=list(X_train.columns), class_names=['W', 'R'], rounded=True, filled=True)
보아하니 'total sulfur dioxide'(총 이산화 황)와 chlorides 두 개의 특성을 통해 레드 와인과 화이트 와인을 구별하는 것 같습니다.
이를 확인하기 위해 위에서 말했던 함수를 사용해 보겠습니다.
11. 중요 특성 확인
# DecisionTreeClassifier의 max_depth가 일종의 hyperparameter이다. 즉, hyperparameter를 조정할 때마다 모델이 바뀐다 생각하면 된다.
dict(zip(X_train.columns, wine_tree.feature_importances_))
{'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}
zip을 통해 서로에 맞게 묶어서 표현 하였습니다. 확실히 위에서 말한 두 특성이 수치가 높은 것으로 보아 해당 특성들이 중요하다는 것을 확인 할 수 있습니다.
하지만 여기서 알아야 할 것은 제가 max_depth를 2로 설정하여 좀 더 깊숙히 까지 확인을 하지 않아 이러한 결과가 나온 것일수도 있으니 너무 믿으면 안됩니다.
12. 이번에는 taste라는 컬럼을 이용하여 맛있는지 맛없는지를 구별하는 데이터를 만들고 훈련 시켜보겠습니다.
# quality를 기준으로 잘랐음. 그러므로 무조건 100%로 나오게 되어있음.(그 이유는 내가 정해준 기준으로 훈련시켰기 때문이다.)
# 그러면 해결 방법으로는 quality를 빼고 훈련을 시켜야 한다.
wine['taste'] = [1. if grade >5 else 0. for grade in wine['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.fit(X_train, y_train)
y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)
# 정확도 검사
accuracy_score(y_train, y_pred_tr), accuracy_score(y_test, y_pred_test)
저희는 맛을 구별하기 위해 quality의 값이 5보다 크면 맛있다(1) 그리고 작다면 맛없다(0)로 설정하였습니다.
그럼 여기서 데이터를 X, y로 구별하는데 여기서 taste만 빼고 훈련을 시킨다면 머신러닝은 저희가 quality를 기준으로 자른 것을 확인하고 quality를 통해 나누게 됩니다. 그렇게 되면 정확도는 (1, 1)이 나올 것이고 저희가 훈련시키는 의미가 없기에 quality 또한 빼고 측정하였습니다.
결과 (0.7294593034442948, 0.7161538461538461) 이러한 수치의 정확도가 나왔습니다. 그래도 quality 없이 구별을 했다는 것을 확인 하였습니다.
13. 이번에도 트리를 통해 어떤 특성이 영향을 주는지 확인 해보겠습니다.
여기에서 alcohol, free sulfur dioxide, volatile acidity 들의 특성들이 맛에 영향이 있다는 것으로 나왔습니다.
실제 와인이 해당 특성들에 의해 맛이 결정되는 것은 모릅니다!! 이거는 따로 알아봐야 하는 내용인 것 같습니다.
네 이상으로 와인 구별하는 내용을 마치겠습니다.
이 글은 제로베이스 데이터 분석 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.
'Data Analyst > ML' 카테고리의 다른 글
[Zero-base] Pipeline (0) | 2024.10.03 |
---|---|
[Zero-base] Scaling & 분류 모델 평가 (1) | 2024.10.03 |
[Zero-base]Linear Regression 2(보스턴 집 값 예측) (0) | 2024.09.30 |
[Zero-base]Linear Regression (0) | 2024.09.30 |
[Zero-Base] Machine Learning - 1 (0) | 2024.09.27 |