index
1. 피쳐스케일링, 표준화, 정규화
2. 피쳐의 분포확인 방법.
3. 표준화 정규화 방법.
4. 코드 구현 성능 차이
1. 피쳐 스케일링 표준화 정규화
0) 피쳐 스케일링?
입력된 데이터에는 각각의 피쳐가 있을 텐데,
해당 피쳐들의 값을 일정한 수준으로 맞춰주는 것이 피쳐 스케일링(Feature scalining) 이라 불림.
이때 적용되는 스케일링 방법이 표준화(standardization) 와 정규화(normalization)다.
Q. 우선 스케일링을 왜 하나 ?
가령 우리가 특정 기기의 센서 데이터를 가지고 있고 해당 데이터는 온도, 진동, 전류값, 사용 시간 등등의 피쳐를 가지고 있다고 하자
기기명 | 온도 | 진동 | 전류값 | 사용시간 |
x1 | a1 | |||
x2 | a2 |
테이블의 살펴본 온도 값들의 평균이 -102 이고 대다수의 값들이 큰 음수이며,
반면 그 다음 칼럼인 진동 값들은 평균이 3042 이고 대다수의 값들이 큰 양수이면,
이 두 피쳐의 값들을 있는 그대로 넣었을 때, 이 두 값의 평균과 분산, 최대 최소 값이 제각각이기 때문에
두 피쳐를 비교하기 어렵고 따라서 학습 성능이 떨어질 수밖에 없다.
하지만 표준화를 통해 두 피쳐들의 값들을 평균 0 표편1 인 표준 정규 분포로 만들어 주거나
값의 범위를 0~1 로 제한하는 정규화 과정을 통해서 위와 같은 상황을 방지할 수 있다.
모델의 학습 성능을 높이기 위해서 해당 값들을 일정한 범위 의 값으로 스케일링 해줄 필요가 있다.
1) 표준화 (standardization)
: 입력된 x 들의 정규 분포를 평균이 0 이고 분산이 1 인 표준 정규 분포로 변환한다는 것
즉, 앞서 예시로 든 기기 데이터의 온도 칼럼을 살펴보자면,
온도 값들 A = {a1,a2..an} 값들은 연속 된 값들이기에 해당 A의 평균과 분산을 구할 수 있다.
그리고 이를 통해 정규 분포를 그릴 수 있는데, 이때 표준화는 해당 정규 분포를 평균이 0이고 분산이 1 인
표준 정규 분포로 바꿔 내는 것이다.
정규 분포에 관한 자세한 설명 링크는 여기 !
입력된 각각의 x 를 전체 x 의 평균 (mean) 으로 빼주고, x 의 표준 편차로 나누어주면, 원래의 x는 평균이 0이고 분산이 1 인 표준 정규 분포로 변환됨 |
2) 정규화 (normalization)
: 정규화는 입력된 x 값들을 모두 0과 1사이의 값으로 변환하는 방식이다.
위의 예시처럼 온도, 진동 피쳐는 각각의 값의 범위가 크게 차이나는데
이 두 피쳐를 정규화 시켜준다면, 모두 0~1 사이의 값으로 표현되어 비교가 더욱 쉬워진다.
정규화 공식은 간단하다.
2. 실제 데이터 분석에서 표준화 정규화로 전처리
우선 연속 값으로 된 데이터들을 모델에 학습 시키전에 표준화/정규화 과정을 거치게 된다. (전처리 과정에 포함된다.)
진행순서는
1) 표준화
2) 이상치 발견 및 제거 (z-score 활용)
3) 정규화 순서로 진행된다.
자세한 과정을 코드를 통해 살펴보자면,
0) 데이터 불러오기
from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import StandardScaler
import seaborn as sns
import matplotlib.pyplot as plt
import scipy as sp
import scipy.stats
# 붓꽃 데이터 셋을 로딩하고 DataFrame으로 변환합니다.
iris = load_iris()
iris_data = iris.data
iris_df = pd.DataFrame(data=iris_data, columns=iris.feature_names)
아이리스 데이터를 간단하게 불러왔다
해당 데이터의 형태는 아래와 같고 피쳐는 총 4개이다.
1) 표준화
# 원래 데이터들의 평균과 분산 확인
print('feature 들의 평균 값')
print(iris_df.mean())
print('\nfeature 들의 분산 값')
print(iris_df.var())
# StandardScaler객체 생성
scaler = StandardScaler()
# StandardScaler 로 데이터 셋 변환. fit( ) 과 transform( ) 호출.
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
print("\n=========== 표준화 ==============\n")
#transform( )시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature 들의 평균 값')
print(iris_df_scaled.mean())
print('\nfeature 들의 분산 값')
print(iris_df_scaled.var())
* 표준화는 sklearn preprocessing 모듈에 있는 standardscalaer를 활용해 표준화 작업을 거쳤다 . * 출력 값을 통해 확인 할 수 있듯이 표준화 전에는 각 칼럼의 평균과 분산이 제각각이지만 표준화 이후에는 평균이 0에 가까운 수치이며, 분산은 1인 것을 확인 할 수 있다. |
# 각 값들의 정규 분포 모양 비교비교
f,ax = plt.subplots(1,2,figsize=(8,5))
# 표준화 전 정규분포
x0 = iris_df['petal length (cm)'].dropna().values
sns.distplot(x0, kde=False, rug=False, fit =sp.stats.norm, ax = ax[0]) #커널 밀도 함수, 러그밀도함수 는 안보이고(False) / 정규분포만 보이게(Fit)
# 표준화 이후 정규 분포
x1 = iris_df_scaled['petal length (cm)'].values
sns.distplot(x1, kde=False, rug=False, fit =sp.stats.norm, ax = ax[1])
plt.show()
칼럼 중에서 petal length 데이터를 가져와 해당 데이터가 표준화가 되었는지 정규 분포 그래프를 통해 확인했다.
정규분포 그래프는 scipy의 stats의 norm으로 확인 할 수 있다. (sp.stats.norm)
2) 이상치 발견 및 제거과정
두개다 같은 표준화 공식이다. 우측의 공식은 뮤가 평균, 분모가 표준편차이다.,
우측의 Z(이하 Z-score로 말하겠다)는 표준화된 각각의 데이터를 나타낸다.
따라서 개별 Z-score 는 해당 데이터가 평균으로 부터 얼마나 멀리 떨어져 있는지,
그 떨어진 정도가 표준편차의 몇배인지를 나타낸다
Z-score의 값이 아주 클수록 평균에서는 아주먼 값이며, 표준편차보다는 큰 값을 의미한다.
즉, 이상치이다.***
가령 데이터 테이블에서 온도 값이 말도 안되게 높거나 낮은 값이 있을수 있다.
이건 센서의 오작동이나, 잘못된 이상치 데이터가 포함된 것이다.
우리는 표준화된 Z score 를 통해 잘못된 이상치를 파악할 수 있다.
통상적으로 Z-score 의 절대값이 2가 넘는 경우 이를 이상치라 정의한다.
표준 정규 분포를 통해 우리는 데이터의 신뢰 구간을 파악 할 수 있는데, 자세한 설명은아래를 참조.
https://bioinformaticsandme.tistory.com/256
# check Z score
df_Zscore = pd.DataFrame()
outlier_dict = {}
outlier_idx_list = []
for one_col in iris_df_scaled.columns:
print("Check",one_col)
df_Zscore[f'{one_col}_Zscore'] = sp.stats.zscore(iris_df_scaled[one_col])
outlier_dict[one_col] = df_Zscore[f'{one_col}_Zscore'][(df_Zscore[f'{one_col}_Zscore']>2)|(df_Zscore[f'{one_col}_Zscore']<-2)]
outlier_idx_list.append(list(outlier_dict[one_col].index))
if len(outlier_dict[one_col]):
print(one_col,'Has outliers\n', outlier_dict[one_col])
else:
print(one_col,"Has Not outlier")
print()
print("Before", iris_df_scaled.shape)
all_outlier_idx = sum(outlier_idx_list,[])
iris_df_scaled = iris_df_scaled.drop(all_outlier_idx)
print("After (drop outlier)", iris_df_scaled.shape)
Z score가 -2 미만이거나 2 이상인 값을 추려내는 과정을 거쳤다.
이후 해당 값들의 인덱스를 outlier list에 담았고, 표준화를 거친 데이터에서 해당 인덱스 만 삭제했다.
이렇게 이상치를 제거하는 과정을 거쳤고 총 11개의 이상치가 삭제되었다.
3) 정규화 작업
반드시 이상치 제거 과정을 거친 후 정규화 작업을 해야한다.
가령 방금 전 예시와 같이 대부분의 온도 값이 -10~0 값으로 이루어져있지만,
해당 데이터에 593도 같은 이상치가 포함되었다고 하자.
이러한 경우 최대값인 593도이 1로 매겨져 정규화 작업이 진행될 것이다.
이렇게 될 경우 해당 이상치로 인해 나머지 값들은 0에 가까운 숫자로 왜곡되게 정규화될 가능성이 높다.!
from sklearn.preprocessing import MinMaxScaler
# MinMaxScaler객체 생성
scaler = MinMaxScaler()
# MinMaxScaler 로 데이터 셋 변환. fit() 과 transform() 호출.
scaler.fit(iris_df)
iris_scaled = scaler.transform(iris_df)
# transform()시 scale 변환된 데이터 셋이 numpy ndarry로 반환되어 이를 DataFrame으로 변환
iris_df_scaled = pd.DataFrame(data=iris_scaled, columns=iris.feature_names)
print('feature들의 최소 값')
print(iris_df_scaled.min())
print('\nfeature들의 최대 값')
print(iris_df_scaled.max())
정규화는 minmax scaler 를 통해 이루어진다. 정규화 한후 데이터의 최대 최소 값이 1/0 으로 정돈된 것을 확인 할 수 있다!
3. 정리
오늘은 전처리과정에서 아주 중요한 표준화 정규화 작업에 대해 살펴보았다.
기본적으로 확률 분포에 대한 개념이 있어야 표준화 개념이 이해하기 쉽다.
(위의 유튜브 링크가 설명 잘되어있으니 참고하시길)
사실 이상치 제거는 데이터 분석과정에서 정말 중요한데 추후에 이 부분에 대해서 한 번 더
깊게 다룰 필요가 있을거 같다.
코드 출처 : 파이선 머신러닝 완벽가이드
자료 출처 : https://sunghan-kim.github.io/statistics/stats-PAS-02-RV-PDF-05/
http://blog.daum.net/deeplook/2212617
https://datascienceschool.net/view-notebook/e6c0d4ff9f4c403c8587c7d394bc930a/
https://datascienceschool.net/view-notebook/4c2d5ff1caab4b21a708cc662137bc65/
댓글