Search

Data Scaling and Transformer

대분류
인공지능/데이터
소분류
ML/DL 정리 노트
유형
머신 러닝
부유형
데이터 전처리
최종 편집 일시
2024/10/27 15:26
생성 일시
2024/08/23 06:34
14 more properties

셋팅

라이브러리 임포트

데이터 로드

make_blobs()
파라미터
n_samples: 표본 데이터의 수
centers: 생성할 클러스터의 수 또는 중심
cluster_std: 클러스터의 표준 편차
리턴
X: (n_samples, n_features) 크기의 배열 독립 변수
y: (n_smaples) 크기의 배열 종속 변수
X, _ = make_blobs(n_samples= 200, centers= 5, random_state=4, cluster_std=1.5) # 훈련 세트와 테스트 세트로 나눕니다 X_train, X_test = train_test_split(X, random_state=5, test_size=.1) plt.scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") plt.scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") plt.legend() plt.show()
Python
복사

Normalizer(정규화)

Normalizer 의 경우 각 샘플(행)마다 적용되는 방식
이는 한 행의 모든 특성들 사이의 유클리드 거리(L2 norm)가 1이 되도록 스케일링한다.
일반적인 데이터 전처리의 상황에서 사용되는 것이 아니라
모델(특히나 딥러닝) 내 학습 벡터에 적용하며,
특히나 피쳐들이 다른 단위(키, 나이, 소득 등)라면 더더욱 사용하지 않는다
from sklearn.preprocessing import Normalizer scaler = Normalizer() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

Transformer (변환기)

데이터를 정규화(표준화)하는 방법으로, 각 특성(feature)의 평균을 0, 표준편차를 1로 맞추어 변환하는 변환기이다.
데이터를 특정한 방식으로 변환하여 머신러닝 모델의 성능을 개선하는 데 사용
정규 분포 (Normal Distribution) : 데이터가 평균값을 중심으로 좌우 대칭적으로 분포하는 형태 - 종 모양 균등 분포 (Uniform Distribution) : 데이터가 특정 구간 내에서 균일하게 분포하는 형태 - 네모 모양

PowerTransformer

데이터를 정규 분포에 가깝게 만들기 위해 특정 함수(예: Box-Cox 변환 또는 Yeo-Johnson 변환)를 적용하는 방법
사용하는 이유
데이터의 분포가 비대칭적이거나 정규 분포와는 거리가 먼 경우, 모델 성능에 악영향을 미칠 수 있다.
이런 경우 Power Transformer를 사용하여 데이터의 분포를 더 정규에 가깝게 만들 수 있다.
데이터의 특성별로 정규분포형태에 가깝도록 변환
from sklearn.preprocessing import PowerTransformer scaler = PowerTransformer() # 학습 데이터 스케일링 : 해당 fit으로 test데이터도 transform 해준다. X_scaled = scaler.fit_transform(X_train) # fit_transform(X_train)는 X_train 데이터의 분포를 기반으로 스케일링 파라미터를 학습하고, X_train 데이터를 변환하여 X_scaled에 저장 # fit : 학습 데이터의 분포를 분석하여 스케일링에 필요한 파라미터를 계산하고, transform 메서드는 이 파라미터를 사용하여 데이터를 변환 # 테스트 데이터 스케일링 X_test_scaled = scaler.transform(X_test) # transform(X_test) : X_train에서 학습한 스케일링 파라미터를 사용하여 X_test 데이터를 변환 # 같은 스케일링을 적용하여 모델 학습에서 사용한 데이터와 동일한 스케일로 조정 # 산점도 생성 및 시각화 fig, ax = plt.subplots(1,2,figsize=[15,5]) # 1행 2열의 서브플롯을 생성 # 각 서브플롯의 크기는 15x5 인치 # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") # X_train[:, 0]과 X_train[:, 1]은 X_train의 첫 두 열을 표시, # 학습 데이터의 산점도를 파란색('b')으로 표시 # X_test[:, 0]과 X_test[:, 1]은 X_test의 첫 두 열을 표시, # 테스트 데이터의 산점도를 빨간색('r')으로 표시 ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") # X_scaled[:, 0]과 X_scaled[:, 1]은 스케일링된 학습 데이터의 첫 두 열을 표시, # 스케일링된 학습 데이터의 산점도를 파란색으로 표시 # X_test_scaled[:, 0]과 X_test_scaled[:, 1]은 스케일링된 테스트 데이터의 첫 두 열을 표시, # 스케일링된 테스트 데이터의 산점도를 빨간색으로 표시 ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

QuantileTransformer

데이터를 정렬하고, 특정 분포(예: 정규 분포, 균등 분포)에 따라 데이터의 순위를 매겨 변환하는 방법
사용 이유
이상치(outliers)에 민감한 데이터의 경우, 순위 기반 변환을 통해 이상치의 영향을 줄일 수 있다.
데이터를 균등하게 분포시키거나 정규 분포에 맞출 수 있다.
작동 방식: 데이터를 정렬한 다음, 각 데이터 포인트를 원하는 분포(정규 분포, 균등 분포 등)에 맞춰 매핑
기본적으로 1000개 분위를 사용하여 데이터를 '균등분포' 시킨다.
Robust처럼 이상치에 민감하지 않으며, 데이터를 0 ~ 1 사이로 압축한다.
기본 사용
from sklearn.preprocessing import QuantileTransformer scaler = QuantileTransformer() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show() /usr/local/lib/python3.9/dist-packages/sklearn/preprocessing/_data.py:2627: UserWarning: n_quantiles (1000) is greater than the total number of samples (180). n_quantiles is set to n_samples. warnings.warn(
Python
복사
정규 분포 형태로 변환
from sklearn.preprocessing import QuantileTransformer # QuantileTransformer + 정규분포 형태로 변환 scaler = QuantileTransformer(output_distribution = 'normal') X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

Scaler

데이터가 가진 크기와 편차가 다르기 때문에 한 피처의 특징을 너무 많이 반영하거나 패턴을 찾아내는데 문제가 발생한다.
따라서 데이터 스케일링을 통해 모든 피처들의 데이터 분포나 범위를 동일하게 조정해줄 필요가 있다.

Standard Scaler

평균 0, 분산 1로 조정
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

Robust Scaler

평균과 분산 대신 중간값(median)과 사분위값을 사용
중간값과 사분위값을 사용하여 이상치가 있는 데이터에 매우 효과적
from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

MinMax Scaler

모든 피처들을 0 ~ 1 사이의 데이터 값을 갖도록 만듬
음수값이 중요한 데이터일 경우 비권장
이상치에 영향을 많이 받는 방법
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

MaxAbs Scaler

모든 피처들의 절댓값이 0과 1 사이에 놓이도록 만들어준다.
즉, 0을 기준으로 절댓값이 가장 큰 수가 1 또는 -1의 값을 가지게 된다.
이것 역시 이상치에 영향을 많이 받는다.
from sklearn.preprocessing import MaxAbsScaler scaler = MaxAbsScaler() X_scaled = scaler.fit_transform(X_train) #해당 fit으로 test데이터도 transform 해줍니다 X_test_scaled = scaler.transform(X_test) fig, ax = plt.subplots(1,2,figsize=[15,5]) # 첫번째 로우 & 왼쪽 ax[0].scatter(X_train[:,0],X_train[:,1], c='b', label="train data set") ax[0].scatter(X_test[:,0],X_test[:,1], c='r', label="test data set") ax[0].set_title('original') # 첫번째 로우 & 오른쪽 ax[1].scatter(X_scaled[:,0],X_scaled[:,1], c='b', label="train data set") ax[1].scatter(X_test_scaled[:,0],X_test_scaled[:,1], c='r', label="test data set") ax[1].set_title('Scaled') plt.legend() plt.show()
Python
복사

Transformer → Scaler

SalePrice_ss -> SalePrice_ss_log1p
Scaler 적용하고, Transformer를 한 경우
두 그래프의 분포도가 달라지는 것을 알 수 있다.(단점)
SalePrice_log1p -> SalePrice_log1p_ss
Transformer 적용하고, Scaler를 한 경우
두 그래프의 분포도가 동일한 것을 알 수 있다.(장점)

예제 : 유방암

데이터 로드

from sklearn.datasets import load_breast_cancer
Python
복사
cancer=load_breast_cancer() dir(cancer) ['DESCR', 'data', 'data_module', 'feature_names', 'filename', 'frame', 'target', 'target_names']
Python
복사
cancer_df = pd.DataFrame(data=cancer.data, columns=cancer.feature_names) cancer_df['target'] = cancer.target cancer_df.head() cancer_df.shape # (569, 31)
Python
복사

모델 학습

No Scaler

X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size=0.2, random_state=3) dtc = DecisionTreeClassifier() dtc.fit(X_train, y_train) no_scaler_score = round(dtc.score(X_test, y_test), 4) print('모델의 정확도 :', no_scaler_score) # 모델의 정확도 : 0.9035 X_train.shape (455, 30)
Python
복사
X_train_data = X_train.reshape(13650,1) # (전체 데이터 수[455x30]=1차원(row), 1차원) plt.hist(X_train_data, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('before data scaling') plt.show()
Python
복사

Normalizer()

from sklearn.preprocessing import Normalizer # 스케일링 nor_scaler = Normalizer() nor_scaler.fit(X_train) X_train_scaled = nor_scaler.transform(X_train) X_test_scaled = nor_scaler.transform(X_test) # 모델 학습 dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'Normalizer 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # Normalizer 정확도: 0.9298 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('Normalizer') plt.show()
Plain Text
복사

PowerTransformer()

from sklearn.preprocessing import PowerTransformer # 스케일링 ptf = PowerTransformer() ptf.fit(X_train) X_train_scaled = ptf.transform(X_train) X_test_scaled = ptf.transform(X_test) # 모델 학습 dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'PowerTransformer 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # PowerTransformer 정확도: 0.886 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('PowerTransformer') plt.show()
Python
복사

QuantileTransformer()

from sklearn.preprocessing import QuantileTransformer qtf = QuantileTransformer() qtf.fit(X_train) X_train_scaled = qtf.transform(X_train) X_test_scaled = qtf.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'QuantileTransformer 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # QuantileTransformer 정확도: 0.8947 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('QuantileTransformer') plt.show()
Python
복사
qtf = QuantileTransformer(output_distribution = 'normal') qtf.fit(X_train) X_train_scaled = qtf.transform(X_train) X_test_scaled = qtf.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'QuantileTransformer with normal 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # QuantileTransformer with normal 정확도: 0.8772 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('QuantileTransformer with normal') plt.show()
Python
복사

StandardScaler()

from sklearn.preprocessing import StandardScaler std = StandardScaler() std.fit(X_train) X_train_scaled = std.transform(X_train) X_test_scaled = std.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'StandardScaler 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # StandardScaler 정확도: 0.9123 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('StandardScaler') plt.show()
Python
복사

MinMaxScaler()

from sklearn.preprocessing import MinMaxScaler mms = MinMaxScaler() mms.fit(X_train) X_train_scaled = mms.transform(X_train) X_test_scaled = mms.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'MinMaxScaler 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # MinMaxScaler 정확도: 0.886 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('MinMaxScaler') plt.show()
Python
복사

RobustScaler()

from sklearn.preprocessing import RobustScaler rbs = RobustScaler() X_train_scaled = rbs.fit_transform(X_train) X_test_scaled = rbs.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'RobustScaler 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # RobustScaler 정확도: 0.9035 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('RobustScaler') plt.show()
Python
복사

MaxAbsScaler()

from sklearn.preprocessing import MaxAbsScaler mas = MaxAbsScaler() mas.fit(X_train) X_train_scaled = mas.transform(X_train) X_test_scaled = mas.transform(X_test) dtc = DecisionTreeClassifier() dtc.fit(X_train_scaled, y_train) print(f'RobustScaler 정확도: {round(dtc.score(X_test_scaled, y_test), 4)} / No Scaler 정확도: {no_scaler_score}') # RobustScaler 정확도: 0.8947 / No Scaler 정확도: 0.9035
Python
복사
X_train_scaled_ss = X_train_scaled.reshape(13650,1) plt.hist(X_train_scaled_ss, bins=30, color= 'red', alpha = 0.7, density = True) plt.title('MaxAbsScaler') plt.show()
Python
복사