본문 바로가기
Python (Linux)

12. Python - 변환기, 특성 스케일링

by #Glacier 2018. 11. 24.
반응형

오늘은 특성 스케일링에 앞서 나만의 변환기에 대해 먼저 볼텐데요. 앞서서 조합했던 특성들을 추가하는 간단한 변환기입니다.

사이킷런은 상속이 아닌 덕 타이핑(duck typing)을 지원하므로, 

fit() (self를 반환) , transform(), fit_transform() 메서드를 구현한 파이썬 클래스를 만들면 됩니다. 

또한 BaseEstimator를 상속하고, 생성자에 *args, **kargs를 사용하지 않으면, 

하이퍼파라미터 튜닝에 필요한 두 메서드(get_param()과 set_param())을 추가로 얻게 됩니다. 

이 경우, 변환기가 add_bedrooms_per_room 하이퍼파라미터 하나를 가지고 있고 기본값은 True로 지정합니다.

(합리적 기본값이 좋습니다.)


 BaseEstimator는 __init__을 통해 스스로를 initialize 한다고 써져있네요.




TransformerMixin은 fit_transform메서드를 가지고 있고, X에는 numpy array (traning Set) 

y에는 target value가 들어가서 변형된 array를 리턴하네용 뭔가 이 API는 java만큼은 친절하진 않은 듯..;;


데이터에 적용할 가장 중요한 변환 중 하나가 특성 스케일링입니다.(Feature Scaling)

몇 가지를 빼면, 머신러닝 알고리즘은 입력 숫자 특성의 스케일이 많이 다르면 잘 작동하지 않습니다. 

주택 가격 데이터도 이에 해당합니다.

즉 전체 방 개수의 범위는 6~39,320인 반면 중간 소득의 범위는 0~15입니다. 

타깃 값에 대한 스케일링은 일반적으로 불필요합니다.

모든 특성의 범위를 같도록 만들어주는 방법으로 min-max 스케일링 표준화(standardization)가 널리 사용됩니다.


min-max 스케일링은 매우 간단한데, 이를 많은 사람들이 정규화(normalization)라 부릅니다.

0~1 범위에 들도록 값을 이동하고, 스케일을 조정하면 됩니다. 

데이터에서 최솟값을 뺀 후 최댓값과 최솟값의 차이로 나누면 이렇게 만들 수 있습니다. 

사이킷 런에서는 이에 해당하는 MinMaxScaler 변환기를 제공합니다

0~1 사이를 원하지 않으면, feature_range 매개변수를 이용하여 범위를 변경 가능합니다.


표준화는 많이 다릅니다. 

먼저 평균을 뺀 후(그래서 표준화를 하면 항상 평균이 0이 됨) 표준 편차로 나누어 분포의 분산이 1이 되도록 합니다.

min-max 스케일링과는 달리 표준화는 범위의 상한과 하한이 없어 때로는 문제가 될 수도 있습니다. 

(예를 들어 신경망에서는 종종 입력값이 0~1 사이를 기대)
그러나 표준화는 이상치에 영향을 덜 받습니다. 사이킷런에는 표준화를 위한 StandardScaler 변환기가 있습니다.


* 모든 변환기에서 스케일링 또한 전체 데이터가 아닌 훈련 데이터에 fit()메서드를 적용하고, 

  훈련 세트와 테스트 세트에 transform()메서드를 사용합니다.


변환 단계가 많지만, 사이킷런에서는 연속된 변환을 순서대로 처리하도록 도와주는 Pipeline 클래스가 있습니다.

숫자 특성을 처리해보죠.


 

〃이전에 했던 imputer를 통해서 누락된 값을 손쉽게 median으로 교체하고, 

특성을 추가하며, StandardScaler를 통해 표준화하는 파이프라인 인가?" 라고 생각하면 될 것 같습니다. 


파이프라인은 연속된 단계를 나타내는 이름 / 추정기 쌍의 목록을 입력으로 받습니다. 

마지막 단계에는 변환기, 추정기를 모두 사용할 수 있고,

그 외에는 모두 변환기여야 합니다. (fit_transform()메서드를 가지고 있어야 한다는 말)

즉, 파이프라인을 통해 마지막 추정까지 한번에 스르륵도 가능 하겠군요..?


파이프라인의 fit()메서드를 호출하면 모든 변환기의 fit_transform()메서드를 순서대로 호출하면서 

한 단계의 출력을 다음 단계의 입력으로 전달합니다. 마지막 단계에서는 fit()메서드만 호출합니다. 

fit_transform()메서드가 없다면 fit()과 transform()을 차례로 호출합니다.


이제, 수치형 컬럼을 넘파이 배열로 추출하는 대신, 판다스의 데이터프레임을 파이프라인에 직접 주입할 수 있다면 좋을 것입니다.

사이킷런이 판다스의 데이터프레임을 다룰 수는 없지만, 이를 처리하는 변환기는 만들 수 있습니다. 

(지금 사용하는 버전 0.20.0 버전에는 특성별 변환을 수행할 수 있는 ColumnTransformer가 

 준비될 예정이라고 하는데요 찾아보셔도 될듯)


(한가지 더 ! from sklearn.preprocessing import Imputer를 사용했는데요. 이게 0.20.0버전에 deprecated되었습니다.  사용할 수는 있는데 바꾸는 방법은 from sklearn.impute import SimpleImputer 하시면 됩니다.)




DataFrameSelector는 나머지는 버리고, 필요한 특성을 선택하여 데이터프레임을 넘파이 배열로 바꾸는 식으로 데이터를 변환합니다. 이를 이용해 데이터 프레임을 받아 수치형만 다루는 파이프라인과 범주형 특성을 만들었고, 범주형 특성을 다루는 파이프라인도

DataFrameSelector로 범주형 특성을("ocean_proximity")을 선택하고 CategoricalEncoder를 적용하여 만듭니다.



이렇게 만든 수치형과 범주형 파이프라인을 사이킷런의 FeatureUnion을 이용하여 합칠 수 있습니다.

변환기 목록(또는 모두 변환기로 이루어진 파이프라인)을 전달하고, transform() 메서드를 호출하면 각 변환기의 transform()

메서드를 병렬로 실행합니다. 그런 다음 각 변환기의 결과를 합쳐 반환합니다. 물론 fit()메서드를 호출하면 각 변환기의 fit()메서드를

실행합니다.


전체 파이프라인을 실행했습니다.


(하다가 오류가 왜났나 했더니 ㅠㅠ DataFrameSelector에서 s하나 빼먹었었네요.. 사진은 고쳐진 겁니다!)


다음시간에는 이제 드디어 훈련을 해보죠!


 블로그 

출처


이 글의 상당 부분은  [핸즈온 머신러닝, 한빛미디어/오렐리앙 제롱/박해선] 서적을 참고하였습니다.


나머지는 부수적인 함수나 메서드에 대해 부족한 설명을 적어두었습니다.

학습용으로 포스팅 하는 것이기 때문에 복제보다는 머신러닝에 관심이 있다면 구매해보시길 추천합니다.


도움이 되셨다면 로그인 없이 가능한

아래 하트♥공감 버튼을 꾹 눌러주세요! 




반응형