Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

동삼이의 노트북

캘리포니아 주택 가격 예측 (3) - Feature Engineering 본문

Projects

캘리포니아 주택 가격 예측 (3) - Feature Engineering

동삼이 2020. 11. 9. 19:15

머신러닝 알고리즘에 데이터를 학습시키기 전에, 갖고 있는 데이터를 준비해야 한다. 

 

데이터 정제

대부분의 머신러닝 알고리즘은 결측치를 다룰 수 없기 때문에 이를 처리하는 함수를 만든다. total_bedrooms 변수에 값이 없는 경우가 몇개 있었기 때문에 이를 정제하려 한다. 세가지 방법이 있는데 이는 다음과 같다.

 

  • 해당 구역을 제거한다.
  • 전체 특성을 삭제한다.
  • 특정 값으로 채운다.(0, 평균, 중앙값 등)

여기서는 사이킷런의 SimpleImputer를 사용한다. 누락된 값을 변수의 중간값으로 대체한다고 지정하여 SimpleImputer의 객체를 생성한다.

 

중간값은 수치형 변수에서만 계산될 수 있기 때문에 텍스트 변수인 ocean_proximity를 제외한 데이터 복사본을 생성한다.

 

imputer 객체의 fit() 메서드를 사용하여 훈련데이터에 적용한다.

 

imputer는 각 특성의 중간값을 계산하여 그 결과를 객체의 statistics_ 속성에 저장한다. total_bedrooms에만 누락된 값이 있지만 나중에 시스템이 서비스될 때 새로운 데이터에서 어떤 값이 누락될지 확신할 수 없으므로 모든 수치형 변수에 imputer를 적용하는 것이 바람직하다.

 

순서대로 각 변수 별 중간값이 기록되어 있다.

이제 학습된 imputer객체를 사용해 훈련 세트에 누락된 값을 학습한 중간값으로 바꿀 수 있다.

 

텍스트 변수 처리

 

우리가 갖고 있는 텍스트 변수는 ocean_proximity 뿐이며, 이는 임의의 텍스트가 아닌 가능한 값을 제한된 갯수로 나열한 카테고리형 변수이다. 대부분의 머신러닝 알고리즘은 숫자를 다루기 때문에 사이킷런의 OrdinalEncoder클래스를 사용하여 이 카테고리를 텍스트에서 숫자로 변환하려 한다. 

 

ocean_proximity 가 갖고 있던 카테고리 값들을 0부터 4사이의 숫자로 대체하였다. categories_ 인스턴스 변수를 사용해 카테고리 목록을 얻을 수 있다.

 

하지만 이 경우 머신러닝 알고리즘이 가까이 있는 두 값이 떨어져 있는 두 값보다 더 비슷하다고 생각하는 문제가 발생한다. 예를 들어 1의 숫자를 부여받은 'INLAND' 값과 2의 숫자를 부여받은 'ISLAND'는 머신러닝 알고리즘이 서로 비슷하다고 인지를 할 것이고, 1의 숫자를 부여받은 'INLAND'와 4의 값을 부여받은 'NEAR OCEAN'은 수치적으로 3만큼 다르다고 인지할 것이다.(물론 'bad', 'average', 'good', 'excellent'와 같이 순서가 있는 카테고리의 경우는 괜찮다) 이런 문제의 경우 One-hot encoding을 통해 해결할 수 있다. 카테고리가 'INLAND'일 때 1, 아닌 경우 0이 되는 식의 이진 변수를 만들면 총 5개의 이진 변수를 만들 수 있으며 이를 dummy 변수라고 한다. 사이킷런은 카테고리 값을 원-핫 벡터로 바꾸기 위한 OneHotEncoder 클래스를 제공한다.

 

 

출력을 보면 넘파이 배열이 아닌 SciPy sparse matrix(희소행렬)인 것을 알 수 있다. 이는 수천 개의 카테고리가 있는 범주형 특성일 경우 매우 효율적이다. 이런 특성을 원-핫 인코딩 하면 열이 수천개인 행렬로 변하고 각 행은 1이 하나뿐이고 모두 0으로 채워진 배열일 것이다. 0을 모두 메모리에 저장하는 것은 낭비이므로 희소 행렬은 0이아닌 원소의 위치만 저장한다. 이를 넘파이 배열로 바꾸려면 toarray() 메소드를 호출하면 된다.

 

 

스케일링

데이터에 적용할 가장 중요한 변환 중 하나가 Feature scaling이다. 머신러닝 알고리즘은 입력 숫자 특성들의 스케일이 많이 다르면 제대로 작동하지 않는다. 위 데이터에서는 전체 방 갯수의 범위는 6에서 39,320인 반면 중간 소득의 범위는 0에서 15까지이다.

모든 특성의 범위를 같게 만들어주는 방법으로 min-max scaling standardization이 널리 사용된다.

 

min-max scaling이 가장 간단하다. 0~1 범위에 들도록 값을 이동하고 스케일을 조정하게 된다. 데이터에서 최솟값을 뺀 후 최댓값과 최솟값의 차이로 나누면 이렇게 할 수 있다. 사이킷런에는 이에 해당하는 MinMaxScaler 를 제공하며 0~1 사이를 원하지 않는다면 feature_range매개변수로 범위를 변경할 수 있다.

 

standardization(표준화)은 다르다. 먼저 평균을 뺀 후(그래서 표준화를 하면 평균이 항상 0이 된다.) 표준편차로 나누어 결과 분포의 분산이 1이 되도록 한다. min-max 스케일링과는 달리 표준화는 범위의 상한이나 하한이 없어 어떤 알고리즘에서는 문제가 될 수 있다. (예를 들어 신경망은 종종 입력값의 범위로 0~1 사이를 기대한다). 그러나 표준화는 아웃라이어의 영향을 덜 받는다. 예를들어 0~15 사이 범위 값을 갖는 중간 소득 변수의 경우, 잘못해서 새로운 값을 100이라 입력할 때 min-max 스케일링은 0~15 사이의 모든 다른 값을 0~0.15로 만들어 버리겠지만 표준화는 크게 영향받지 않는다. 사이킷런에는 표준화를 위한 StandardScaler를 제공한다.

 

변환 파이프라인

앞서 진행했던 변환 단계들을 순서대로 실행시키기 위해 사이킷런의 Pipeline 클래스를 이용한다. Pipeline은 연속된 단계를 나타내는 이름/추정기 쌍의 목록을 입력으로 받는다. 마지막 단계에는 변환기와 추정기를 모두 사용할 수 있어야 하고 그 외에는 모두 변환기여야 한다. 즉 fit_transform() 메소드를 갖고 있어야 한다. 

 

파이프라인의 fit() 메소드를 호출하면 모든 변환기의 fit_transform() 메소드를 순서대로 호출하면서 한 단계의 출력을 다음단계의 입력으로 전달한다. 마지막 단계에서는 fit() 메소드만 호출한다.

 

파이프라인 객체는 마지막 추정기와 동일한 메소드를 제공한다. 위의 코드에서는 마지막 추정기가 변환기인 StandardScaler이므로 파이프라인이 데이터에 대해 모든 변환을 순서대로 적용하는 transform() 메소드를 갖고 있다. 

 

위 코드는 num_pipeline이라는 이름의 수치형 변수를 변환 해주는 파이프라인 객체를 생성한다. 순서는 다음과 같다.

  1. SimpleImputer를 이용한 결측치를 median값으로 대체하는 변환기
  2. 직접 만든 CombinedAttributesAdder를 이용하여 가구 당 방 갯수, 가구 당 인구 수, 방 당 침실 수 변수를 만드는 변환기
  3. StandardScaler를 이용한 표준화 스케일링 변환기

여기까지가 수치형 변수를 위한 변환기 pipeline이었다. 우리는 범주형 변수까지 처리하기 원하기 때문에 하나의 변환기로 수치형, 범주형 변수마다 적절한 변환을 적용해주는 ColumnTransformer를 활용한다.

 

ColumnTransformer는 튜플의 리스트를 입력받는다. 각 튜플은 이름, 변환기, 변환기가 적용될 열 이름(또는 인덱스)의 리스트로 이루어진다. 위의 경우 'num' 이라는 이름을 부여한 후 이전 코드에서 생성한 num_pipeline(수치형 변환기) 변환기를 입력, 그 후 수치형 변수들의 이름을 입력하였다. 

 

이제 모델 훈련을 위한 데이터 처리가 끝났다. 다음 포스팅에서는 여러 모델을 훈련해보면서 성능을 평가하고, 최적의 머신러닝 알고리즘을 선택해 볼 것이다. 

Comments