[python] Scaler 구현하기

skyepodium·2021년 5월 18일
0

사이킷런의 scaler 3개를 직접 구현해봅시다.
1. MinMaxScaler, 2. StandardScaler, 3. RobustScaler

1. MinMaxScaler

1) 정의

모든 값을 0 ~ 1 사이의 실수로 변환시킵니다.

공식은 다음과 같습니다.

(x - 최소값) / (최대값 - 최소값)

2) 파이썬으로 직접구현

# 0. 계산을 편하게 하기 위해 넘파이를 가져옵니다.
import numpy as np


# 1. 클래스를 만들어줍니다.
class UserMinMaxScaler:
    # 1) 생성자에서 최대값, 최소값을 정의해줍니다.
    def __init__(self):
        self.max_num = -np.inf
        self.min_num = np.inf

    # 2) 최대값, 최소값을 계산해줍니다.
    def fit(self, arr):
        if arr is None:
            print("fit() missing 1 required positional argument: 'X'")

        self.max_num = np.min(arr)
        self.min_num = np.max(arr)

    # 3) 최대값, 최소값을 계산하며 동시에 scaled를 적용합니다.
    def fit_transform(self, arr):
        if arr is None:
            print("fit_transform() missing 1 required positional argument: 'X'")

        self.max_num = np.max(arr)
        self.min_num = np.min(arr)

        # MinMaxScaler 계산 공식을 적용합니다.
        return (arr - self.min_num) / (self.max_num - self.min_num)

    # 4) 이미 계산된 최대값, 최소값으로 scaled를 적용합니다.
    def transform(self, arr):
        return (arr - self.min_num) / (self.max_num - self.min_num)


# 2. 랜덤한 값을 10개가 들어있는 1차원 ndarray를 만듭니다.
random_list = np.random.random(size=(10,))

# 3. 직접 만든 scaler의 인스턴스를 생성합니다.
UMM = UserMinMaxScaler()

# 4. 직접 만든 scaler 로 fit_transform합니다.
scaled_list = UMM.fit_transform(random_list.reshape(-1, 1))
print("1. 직접 구현 결과: ", scaled_list)

# 5. 비교를 위해 사이킷런 라이브러리를 가져옵니다.
from sklearn.preprocessing import MinMaxScaler
MMS = MinMaxScaler()

# 6. 사이킷런을 사용해서 scaled를 적용합니다.
sklearn_list = MMS.fit_transform(random_list.reshape(-1, 1))
print("2. 사이킷런 결과: ", sklearn_list)

"""
1. 직접 구현 결과:  [[0.44808786]
 [0.        ]
 [0.97067102]
 [0.10727862]
 [0.11502583]
 [0.47569795]
 [0.3656127 ]
 [0.11468913]
 [1.        ]
 [0.3340829 ]]
2. 사이킷런 결과:  [[0.44808786]
 [0.        ]
 [0.97067102]
 [0.10727862]
 [0.11502583]
 [0.47569795]
 [0.3656127 ]
 [0.11468913]
 [1.        ]
 [0.3340829 ]]


"""

2. StandardScaler

1) 정의

모든 값을 평균이 0 분산이 1인 정규분포로 변환합니다.

공식은 다음과 같습니다.

(x - 평균) / 표준편차

2) 파이썬으로 직접구현

# 0. 계산을 편하게 하기 위해 넘파이를 가져옵니다.
import numpy as np


# 1. 클래스를 만들어줍니다.
class UserStandardScaler:
    # 1) 생성자에서 평균, 표준편차를 정의해줍니다.
    def __init__(self):
        self.mean_num = None
        self.std_num = None

    # 2) 평균, 표준편차를 계산해줍니다.
    def fit(self, arr):
        if arr is None:
            print("fit() missing 1 required positional argument: 'X'")

        self.mean_num = np.mean(arr)
        self.std_num = np.std(arr)

    # 3) 평균, 표준편차를 계산하며 동시에 scaled를 적용합니다.
    def fit_transform(self, arr):
        if arr is None:
            print("fit_transform() missing 1 required positional argument: 'X'")

        self.mean_num = np.mean(arr)
        self.std_num = np.std(arr)

        # StandardScaler 계산 공식을 적용합니다.
        return (arr - self.mean_num) / self.std_num

    # 4) 이미 계산된 평균, 표준편차로 scaled를 적용합니다.
    def transform(self, arr):
        return (arr - self.mean_num) / self.std_num


# 2. 랜덤한 값을 10개가 들어있는 1차원 ndarray를 만듭니다.
random_list = np.random.random(size=(10,))

# 3. 직접 만든 scaler의 인스턴스를 생성합니다.
UMM = UserStandardScaler()

# 4. 직접 만든 scaler 로 fit_transform합니다.
scaled_list = UMM.fit_transform(random_list.reshape(-1, 1))
print("1. 직접 구현 결과: ", scaled_list)

# 5. 비교를 위해 사이킷런 라이브러리를 가져옵니다.
from sklearn.preprocessing import StandardScaler
SS = StandardScaler()

# 6. 사이킷런을 사용해서 scaled를 적용합니다.
sklearn_list = SS.fit_transform(random_list.reshape(-1, 1))
print("2. 사이킷런 결과: ", sklearn_list)
"""
1. 직접 구현 결과:  [[ 1.3368932 ]
 [-1.16443928]
 [ 0.48077118]
 [-1.15913772]
 [-1.68173761]
 [ 1.16399601]
 [ 0.24231737]
 [ 0.06231553]
 [-0.2641205 ]
 [ 0.98314184]]
2. 사이킷런 결과:  [[ 1.3368932 ]
 [-1.16443928]
 [ 0.48077118]
 [-1.15913772]
 [-1.68173761]
 [ 1.16399601]
 [ 0.24231737]
 [ 0.06231553]
 [-0.2641205 ]
 [ 0.98314184]]
"""

3. RobustScaler

1) 정의

  • 중앙값이 0, 최대값 1, 최소값 -1 인 분포로 변경됩니다.
    만약 이상값이 너무 크거나 작으면 -1, 1을 뚫어버립니다.

공식은 다음과 같습니다.

(x - 중앙값) / (q3 - q1)

2) 파이썬으로 직접구현

# 0. 계산을 편하게 하기 위해 넘파이를 가져옵니다.
import numpy as np


# 1. 클래스를 만들어줍니다.
class UserRobustScaler:
    # 1) 생성자에서 q3, q1, 중앙값을 정의해줍니다.
    def __init__(self):
        self.q3 = None
        self.q1 = None
        self.median_num = None

    # 2) q3, q1, 중앙값을 계산해줍니다.
    def fit(self, arr):
        if arr is None:
            print("fit() missing 1 required positional argument: 'X'")

        self.q3 = np.percentile(arr, 75)
        self.q1 = np.percentile(arr, 25)
        self.median_num = np.median(arr)

    # 3) q3, q1, 중앙값을 계산하며 동시에 scaled를 적용합니다.
    def fit_transform(self, arr):
        if arr is None:
            print("fit_transform() missing 1 required positional argument: 'X'")

        self.q3 = np.percentile(arr, 75)
        self.q1 = np.percentile(arr, 25)
        self.median_num = np.median(arr)

        # RobustScaler 계산 공식을 적용합니다.
        return (arr - self.median_num) / (self.q3 - self.q1)

    # 4) 이미 계산된 q3, q1, 중앙값으로 scaled를 적용합니다.
    def transform(self, arr):
        return (arr - self.median_num) / (self.q3 - self.q1)


# 2. 랜덤한 값을 10개가 들어있는 1차원 ndarray를 만듭니다.
random_list = np.random.random(size=(10,))

# 3. 직접 만든 scaler의 인스턴스를 생성합니다.
UR = UserRobustScaler()

# 4. 직접 만든 scaler 로 fit_transform합니다.
scaled_list = UR.fit_transform(random_list.reshape(-1, 1))
print("1. 직접 구현 결과: ", scaled_list)

# 5. 비교를 위해 사이킷런 라이브러리를 가져옵니다.
from sklearn.preprocessing import RobustScaler
RS = RobustScaler()

# 6. 사이킷런을 사용해서 scaled를 적용합니다.
sklearn_list = RS.fit_transform(random_list.reshape(-1, 1))
print("2. 사이킷런 결과: ", sklearn_list)

"""
1. 직접 구현 결과:  [[ 0.02222105]
 [ 0.71546141]
 [-0.69860117]
 [-0.93813594]
 [ 0.3770147 ]
 [ 0.36368742]
 [-0.40946496]
 [-1.14728874]
 [-0.02222105]
 [ 0.66006727]]
2. 사이킷런 결과:  [[ 0.02222105]
 [ 0.71546141]
 [-0.69860117]
 [-0.93813594]
 [ 0.3770147 ]
 [ 0.36368742]
 [-0.40946496]
 [-1.14728874]
 [-0.02222105]
 [ 0.66006727]]

"""
profile
callmeskye

0개의 댓글