경고 메시지 출력 표기 생략

from IPython.display import Image
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings

warnings.filterwarnings('ignore')

# unicode 에러
plt.rcParams['axes.unicode_minus'] = False

표준화 (Standardization)

표준화는 데이터의 평균을 0 분산 및 표준편차를 1로 만들어 줍니다.

표준화를 하는 이유

  • 서로 다른 통계 데이터들을 비교하기 용이하기 때문입니다.
  • 표준화를 하면 평균은 0, 분산과 표준편차는 1로 만들어 데이터의 분포를 단순화 시키고, 비교를 용이하게 합니다.

표준화 공식

\(\Large z = \frac{(X - \mu)}{\sigma}\)

샘플데이터

iris 붓꽃 샘플데이터를 가져옵니다.

from sklearn.datasets import load_iris
  • iris 데이터를 가져와 iris 변수에 대입합니다.
# 코드를 입력해 주세요
iris = 

iris 데이터를 활용하여 DataFrame을 생성해 주세요

# 코드를 입력해 주세요
df = 

df.head()

[출력 결과]

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) target
0 5.1 3.5 1.4 0.2 0
1 4.9 3.0 1.4 0.2 0
2 4.7 3.2 1.3 0.2 0
3 4.6 3.1 1.5 0.2 0
4 5.0 3.6 1.4 0.2 0

4개의 feature 데이터 중 sepal length (cm)의 feature만 임의로 선택하여 X 변수에 저장합니다.

sepal length (cm) 컬럼만 X 변수에 저장

# 코드를 입력해 주세요
X = 

표준화 코드 구현

표준화를 Python으로 직접 구현하면 다음과 같습니다. 공식을 그대로 코드로 옮기면 됩니다.

  • X_ 변수에 바로 위에서 만든 X 변수를 표준화를 거친 후 결과를 담습니다.

\(\Large z = \frac{(X - \mu)}{\sigma}\)

# 코드를 입력해 주세요
X_ = 

시각화

시각화로 표준화의 전과 후를 비교합니다.

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.distplot(X, bins=5, color='b')
plt.title('Original', fontsize=16)

plt.subplot(1, 2, 2)
sns.distplot(X_, bins=5, color='r')
plt.title('Standardization', fontsize=16)
plt.show()

iris 붓꽃 데이터 분포 시각화

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(df['sepal length (cm)'], df['sepal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Sepal', fontsize=16)

plt.subplot(1, 2, 2)
sns.scatterplot(df['petal length (cm)'], df['petal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Petal', fontsize=16)
plt.show()

StandardScaler의 활용

sklearn.preprocesssingStandardScaler로 표준화 (Standardization) 할 수 있습니다.

from sklearn.preprocessing import StandardScaler
# 코드를 입력해 주세요
scaler = 

feature 데이터를 표준화 합니다. (표준화 할 때는 Y 값은 제외합니다.)

# 코드를 입력해 주세요
scaled_data = 
scaled_data[:5]
# 코드검증
round(scaled_data.mean(), 2), scaled_data.std()

[출력 결과]

(-0.0, 1.0)

Scale 전, 후 비교 (시각화)

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(df['sepal length (cm)'], df['sepal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Sepal (Original)', fontsize=16)

plt.subplot(1, 2, 2)
sns.scatterplot(scaled_data[:, 0], scaled_data[:, 1], hue=df['target'], palette='Set1')
plt.title('Sepal (Scaled)', fontsize=16)
plt.show()
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(df['petal length (cm)'], df['petal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Petal (Original)', fontsize=16)

plt.subplot(1, 2, 2)
sns.scatterplot(scaled_data[:, 2], scaled_data[:, 3], hue=df['target'], palette='Set1')
plt.title('Petal (Scaled)', fontsize=16)
plt.show()

정규화 (Normalization)

정규화 (Normalization)도 표준화와 마찬가지로 데이터의 스케일을 조정합니다.

정규화가 표준화와 다른 가장 큰 특징은 모든 데이터가 0 ~ 1 사이의 값을 가집니다.

즉, 최대값은 1, 최소값은 0으로 데이터의 범위를 조정합니다.

정규화 코드 구현

sepal length (cm) 컬럼만 X 변수에 저장

# 코드를 입력해 주세요
X = 

정규화 공식

Image(url='https://mblogthumb-phinf.pstatic.net/MjAxODA3MzFfMjgx/MDAxNTMzMDIxNzg5MTkz.odx32KoGhDrjwJHgjb_NslL1Nlmsp4veLz6OULb2q00g.5Ynl7GOds1YAgBgJ_TSiuWjHZfrNWPq3hsHtwCjvNP0g.PNG.angryking/image_4532734831533021765958.png?type=w800', width=200)

정규화 코드 구현합니다.

# 코드를 입력해 주세요
X_ = 

시각화

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.distplot(X, bins=5, color='b')
plt.title('Original', fontsize=16)

plt.subplot(1, 2, 2)
sns.distplot(X_, bins=5, color='r')
plt.title('Normalization', fontsize=16)
plt.show()

MinMaxScaler의 활용

from sklearn.preprocessing import MinMaxScaler
# 코드를 입력해 주세요
minmax_scaler =
  • feature 4개를 모두 변환합니다.
  • 변환된 결과는 scaled_data2에 대입합니다.
# 코드를 입력해 주세요
scaled_data2 = 
scaled_data2[:5]
# 코드검증
scaled_data2.min(), scaled_data2.max()

[출력 결과]

(0.0, 1.0)

Scale 전, 후 비교 (시각화)

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(df['sepal length (cm)'], df['sepal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Sepal (Original)', fontsize=16)

plt.subplot(1, 2, 2)
sns.scatterplot(scaled_data2[:, 0], scaled_data2[:, 1], hue=df['target'], palette='Set1')
plt.title('Sepal (Scaled)', fontsize=16)
plt.show()
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(df['petal length (cm)'], df['petal width (cm)'], hue=df['target'], palette='Set1')
plt.title('Petal (Original)', fontsize=16)

plt.subplot(1, 2, 2)
sns.scatterplot(scaled_data2[:, 2], scaled_data2[:, 3], hue=df['target'], palette='Set1')
plt.title('Petal (Scaled)', fontsize=16)
plt.show()

Label Encoder

머신러닝 알고리즘은 문자열 데이터를 입력으로 받지 못합니다.

따라서, 데이터가 가지고 있는 범주형(Categorical) 데이터는 반드시 숫자형(Numerical)으로 변환해주어야 합니다.

LabelEncoder는 범주형(Categorical) 데이터를 수치형으로 인코딩(encoding) 합니다.

여기서 인코딩(encoding) 이란, 문자형 -> 숫자형 데이터로 변환 해주는 것을 의미합니다.

샘플 데이터 (tips)

tips 데이터를 load 합니다.

tips = sns.load_dataset('tips')
tips.head()
# day 컬럼의 분포 확인
tips['day'].value_counts()
plt.figure(figsize=(10, 5))
sns.countplot(tips['day'])
plt.title('Data Counts', fontsize=16)
plt.show()

만약 tips데이터의 day컬럼에서의 값(value)인 [Thur(목), Fri(금), Sat(토), Sun(일)] 을 인코딩(encoding) 해주지 않고 그대로 머신러닝 모델에 학습데이터로 feed한다면 error가 발생합니다.

apply를 활용한 인코딩(encoding)

아래와 같이 encoding이라는 함수를 정의한 후 변환하고자 하는 컬럼에 apply해줌으로써 인코딩을 진행합니다.

# 코드를 입력해 주세요
def converted(x):
    
    
    
  • converted 변수에 변환된 결과를 대입합니다.
  • 대입한 후 결과에 대한 분포를 확인합니다.
# 코드를 입력해 주세요
converted = 
converted.value_counts()

[출력 결과]

2    87
3    76
0    62
1    19
Name: day, dtype: int64

인코딩 한 값을 간단히 시각화 해 볼 수 있습니다.

plt.figure(figsize=(10, 5))
sns.countplot(converted)
plt.title('(Encoded) Data Counts', fontsize=16)
plt.show()

LabelEncoder 활용

위와 같이 apply로 변환하고자 하는 컬럼 별로 인코딩을 해줄 수 있지만, sklearn.preprocessing.LabelEncoder를 활용하여 쉽게 인코딩할 수 있습니다.

from sklearn.preprocessing import LabelEncoder
# 코드를 입력해 주세요
encoder = 
# 코드를 입력해 주세요
encoded = 
encoded
plt.figure(figsize=(10, 5))
sns.countplot(encoded, order=[3, 0, 1, 2])
plt.title('(Encoded) Data Counts', fontsize=16)
plt.show()

LabelEncoder를 사용하면 원래 class 의 label도 확인할 수 있습니다.

encoder.classes_

Inverse Transform(역변환)

머신러닝 학습을 위하여 어쩔 수 없이 범주형(Categorical) 데이터를 숫자형으로 변환하였다면, 이제 결과 확인을 위하여 다시 역변환이 필요합니다.

이는 LabelEncoderinverse_transform을 사용하여 쉽게 역변환할 수 있습니다.

inversed = encoder.inverse_transform(encoded)
inversed
plt.figure(figsize=(10, 5))
sns.countplot(inversed, order=['Thur', 'Fri', 'Sat', 'Sun'])
plt.title('(Inversed) Data Counts', fontsize=16)
plt.show()