
0. 들어가면서
이번 장에서 다루게 되는 정규화 및 표준화에 대한 이야기는 데이터 분석 뿐만 아니라 머신러닝, 딥러닝을 사용하기 위해서 기본이 되는 이야기이자, 매우 중요한 이야기가 될 것이다. 막대한 양의 데이터를 다루기 위해 데이터가 어떻게 분포하는 지에 따라 성능에 크게 영향을 줄 수 있기 때문이다. 그렇기 때문에 분석 및 모델학습에 사용되는 변수들이 최대한 비슷한 영향력을 가질 수 있도록 데이터를 변환해주어야 한다. 이번 장에서는 데이터를 변환하는 기술 중 기본이 되는 정규화와 표준화에 대해 알아보고, 서로 어떤 차이가 있고, 어떤 때에 활용되면 좋은지 등에 대해서 다뤄볼 예정이다.
1. 정규화 (Normalization)
먼저 데이터 정규화(Normaliztion) 에 대해서 알아보자. 데이터 분석에서 말하는 정규화라 함은 전체 데이터에 대해서 값을 0 ~ 1 사이의 값으로 치환하는 과정을 의미한다. 기존의 데이터를 0~1 사이의 값으로 크기를 조절하기 때문에 일각에서는 스케일링(Scaling)이라고 표현하기도 한다. 이렇게 값을 바꿔주게되면 학습을 할 때, 원본 데이터 상에서 각 변수별로 값이 다르고, 크기가 큰 값들이 많은 변수에 대한 영향도가 높아지는 데, 이를 방지할 수 있고, 학습 시 Local Minima 에 빠지는 것을 방지할 수 있다. 뿐만 아니라, 일부 머신러닝 알고리즘의 경우, 빠르게 결과값에 수렴을 할 수 있기 때문에 학습 속도도 빨라지는 효과를 가져올 수 있다. 대표적인 정규화 방법으로는 최대값 - 최소값을 사용하는 Min-Max 정규화 방법이 있다.
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import load_iris
iris = load_iris()
x = iris.data
y = iris.target
print("변경 전: ")
print(x)
scaler = MinMaxScaler()
x_norm = scaler.fit_transform(x)
print("변경 후")
print(x_norm)
[실행결과]
변경 전:
[[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]
...
[6.3 2.5 5. 1.9]
[6.5 3. 5.2 2. ]
[6.2 3.4 5.4 2.3]
[5.9 3. 5.1 1.8]]
변경 후
[[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]
...
[0.66666667 0.41666667 0.71186441 0.91666667]
[0.55555556 0.20833333 0.6779661 0.75 ]
[0.61111111 0.41666667 0.71186441 0.79166667]
[0.52777778 0.58333333 0.74576271 0.91666667]
[0.44444444 0.41666667 0.69491525 0.70833333]]
R에서는 caret 패키지의 preProcess() 함수를 통해 스케일링이 가능하다. 해당 함수는 데이터를 정규화, 표준화, 중심화 등의 전처리를 쉽게 할 수 있도록 하는 함수이다. 전처리 방법은 매개변수 중 하나인 "method" 에 입력해주면 되며, 정규화는 "range" 를, 표준화는 "scale" 을, 중심화는 "center" 를 입력해주면 된다. 예시에서는 min-max 스케일링이고, 데이터의 스케일을 최대-최소값의 범위로 조정하여 일정 범위 내에 값을 매핑하는 것이기 때문에 method 의 값으로 "scale" 이 아닌 "range" 를 사용한 것이다.
# 필요한 패키지 로드
install.packages("caret")
library(caret)
# iris 데이터셋 로드
data(iris)
# 1. 정규화
# 데이터 준비
x <- iris[, 1:4]
y <- iris[, 5]
# 정규화 전 데이터 출력
cat("변경 전:\n")
print(head(x))
# Min-Max 스케일링
scaler <- preProcess(x, method = c("range"))
x_norm <- predict(scaler, x)
# 정규화 후 데이터 출력
cat("변경 후:\n")
print(head(x_norm))
[실행결과]
변경 전:
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.1 3.5 1.4 0.2
2 4.9 3.0 1.4 0.2
3 4.7 3.2 1.3 0.2
4 4.6 3.1 1.5 0.2
5 5.0 3.6 1.4 0.2
6 5.4 3.9 1.7 0.4
변경 후:
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 0.22222222 0.6250000 0.06779661 0.04166667
2 0.16666667 0.4166667 0.06779661 0.04166667
3 0.11111111 0.5000000 0.05084746 0.04166667
4 0.08333333 0.4583333 0.08474576 0.04166667
5 0.19444444 0.6666667 0.06779661 0.04166667
6 0.30555556 0.7916667 0.11864407 0.12500000
2. 표준화(Standardization)
이번에는 표준화에 대해서 알아보도록 하자. 데이터 분석에서의 표준화는 정규분포의 형태로 값의 범위를 바꿔준다는 의미이다. 즉, 평균은 0, 표준편차는 1이 되도록 값을 치환하는 것이다. 기대효과는 정규화와 동일하게 원본 데이터를 정규분포에 맞추기 위해 값을 변환하는 작업이므로 값의 범위가 큰 변수에 대한 영향도가 비대해지는 것을 방지할 수 있고, 모델 학습 시 발생할 수 있는 Local Minima 현상을 방지할 수 있다. 대표적인 방법으로는 Z-Score 표준화 기법이 있다.
import numpy as np
sample = np.array([0,1,2,3,4,5])
print("표준화 결과: ", (sample - sample.mean()) / sample.std())
print("정규화 결과: ", (sample - sample.min()) / sample.max() - sample.min())
[실행결과]
표준화 결과: [-1.46385011 -0.87831007 -0.29277002 0.29277002 0.87831007 1.46385011]
정규화 결과: [0. 0.2 0.4 0.6 0.8 1. ]
# 데이터 준비
sample <- c(0, 1, 2, 3, 4, 5)
# 표준화
standardized_result <- (sample - mean(sample)) / sd(sample)
cat("표준화 결과: ", standardized_result, "\n")
# 정규화
normalized_result <- (sample - min(sample)) / (max(sample) - min(sample))
cat("정규화 결과: ", normalized_result, "\n")
[실행결과]
표준화 결과: -1.336306 -0.8017837 -0.2672612 0.2672612 0.8017837 1.336306
정규화 결과: 0 0.2 0.4 0.6 0.8 1
파이썬의 경우에는 사이킷 런 라이브러리에서 아래 코드와 같이 관련함수를 지원해준다.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
x_standard = scaler.fit_transform(x)
print(x_standard)
[실행 결과]
[[-9.00681170e-01 1.01900435e+00 -1.34022653e+00 -1.31544430e+00]
[-1.14301691e+00 -1.31979479e-01 -1.34022653e+00 -1.31544430e+00]
[-1.38535265e+00 3.28414053e-01 -1.39706395e+00 -1.31544430e+00]
위의 코드에서처럼 fit_transform() 메소드 사용하게되면, 학습 데이터에 한 번만 적용시켜도 이 후 동일한 차원의 다른 데이터에 대해서라도 fit() 메소드 사용 없이 바로 transform() 메소드를 사용할 수 있다. 위의 코드를 R에서는 아래와 같이 preProcess() 함수를 통해 구현할 수 있다. 예시에서는 파이썬의 StandardScaler() 와 동일하게 기능할 수 있도록 method 에 "center" 와 "scale" 을 같이 입력하여 표준정규분포의 값을 반환되도록 하였다.
scaler <- preProcess(x, method = c("center", "scale"))
x_standard <- predict(scaler, x)
# 결과 출력
print(head(x_standard))
[실행 결과]
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 -0.8976739 1.01560199 -1.335752 -1.311052
2 -1.1392005 -0.13153881 -1.335752 -1.311052
3 -1.3807271 0.32731751 -1.392399 -1.311052
4 -1.5014904 0.09788935 -1.279104 -1.311052
5 -1.0184372 1.24503015 -1.335752 -1.311052
6 -0.5353840 1.93331463 -1.165809 -1.048667
이 외에도 다양한 전처리 방법이 있으며, 관련내용은 이 후에 하나씩 다뤄볼 예정이다.
'Data Science > 데이터 분석 📊' 카테고리의 다른 글
[데이터 분석] 7. 통계분석 Ⅱ: 확률과 분포 (0) | 2024.07.31 |
---|---|
[데이터분석] 6. 통계 분석Ⅰ: 모집단 & 표본 (0) | 2024.07.31 |
[데이터 분석] 4. 데이터 전처리 Ⅰ : 결측치 & 범주형 (0) | 2024.07.30 |
[데이터분석] 3. 데이터 자료구조 Ⅱ: R (0) | 2024.07.30 |
[데이터 분석] 2. 데이터 자료구조Ⅰ: Python (0) | 2024.07.30 |