import pandas as pd
import numpy as np
import sklearn.preprocessing전처리 | 연속형 자료의 범위 조정
sklearn.preprocessing을 이용하여 자료의 범위를 전처리해보자.
해당 자료는 전북대학교 통계학과 최규빈 교수님의 강의 내용을 토대로 재구성되었음을 밝힙니다.
1. 라이브러리 import
2. MinMaxScaler
A. 모티브
- 예제자료 : 학점, 토익 등이 취업에 미치는 정도
df = pd.read_csv('https://raw.githubusercontent.com/guebin/MP2023/main/posts/employment.csv').loc[:7,['toeic','gpa']]
df| toeic | gpa | |
|---|---|---|
| 0 | 135 | 0.051535 |
| 1 | 935 | 0.355496 |
| 2 | 485 | 2.228435 |
| 3 | 65 | 1.179701 |
| 4 | 445 | 3.962356 |
| 5 | 65 | 1.846885 |
| 6 | 290 | 0.309928 |
| 7 | 730 | 0.336081 |
- 모형을 돌려보고 해석한 결과… (sklearn.linear_model.Linear_Regression())
u = X.toeic*0.00571598 + X.gpa*2.46520018 -8.45433334
v = 1/(1+np.exp(-u))
v # 확률같은것임
그래서… * 토익이 중요해? 아니면 학점이 중요해? * 무엇이 얼만큼 중요해?
- 모티브 : 토익과 gpa 모두 0~1 사이의 척도로 바꾸면 해석이 쉽지 않을까?
### B. 사용방법
- class를 이용, object를 생성하는 방법(이전과 유사한 방법)
scalr = sklearn.preprocessing.MinMaxScaler()
scalr.fit(df)
scalr.transform(df) ## 전처리의 경우에는 transform을 사용한다. .impute.SimpleImputer()에서도 그랬잖아?array([[0.08045977, 0. ],
[1. , 0.07772319],
[0.48275862, 0.55663499],
[0. , 0.28847292],
[0.43678161, 1. ],
[0. , 0.45907256],
[0.25862069, 0.06607128],
[0.76436782, 0.07275881]])
- 역시 한번에 할 수도 있다.
scalr.fit_transform(df) ## 당연히 원래 자료를 훼손하진 않는다.array([[0.08045977, 0. ],
[1. , 0.07772319],
[0.48275862, 0.55663499],
[0. , 0.28847292],
[0.43678161, 1. ],
[0. , 0.45907256],
[0.25862069, 0.06607128],
[0.76436782, 0.07275881]])
sklearn.preprocessing.minmax_scale(df) ## 한 번에 할 수도 있다.array([[0.08045977, 0. ],
[1. , 0.07772319],
[0.48275862, 0.55663499],
[0. , 0.28847292],
[0.43678161, 1. ],
[0. , 0.45907256],
[0.25862069, 0.06607128],
[0.76436782, 0.07275881]])
위처럼 할 수도 있는데, 이 경우는 scalr를 test셋에 적용시킬 수 없기 때문에 사용하지 않는다.
C. 옳고 그른 방법론
# 1 비효율적인 전환
- 주어진 자료가 아래와 같이 train/test로 나뉘어있다고 하자.
X = np.array([1.0, 2.0, 3.0, 4.0, 5.0]).reshape(-1,1)
XX = np.array([1.5, 2.5, 3.5]).reshape(-1,1)
X, XX(array([[1.],
[2.],
[3.],
[4.],
[5.]]),
array([[1.5],
[2.5],
[3.5]]))
scalr = sklearn.preprocessing.MinMaxScaler()
scalr.fit_transform(X), scalr.fit_transform(XX)(array([[0. ],
[0.25],
[0.5 ],
[0.75],
[1. ]]),
array([[0. ],
[0.5],
[1. ]]))
같은 값임에도 다르게 스케일을 변환시키는 것을 볼 수 있다.(X에선 5가 1인데, XX에선 3.5가 1이 됨.
# 2 권장하는 스케일링 방법
scalr = sklearn.preprocessing.MinMaxScaler()
scalr.fit(X)
scalr.transform(X), scalr.transform(XX)(array([[0. ],
[0.25],
[0.5 ],
[0.75],
[1. ]]),
array([[0.125],
[0.375],
[0.625]]))
더 합리적이다.
# 3 변환값의 범위
- 변환한 값이 무조건 0과 1 사이가 되는 것은 아니다.
X = np.array([1.0, 2.0, 3.0, 4.0, 3.5]).reshape(-1,1)
XX = np.array([1.5, 2.5, 5.0]).reshape(-1,1)
## XX의 5.0은 X에서의 최대값인 4.0을 초과한다.sclr = sklearn.preprocessing.MinMaxScaler()
sclr.fit(X)
sclr.transform(X), sclr.transform(XX)(array([[0. ],
[0.33333333],
[0.66666667],
[1. ],
[0.83333333]]),
array([[0.16666667],
[0.5 ],
[1.33333333]]))
스케일링한 값이 1보다 커질 수 있다.
### D. 아주아주 잘못된 스케일링 방법 - 정보누수
- 주어진 자료가 아래와 같다고 하자.
X = np.array([1.0, 2.0, 3.0, 4.0, 3.5]).reshape(-1,1)
XX = np.array([1.5, 2.5, 5.0]).reshape(-1,1)- train data와 test data를 합친다….????!!!??!?!??
np.concatenate([X, XX], axis = 0)array([[1. ],
[2. ],
[3. ],
[4. ],
[3.5],
[1.5],
[2.5],
[5. ]])
- 합친 데이터에서 스케일링….
sklearn.preprocessing.MinMaxScaler().fit_transform(np.concatenate([X, XX], axis = 0))array([[0. ],
[0.25 ],
[0.5 ],
[0.75 ],
[0.625],
[0.125],
[0.375],
[1. ]])
이렇게 전저리하는 것은 정보누수에 해당한다. 본래 test dataset은 알지 못한 상태인데 그것을 합칠 순 없다!
대회에서 이런 일이 발생하면 cheating으로 간주되어 탈락된다.
- 위에서
minmax_scale()로 처리하는 것은 전략적으로 비효율적인 문제이지 치팅과 관련된 치명적인 문제가 아니다. (만약 어떠한 경우에minmax_scale전처리 방식이 유리하다는 생각이 들면 사용해도 무방함)
3. StandardScaler
df = pd.read_csv('https://raw.githubusercontent.com/guebin/MP2023/main/posts/employment.csv').loc[:7,['toeic','gpa']]
df| toeic | gpa | |
|---|---|---|
| 0 | 135 | 0.051535 |
| 1 | 935 | 0.355496 |
| 2 | 485 | 2.228435 |
| 3 | 65 | 1.179701 |
| 4 | 445 | 3.962356 |
| 5 | 65 | 1.846885 |
| 6 | 290 | 0.309928 |
| 7 | 730 | 0.336081 |
여기서 토익과 gpa가 미치는 영향을 비교하기 위해 각 값들을 표준화해보자.
A. 사용법
sclr = sklearn.preprocessing.StandardScaler()
sclr.fit_transform(df)array([[-0.8680409 , -0.98104887],
[ 1.81575704, -0.73905505],
[ 0.3061207 , 0.75205327],
[-1.10287322, -0.08287854],
[ 0.17193081, 2.13248542],
[-1.10287322, 0.44828929],
[-0.34805505, -0.77533368],
[ 1.12803382, -0.75451182]])
MinMaxScaler도 마찬가지로 여러 열을 한번에 할 수 있다.
- 원리
(df.toeic - df.toeic.mean())/df.toeic.std(ddof=0) # 계산식, 자유도는 0(모분산으로 취급)0 -0.868041
1 1.815757
2 0.306121
3 -1.102873
4 0.171931
5 -1.102873
6 -0.348055
7 1.128034
Name: toeic, dtype: float64
그냥 표준화하는 것
4. 비교
- MinMaxScaler와 StandardScaler는 데이터의 스케일을 조정하는 두 가지 일반적인 방법이다.
- MinMaxSclaer:
- 장점 : 원하는 범위 내로 데이터를 조정할 때 유용, 특히 신경망에서는 활성화 함수의 범위와 일치하도록 입력값을 조정하는 데 유용.
- 단점 : 이상치에 매우 민감하다.
- StandardScaler:
- 장점 : 이상치에 덜 민감함, 많은 통계적 기법들 - 선형 알고리즘에서 잘 작동함
- 단점 : 표준화된 데이터의 값이 특정 범위 내에 있음을 보장하지 않음.
단순히 MinMaxScaler는 데이터가 0~1 또는 -1~1사이의 범위에 있다고 가정한다.
그래서 둘 중 어느 것을 선택해야 하는데???
- 둘 중 이상치가 많으면
StandardScaler가 더 적합할 수 있다. - 모델의 알고리즘과 특성에 따라 선택해야 한다. 신경망의 경우
MinMaxScaler가 적합할 수 있다.
결론적으로 두 스케일링 방법 중 어느 것이 더 좋은지는 사용 사례와 데이터의 특성에 따라 다르기 때문에, 가능한 경우 둘 다 시도해보고 모델의 성능을 비교하는 것이 좋다.