스케일링

강림·2023년 11월 16일
0

Data Pre-processing

목록 보기
8/11
post-thumbnail

1. Scikit-Learn

1.1 Sikit-Learn

  • python을 대표하는 머신러닝 라이브러리
  • 매우 다양한 전처리 도구와 알고리즘을 제공하고 있어 머신러닝 기법을 배우는 데 적합
    • 분류, 회귀, 클러스터링, 차원 축소 등을 포함한 광범위한 머신러닝 알고리즘을 제공
    • 예제와 사용 설명서가 잘 되어있어 참고하여 코드를 작성하기 용이
  • 데이터 분석을 위한 간단하고 효율적인 도구를 제공
    • 간단하고 직관적인 API를 제공하므로 다양한 수준의 전문 지식을 가진 사용자가 접근 가능
      fit(), transform(), predict() 등 체계적이고 일관된 분석 및 학습모형 운용 체계를 갖추고 있음
    • 다른 많은 패키지도 scikit-learn과 동일한 체계를 제공하여 유사한 프레임에서 사용이 가능
  • NumPy, Pandas, SciPy 및 matplotlib를 기반으로 구축되어 있어 다른 파이썬 패키지와 함께 사용하기 용이
    • NumPy: 다차원 배열을 위한 기본 패키지
    • Pandas: 데이터프레임을 위한 기본 패키지
    • SciPy: 과학 계산용 함수를 모아놓은 패키지
    • matplotlib: 데이터 시각화를 위한 패키지
  • 단점은
    • 딥러닝, 강화학습, 시계열 모형은 매우 약함
    • 최근 개발된 대용량을 위한 데이터프레임인 Polars와 같은 라이브러리와는 연동이 잘 안됨

1.2 Scikit-Learn의 주요 기능

  • 분류: 로지스틱 회귀, 결정 트리, 서포트 벡터 머신(SVM)
  • 회귀: 선형 회귀, 릿지 회귀 등
  • 군집화: k-평균 군집화, 계층적 군집화 등
  • 차원 축소: 주성분 분석(PCA), t-분산 확률적 이웃 내재화(t-SNE) 등
  • 전처리: 데이터 정규화, 스케일링, 인코딩 등

2. Scikit-Learn Preprocessing

  • Scikit-learn의 전처리 기능은 크게 4가지로 나눌 수 있음
    • 스케일링(scaling): 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 것
    • 이진화(binarization): 연속적인 값을 0 또는 1로 나누는 것, 연속형 변수 → 이진형 변수
    • 인코딩(encodig): 범주형 값을 적절한 숫자형으로 변환하는 작업, 범주형 변수 → 수치형 변수
    • 변환(transformation): 데이터의 분포를 변환하여 정규성을 확보하는 것

2.1 스케일링(Scaling)

  • 서로 다른 변수(feature)의 값 범위를 선형변환을 통하여 일정한 수준으로 맞추는 작업

    • 독립변수(feature)별로 값의 변위가 상이하면
      • 종속변수(target)에 대한 영향이 독립변수의 변위에 따라 크게 달라짐 → 머신러닝 시 학습효과가 떨어짐
    • 다차원의 값들을 동일한 수준에서 비교 분석하기 용이하게 만들어 줌
    • 컴퓨터의 비트수로 인하여 다른 값으로 인식되는 오버플로우(overflow)나 언더플로우(underflow)를 방지
    • 최적화 과정에서의 안정성 및 수렴 속도를 향상
    • 특히 k-means 등 거리 기반의 모델에서는 스케일링이 매우 중요
  • 표준화, 정규화, 변환이 있음

    • 표준화(Standardization) → 표준분포화(평균을 0, 분산을 1 로 스케일링)

      • StandardScaler(): 기본 스케일러, 평균과 표준편차 사용
      • RobustScaler(): 중앙값과 IQR(Q3-Q1)을 사용. 이상치의 영향을 최소화
    • 정규화(Normalization) → 규격화(특정 범위(주로 [0,1]) 로 스케일링)

      • MinMaxScaler(): 범위가 [0,1]이 되도록 스케일링
      • MaxAbsScaler(): 양수는 [0,1], 음수는 [-1,0], 양음수는 [-1,1]이 되도록 스케일링
    • 변환(Transformation)(특정한 분포나 모양을 따르도록 스케일링)

      • PowerTransformer(): 정규분포화(Box-Cox 변환, Yeo-Johnson 변환)
      • QuantileTransformer(): 균일(Uniform)분포 또는 정규(Gaussian)분포로 변환
      • Normalizer(): 한 행의 모든 피처들 사이의 유클리드 거리가 1이 되도록 변환

2.2 스케일링 절차

Scaler 객체를 이용

  1. fit(): 주어진 데이터에 맞추어 학습
    • 데이터 변환을 위한 기준 정보 설정을 적용 (ex.최소값,최대값 등)
  2. transform(): Scaler 적용, fit()된 정보를 이용해 데이터를 변환
  3. fit_transform() : fit()과 transform()을 한 번에 실행

훈련 데이터와 평가 데이터의 스케일링 변환 시 유의점

  • 훈련 데이터는 fit()과 transform() 모두 적용
    • 평가 데이터는 fit()은 필요없으므로 transform()만 적용해야 함
    • 훈련 데이터로 fit()된 스케일링 기준 정보를 그대로 테스트에 적용해야하기 때문

2.3 표준화 (Standardization)

  • 표준화를 하면, 서로 다른 통계 데이터들을 비교하기 용이함

    • 평균은 0, 분산과 표준편차는 1이 되므로 데이터의 분포가 단순화되어 독립변수간 데이터 수준의 비교가 용이
    • RBF(Radial Basis Function) 커널을 이용하는 서포트 벡터 머신(Support Vector Machine), 선형회귀(Linear Regression), 로지스틱 회귀(Logistic Regression)는 데이터가 정규분포를 가지고 있다고 가정하고 구현됨
      • RBF Kernel: Gaussian kernel, 가우시안 방사 기저 함수
  • 이상치에 민감하며, 분류보다는 회귀에 유용


  • 기저함수(basis function, ϕ) 혹은 feature map은 비선형 특징을 가지는 Input space를 선형 특징을 가지는 Feature space로 변환해주는 함수

  • Kernel이란 알맹이, 핵심이라는 뜻
    • 운영체제(Operation System)에서는 컴퓨터 자원을 관리하는 핵심 부분을 의미
    • 수학에서는 기저함수의 내적을 계산하는 함수
      • 커널함수는 두 벡터를 입력받아서 하나의 스칼라 값을 계산하는 함수
      • 일종의 변환함수라고 생각하면 됨


데이터 로드

import pandas as pd
import seaborn as sns

# Pandas 소수점 4째자리 이하에서 반올림
pd.set_option('display.float_format', lambda x: f'{x:.4f}')

# iris 데이터 로드
iris = sns.load_dataset('iris')

# iris의 수치형 변수만 선택
iris = iris.select_dtypes(exclude='object')

# iris의 기술통계량을 확인
iris.describe()

# sepal_lengh와 petal_length의 jointplot을 그림
sns.jointplot(data=iris, x='petal_length', y='petal_width', kind='reg')

iris.select_dtypes(exclude='object')는 데이터프레임 iris에서 'object' 타입을 제외한 모든 열을 선택

데이터 분석 및 머신러닝 모델 학습에 있어서 특히 수치형 데이터에만 관심이 있는 경우에 유용

표준화

from sklearn.preprocessing import StandardScaler, RobustScaler

# Scaler 객체 생성
standard_scaler = StandardScaler()
robust_scaler = RobustScaler()

# 데이터 변환
iris_standard = pd.DataFrame(standard_scaler.fit_transform(iris), columns=iris.columns)
iris_robust = pd.DataFrame(robust_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print('Standard Scaled: \n', iris_standard.describe()) # mean = 0, std = 1
print()
print('Robust Scaled: \n', iris_robust.describe()) # median = 0, IQR = 1

scikit-learn 라이브러리에서 제공하는 StandardScaler와 RobustScaler를 사용하여 데이터를 표준화(standardization) 및 로버스트 표준화(robust standardization)하는 과정

  • StandardScaler: 평균이 0이고 표준편차가 1이 되도록 데이터를 표준화하는 객체

  • RobustScaler: 중앙값(median)과 사분위수(quartiles)를 사용하여 이상치에 민감하지 않게 데이터를 표준화하는 객체

  • seaborn의 jointplot은 figure의 axes를 지정할 수 없어 subplot을 그리기가 어려움
  • patchworklib 패키지8을 사용하여 subplot을 그림
    • 설치
      (mamba install patchworklib)
# 그래프로 확인
import seaborn as sns
import patchworklib as pw
pw.overwrite_axisgrid()

# 첫번째 그래프 
g1 = sns.jointplot(data=iris_standard, x='petal_length', y='petal_width', kind='reg')
g1 = pw.load_seaborngrid(g1)
g1.set_suptitle("Standard Scaled")

# 두번째 그래프 
g2 = sns.jointplot(data=iris_robust, x='petal_length', y='petal_width', kind='reg')
g2 = pw.load_seaborngrid(g2)
g2.set_suptitle("Robust Scaled")

# 그래프 합치기
g12 = (g1|g2)
g12
  • sns.jointplot(...): seaborn의 jointplot 함수를 사용하여 표준화된 데이터에 대한 산점도와 회귀선을 그림
  • x='petal_length', y='petal_width': x축과 y축에 각각 'petal_length'와 'petal_width' 열의 데이터를 사용
  • kind='reg': 회귀선이 있는 산점도를 그립니다.
  • pw.load_seaborngrid(g1): patchwork 라이브러리에서 seaborn 그리드를 로드
  • g1.set_suptitle("Standard Scaled"): 그래프의 전체 제목을 설정

2.4 정규화(Normalization)

  • MinMaxScaler(): 범위가 [0,1]이 되도록 스케일링
  • MaxAbsScaler()
    • 모든 값이 양수이면, 범위가 [0,1]이 되도록 스케일링, MinMaxScaler()와 유사
    • 모든 값이 음수이면, 범위가 [-1,0]이 되도록 스케일링
    • 양수와 음수가 혼재하면, 범위가 [-1,1]이 되도록 스케일링
from sklearn.preprocessing import MinMaxScaler, MaxAbsScaler

# Scaler 객체 생성
minmax_scaler = MinMaxScaler()
maxabs_scaler = MaxAbsScaler()

# 데이터 변환
iris_minmax = pd.DataFrame(minmax_scaler.fit_transform(iris), columns=iris.columns)
iris_maxabs = pd.DataFrame(maxabs_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print('MinMax Scaled: \n', iris_minmax.describe()) # min = 0, max = 1
print()
print('MaxAbs Scaled: \n', iris_maxabs.describe()) # min ~ 0, max = 1

scikit-learn 라이브러리에서 제공하는 MinMaxScaler와 MaxAbsScaler를 사용하여 데이터를 최소-최대 스케일링(Min-Max Scaling)과 최대 절대값 스케일링(Maximum Absolute Scaling)하는 과정

스케일링은 데이터의 범위를 조절하여 특정 구간에 데이터를 매핑하거나, 데이터의 절대값을 최대 1로 만드는 등의 목적

  • MinMaxScaler: 데이터를 최소-최대 스케일링하여 최소값이 0, 최대값이 1이 되도록 만드는 객체

  • MaxAbsScaler: 최대 절대값을 1로 만들어 데이터를 스케일링하는 객체

  • fit_transform: 주어진 데이터에 대해 스케일러를 학습하고, 동시에 데이터를 변환

  • minmax_scaler.fit_transform(iris): MinMaxScaler를 사용하여 iris 데이터를 최소-최대 스케일링

  • maxabs_scaler.fit_transform(iris): MaxAbsScaler를 사용하여 iris 데이터를 최대 절대값 스케일링

  • pd.DataFrame(...): 변환된 데이터를 새로운 데이터프레임

  • columns=iris.columns: 원래 데이터프레임의 열 이름을 유지

# 세번째 그래프 
g3 = sns.jointplot(data=iris_minmax, x='petal_length', y='petal_width', kind='reg')
g3 = pw.load_seaborngrid(g3)
g3.set_suptitle("MinMax Scaled")

# 네번째 그래프 
g4 = sns.jointplot(data=iris_maxabs, x='petal_length', y='petal_width', kind='reg')
g4 = pw.load_seaborngrid(g4)
g4.set_suptitle("MaxAbs Scaled")

# 그래프 합치기
g34 = (g3|g4)
g34

seaborn 라이브러리를 사용하여 최소-최대 스케일링된(MinMax Scaled) 데이터와 최대 절대값 스케일링된(MaxAbs Scaled) 데이터에 대한 산점도와 회귀선을 시각화하고, 이를 patchwork 라이브러리를 사용하여 함께 표시

2.5 변환(Transformation)

  • PowerTransformer(): 정규성 변환(Box-Cox 변환, Yeo-Johnson 변환)
  • QuantileTransformer(): 균일(Uniform)분포 또는 정규(Gaussian)분포로 변환
  • Normalizer(): 한 행의 모든 피처들 사이의 유클리드 거리가 1이 되도록 변환
import numpy as np
from sklearn.preprocessing import PowerTransformer, Normalizer

# Scaler 객체 생성
power_scaler = PowerTransformer()
normal_scaler = Normalizer()

# 데이터 변환
iris_power = pd.DataFrame(power_scaler.fit_transform(iris), columns=iris.columns)
iris_normal = pd.DataFrame(normal_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print('PowerTranformer Scaled: \n', iris_power.describe()) # mean = 0, std = 1
print()
print('Normalizer Scaled: \n', iris_normal.describe())
print('Euclidian Distance from 0: \n', np.linalg.norm(iris_normal, axis=1)) # 각 행의 벡터 크기가 1이 되는지 확인

scikit-learn 라이브러리에서 제공하는 PowerTransformer와 Normalizer를 사용하여 데이터를 변환하는 작업을 수행

PowerTransformer는 데이터를 정규 분포에 가깝게 변환하고, Normalizer는 각 행의 벡터를 정규화하여 크기가 1이 되도록 만듦

  • PowerTransformer: 데이터를 정규 분포에 가깝게 변환하는 스케일러
    기본적으로는 Box-Cox 변환을 수행
  • Normalizer: 각 행의 벡터를 정규화하여 크기가 1이 되도록 만드는 스케일러
  • np.linalg.norm(iris_normal, axis=1): 각 행의 벡터 크기를 계산하여 출력
    각 행이 정규화되었을 때 1이 되어야 함

# 다섯번째 그래프
g5 = sns.jointplot(data=iris_power, x='petal_length', y='petal_width', kind='reg')
g5 = pw.load_seaborngrid(g5)
g5.set_suptitle("PowerTransformer Scaled")

# 여섯번째 그래프
g6 = sns.jointplot(data=iris_normal, x='petal_length', y='petal_width', kind='reg')
g6 = pw.load_seaborngrid(g6)
g6.set_suptitle("Normalizer Scaled")

# 그래프 합치기
g56 = (g5|g6)
g56

from sklearn.preprocessing import QuantileTransformer

# Scaler 객체 생성
gaussian_scaler = QuantileTransformer(output_distribution='normal')
uniform_scaler = QuantileTransformer(output_distribution='uniform')

# 데이터 변환
iris_gaussian = pd.DataFrame(gaussian_scaler.fit_transform(iris), columns=iris.columns)
iris_uniform = pd.DataFrame(uniform_scaler.fit_transform(iris), columns=iris.columns)

# 결과 출력
print('QuantileTranformer_Gaussian Scaled: \n', iris_gaussian.describe())
print()
print('QuantileTranformer_Uniform Scaled: \n', iris_uniform.describe())

scikit-learn 라이브러리에서 제공하는 QuantileTransformer를 사용하여 데이터를 변환하는 작업을 수행

QuantileTransformer는 데이터를 특정 분위수에 매핑하여 변환하는 스케일러 중 하나

정규 분포와 균일 분포 두 가지 타입의 출력 분포를 지정하여 사용

  • QuantileTransformer: 데이터를 특정 분위수에 매핑하여 변환하는 스케일러입니다.
  • output_distribution='normal': 정규 분포로 변환합니다.
  • output_distribution='uniform': 균일 분포로 변환합니다.

# 일곱번째 그래프
g7 = sns.jointplot(data=iris_gaussian, x='petal_length', y='petal_width', kind='reg')
g7 = pw.load_seaborngrid(g7)
g7.set_suptitle("QuantileTranformer_Gaussian Scaled")

# 여덟번째 그래프
g8 = sns.jointplot(data=iris_uniform, x='petal_length', y='petal_width', kind='reg')
g8 = pw.load_seaborngrid(g8)
g8.set_suptitle("QuantileTranformer_Uniform Scaled")

# 그래프 합치기
g78 = (g7|g8)
g78

# 모든 그래프 합치기

(g1|g2|g3|g4)/(g5|g6|g7|g8)

응용해보기

import matplotlib.pyplot as plt

# Original Data
plt.figure(figsize=(15, 5))
plt.subplot(2, 5, 1)
sns.scatterplot(data=iris, x='petal_length', y='petal_width')
plt.title('Original Data')

# Standard Scaled
plt.subplot(2, 5, 2)
sns.scatterplot(data=iris_standard, x='petal_length', y='petal_width')
plt.title('Standard Scaled')

# Robust Scaled
plt.subplot(2, 5, 3)
sns.scatterplot(data=iris_robust, x='petal_length', y='petal_width')
plt.title('Robust Scaled')

# MinMax Scaled
plt.subplot(2, 5, 4)
sns.scatterplot(data=iris_minmax, x='petal_length', y='petal_width')
plt.title('MinMax Scaled')

# MaxAbs Scaled
plt.subplot(2, 5, 5)
sns.scatterplot(data=iris_maxabs, x='petal_length', y='petal_width')
plt.title('MaxAbs Scaled')

# PowerTransformer Scaled
plt.subplot(2, 5, 6)
sns.scatterplot(data=iris_power, x='petal_length', y='petal_width')
plt.title('PowerTransformer Scaled')

# Normalizer Scaled
plt.subplot(2, 5, 7)
sns.scatterplot(data=iris_normal, x='petal_length', y='petal_width')
plt.title('Normalizer Scaled')

# QuantileTranformer_Gaussian Scaled
plt.subplot(2, 5, 8)
sns.scatterplot(data=iris_gaussian, x='petal_length', y='petal_width')
plt.title('QuantileTranformer_Gaussian Scaled')

# QuantileTranformer_Uniform Scaled
plt.subplot(2, 5, 9)
sns.scatterplot(data=iris_uniform, x='petal_length', y='petal_width')
plt.title('QuantileTranformer_Uniform Scaled')

plt.tight_layout()
plt.show()

profile
DRUDGER

0개의 댓글