1.1 표준화 (Standardization)
표준화는 데이터의 평균을 0 분산 및 표준편차를 1로 만들어 줍니다.
표준화를 하는 이유
- 서로 다른 통계 데이터들을 비교하기 용이하기 때문입니다.
- 표준화를 하면 평균은 0, 분산과 표준편차는 1로 만들어 데이터의 분포를 단순화 시키고, 비교를 용이하게 합니다.
표준화 공식
표준화 결과
- 평균이 0이 되고, 분산 정도는 1이 됩니다.(표준편차도 1이 됩니다)
- 데이터가 분포되는 생김새, 패턴이 변하진 않지만, 값의 range(scaling)만 변합니다.
샘플데이터
iris 붓꽃 샘플데이터를 가져옵니다.
**from** sklearn.datasets **import** load_iris
iris **=** load_iris()
x **=** iris['data']*# data, input data, X*
y **=** iris['target'] *# target, labwl, 정답, y*
4개의 feature 데이터 중 1개의 feature만 임의로 선택합니다.
*# x 데이터 중에서 row는 다 받아옥, 컬럼은 첫 번째 것 한 개만 가져온다.*
X **=** x[:, 0]
X[:5]
# array([5.1, 4.9, 4.7, 4.6, 5. ])
표준화 코드 구현
표준화를 Python으로 직접 구현하면 다음과 같습니다. 공식을 그대로 코드로 옮기면 됩니다.
X_ **=** (X**-**X.mean())**/**X.std() *# 표준화 시킨 X 값*
X_
'''
array([-0.90068117, -1.14301691, -1.38535265, -1.50652052, -1.02184904,
-0.53717756, -1.50652052, -1.02184904, -1.74885626, -1.14301691,
'''
시각화
시각화로 표준화의 전과 후를 비교합니다.
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()
표준화 전과 후의 그래프를 구별해보면 가장 두드러지는 점이 바로 평균이 0으로 맞춰진다는 것과 scale이 줄어든다는 것입니다.
StandardScaler의 활용
sklearn.preprocesssing 에 StandardScaler로 표준화 (Standardization) 할 수 있습니다.
표준화를 진행할 땐 y는 라벨이기 때문에 X만 scaling 해야 합니다.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler() # ((150, 4)
x.shape, x[:5]
'''
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2]])
'''
x_scaled = scaler.fit_transform(x)
x_scaled[:5]
'''
array([[-0.90068117, 1.01900435, -1.34022653, -1.3154443 ],
[-1.14301691, -0.13197948, -1.34022653, -1.3154443 ],
[-1.38535265, 0.32841405, -1.39706395, -1.3154443 ],
[-1.50652052, 0.09821729, -1.2833891 , -1.3154443 ],
[-1.02184904, 1.24920112, -1.34022653, -1.3154443 ]])
'''
round(x_scaled
Scale 전, 후 비교 (시각화)
Sepal - 꽃받침
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.scatterplot(x[:,0],x[:,1], hue=y, palette='muted')
plt.title('Sepal(0riginal)', fontsize=16)
plt.subplot(1,2,2)
sns.scatterplot(x_scaled[:,0],x_scaled[:,1], hue=y, palette='muted')
plt.title('Sepal(Scaled)', fontsize=16)
plt.show()
Scale 전, 후 비교 (시각화)
Petal - 꽃잎
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
sns.scatterplot(x[:,2],x[:,3], hue=y, palette='muted')
plt.title('Petal(0riginal)', fontsize=16)
plt.subplot(1,2,2)
sns.scatterplot(x_scaled[:,2],x_scaled[:,3], hue=y, palette='muted')
plt.title('Petal(Scaled)', fontsize=16)
plt.show()
1.2 정규화 (Normalization)
정규화 (Normalization)도 표준화와 마찬가지로 데이터의 스케일을 조정합니다.
정규화가 표준화와 다른 가장 큰 특징은 모든 데이터가 0 ~ 1 사이의 값을 가집니다.
즉, 최대값은 1, 최소값은 0으로 데이터의 범위를 조정합니다.
정규화 공식
scaling ⇒ 데이터 모양 변하지 않고 단지 x, y 값의 range만 변하는데 표준화 작업을 왜 해야 할까요?
예를 들어 영화 평점 예측 model을 Naver vs. 넷플릭스로 비교해봅시다.
네이버는 영화 평점 1~10점이고,
넷플릭스는 영화 평점 1~5점 일 때
두 데이터를 merge 해서 학습시켜야 할 때를 고려해봅시다.
네이버에서 4.5점과 넷플릭스 4점은 평점이 완전히 다른 경우이죠.
하지만 scaling이 맞춰졌을 때 동일한 선상에서 데이터 분석이 가능해질 수 있습니다.
정규화 코드 구현
X = x[:,0]
X_ = (X-X.min())/(X.max()-X.min()) # 정규화 적용
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
scaler = MinMaxScaler()
x_scaled = scaler.fit_transform(x)
x[:5]
'''
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2]])
'''
x_scaled[:5]
'''
array([[0.22222222, 0.625 , 0.06779661, 0.04166667],
[0.16666667, 0.41666667, 0.06779661, 0.04166667],
[0.11111111, 0.5 , 0.05084746, 0.04166667],
[0.08333333, 0.45833333, 0.08474576, 0.04166667],
[0.19444444, 0.66666667, 0.06779661, 0.04166667]])
'''
x_scaled.min(), x_scaled.maxx() # (0.0, 1.0)
Scale 전, 후 비교 (시각화)
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(x[:, 0], x[:, 1], hue=y, palette='muted')
plt.title('Sepal (Original)', fontsize=16)
plt.subplot(1, 2, 2)
sns.scatterplot(x_scaled[:, 0], x_scaled[:, 1], hue=y, palette='muted')
plt.title('Sepal (Scaled)', fontsize=16)
plt.show()
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
sns.scatterplot(x[:, 2], x[:, 3], hue=y, palette='muted')
plt.title('Petal (Original)', fontsize=16)
plt.subplot(1, 2, 2)
sns.scatterplot(x_scaled[:, 2], x_scaled[:, 3], hue=y, palette='muted')
plt.title('Petal (Scaled)', fontsize=16)
plt.show()
2. Encoding ↔ Decoding
Label Encoder
머신러닝 알고리즘은 문자열 데이터를 입력으로 받지 못합니다.
따라서, 데이터가 가지고 있는 범주형(Categorical) 데이터는 반드시 숫자형(Numerical)으로 변환해주어야 합니다.
LabelEncoder는 범주형(Categorical) 데이터를 수치형으로 인코딩(encoding) 합니다.
여기서 인코딩(encoding) 이란, 문자형 -> 숫자형 데이터로 변환 해주는 것을 의미합니다.
샘플 데이터 (tips)
tips = sns.load_dataset('tips')
tips.head()
tips['day'].value_counts() # 값이 많은 순으로 출력
'''
Sat 87
Sun 76
Thur 62
Fri 19
Name: day, dtype: int64
'''
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 convert(data):
if data=='Thur':
return 0
elif data == 'Fri':
return 1
elif data == 'Sat':
return 2
elif data == 'Sun':
return 3
converted = tips['day'].apply(convert)
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
# LabelEncoder 적용
encoder = LabelEncoder()
# LabelEncoder 변환
encoded = encoder.fit_transform(tips['day']) # 날짜를 변환해야 함!
#결과값 확인
encoded
'''
array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 3])
'''
LabelEncoder를 사용하면 원래 class 의 label도 확인할 수 있습니다.
encoder.classes_ # array(['Fri', 'Sat', 'Sun', 'Thur'], dtype=object)
Inverse Transform(역변환)
머신러닝 학습을 위하여 어쩔 수 없이 범주형(Categorical) 데이터를 숫자형으로 변환하였다면, 이제 결과 확인을 위하여 다시 역변환이 필요합니다.
이는 LabelEncoder의 inverse_transform을 사용하여 쉽게 역변환할 수 있습니다.
#역변환
inversed = encoder.inverse_transform(encoded)
inversed
'''
array(['Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri',
'Fri', 'Fri', 'Fri', 'Fri', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sat', 'Sat', 'Sat', 'Sat', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun',
'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Sun', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Thur',
'Thur', 'Thur', 'Thur', 'Thur', 'Thur', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Fri', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat',
'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Sat', 'Thur'], dtype=object)
'''
plt.figure(figsize=(10, 5))
sns.countplot(inversed)
plt.title('(Inversed) Data Counts', fontsize=16)
plt.show()
'AI > 머신러닝' 카테고리의 다른 글
[머신러닝] 경사하강법 (Gradient Descent) 1 (0) | 2022.04.16 |
---|---|
[머신러닝] 최소제곱법을 활용한 LinearRegression (0) | 2022.04.12 |
[머신러닝] K-최근접 이웃(K-NN) 분류 알고리즘 - 실습 (0) | 2022.04.11 |
[머신러닝] K-최근접 이웃(K-NN) 분류 알고리즘 (0) | 2022.04.11 |
[머신러닝] 데이터셋 다루기 (0) | 2022.04.11 |
댓글