[ML] Encoder and Scaler, Wine using DT

svenskpotatis·2023년 11월 2일

Encoder add Scaler

label_encoder

  • label encoder: 글자 -> 숫자
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
df = pd.DataFrame({'A': ['a', 'b', 'c', 'a', 'b'], 
                    'B': [1, 2, 3, 1, 0]                   
})
le.fit(df['A'])
# 방금 fit 시킨 변수 확인
le.classes_

--> array([0, 1, 2, 0, 1])


df['le_A'] = le.transform(df['A'])
le.fit_transform(df['A'])

--> array([0, 1, 2, 0, 1])


le.transform(['a'])

--> array([0])


le.inverse_transform(df['le_A'])

--> array(['a', 'b', 'c', 'a', 'b'], dtype=object)

min-max scaling

df = pd.DataFrame({
    'A': [10, 20, -10, 0, 25],
    'B': [1, 2, 3, 1, 0]
})
from sklearn.preprocessing import MinMaxScaler

mms = MinMaxScaler()
mms.fit(df)
mms.data_max_, mms.data_min_, mms.data_range_

--> (array([25., 3.]), array([-10., 0.]), array([35., 3.]))


df_mms = mms.transform(df)
df_mms
--> 
array( [[0.57142857, 0.33333333],
       [0.85714286, 0.66666667],
       [0.        , 1.        ],
       [0.28571429, 0.33333333],
       [1.        , 0.        ]])

# 역변환
mms.inverse_transform(df_mms)
array([[ 10.,   1.],
       [ 20.,   2.],
       [-10.,   3.],
       [  0.,   1.],
       [ 25.,   0.]])

Standard Scaler

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
ss.fit(df)
ss.mean_, ss.scale_  

--> (array([9. , 1.4]), array([12.80624847, 1.0198039 ]))

# transform

df_ss = ss.transform(df)
ss.fit_transform(df)

Robust Scaler

df = pd.DataFrame({
    'A': [0.1, 0., 0.1, 0.2, 0.3, 0.4, 1.0, 1.1, 5.0]
})

df
from sklearn.preprocessing import RobustScaler

mm = MinMaxScaler()
ss = StandardScaler()
rs = RobustScaler()
df_scaler = df.copy()

df_scaler['MinMax'] = mm.fit_transform(df)
df_scaler['Standard'] = ss.fit_transform(df)
df_scaler['Robust'] = rs.fit_transform(df)

boxplot

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style='whitegrid')

plt.figure(figsize=(16, 6))
sns.boxplot(data=df_scaler, orient='h');
  • minmax, standard scaler는 outlier에 영향 많이 받음
  • robust scaler: outlier에 영향 적게 받음

Wine using DT

px.histogram

import plotly.express as px

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

  • red/white 와인별로 등급 histogram
import plotly.express as px

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

red / white wine 분류기

X = wine.drop(['color'], axis=1)  # feature
y = wine['color']  # label

train / test split

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)
np.unique(y_train, return_counts=True)

--> (array([0, 1]), array([3913, 1284]))
대충 3900개 : 1300개로 분리됨

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

  • DT 훈련
from sklearn.tree import DecisionTreeClassifier

wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)
# accuracy 확인
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


accuracy_score(y_train, y_pred_tr)  # (참값, 예측값)

--> 0.9553588608812776


accuracy_score(y_test, y_pred_test)

--> 0.9569230769230769

데이터 전처리

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

from sklearn.preprocessing import MinMaxScaler, StandardScaler

MMS = MinMaxScaler()
SS = StandardScaler()

SS.fit(X)
MMS.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)
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()


--> MinMaxScaler: 최대 최소값을 1과 0으로 강제로 맞춤


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)

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

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.2423036054966077,
 'free sulfur dioxide': 0.0,
 'total sulfur dioxide': 0.7576963945033923,
 'density': 0.0,
 'pH': 0.0,
 'sulphates': 0.0,
 'alcohol': 0.0,
 'quality': 0.0}

  • max_depth 바꿔봄
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=4, random_state=13)
wine_tree.fit(X_train, y_train)

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

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

-->
{'fixed acidity': 0.0,
 'volatile acidity': 0.05294226193535861,
 'citric acid': 0.0,
 'residual sugar': 0.0,
 'chlorides': 0.21810457553750037,
 'free sulfur dioxide': 0.0,
 'total sulfur dioxide': 0.7142978906861245,
 'density': 0.0030924765614972747,
 'pH': 0.0,
 'sulphates': 0.01156279527951925,
 'alcohol': 0.0,
 'quality': 0.0}

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

# 5등급보다 크면 1
wine['taste'] = [1. if grade>5 else 0. for grade in wine['quality']]
wine.head()
  • DT
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=4, 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))

--> 100 % 나옴, why?


import sklearn.tree as tree

plt.figure(figsize=(12, 8))
tree.plot_tree(wine_tree, feature_names=X.columns.tolist())
plt.show()

  • quality 를 기준으로 정했기 때문
  • quality 도 drop
# quality 도 drop
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

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

0개의 댓글