티스토리 뷰

데이터 전처리(Preprocessing)은 머신러닝 알고리즘만큼 중요합니다. 사실 더 중요하다고 할 수 있습니다. 알고리즘이 아무리 뛰어나도 Garbage In, Garbage Out은 불변의 법칙이기 때문입니다. 무작정 머신러닝 알고리즘을 이용하기 전에, 데이터에 대해 미리 처리해야 할 기본 사항이 있습니다.

 


첫 번째로, 결손값(NaN, Null)은 허용되지 않습니다. 어떤 피처에 Null 개수가 얼마 없다면 피처의 평균값 등으로 Null을 간단히 대체해도 되지만, Null이 대부분이라면 오히려 해당 피처를 드랍하는 것이 좋습니다. Null의 개수가 애매모호하다면 해당 피처의 중요도 등을 고려하여 더 정밀한 대체값을 선정해야 합니다.

 


두 번째로, 사이킷런 알고리즘 모델은 문자열을 입력값으로 허용하지 않습니다. 그러므로 모든 문자열 값은 인코딩을 통해 숫자형으로 변환돼야 합니다. 문자열 피처는 일반적으로 카테고리 형과 텍스트 형을 의미합니다. 텍스트형 피처는 피처 벡터화 등의 기법으로 벡터화 하거나, 불필요하다면 삭제하는 게 좋습니다. 예를들어, 주민번호나 아이디같은 피처는 단순히 데이터의 식별자이므로 제거하는 것이 모델 성능 향상에 도움이 됩니다.

 


대표적인 인코딩 방식으로 레이블 인코딩(Label encoding)과 원-핫 인코딩(One Hot encoding)이 있습니다. 레이블 인코딩은 카테고리형 피처를 코드형 숫자로 변환합니다.

 

 

 

 

 

 

 

 

 

사이킷런에서 레이블 인코딩은 sklearn.preprocessing 패키지의 LabelEncoder 클래스로 구현됩니다. 해당 객체를 생성한 후 fit()과 transform()을 호출해 레이블 인코딩을 수행합니다.

 

 

 

 

 

 

 

 

 

 

어떤 문자열이 어떤 숫자값으로 인코딩 됐는 지를 확인하려면, classes_ 속성을 확인하면 됩니다. 해당 속성은 0번부터 순서대로 변환된 인코딩 값에 대한 원본값을 가집니다. 따라서 TV = 0,냉장고 = 1 등으로 인코딩됐음을 알 수 있습니다. inverse_transform()을 통해 인코딩된 값을 다시 디코딩 할 수도 있습니다.

 

 

 

 

 

 

 

 

 

 

레이블 인코은 일괄적인 숫자값으로 인코딩을 수행하므로, 몇몇 머신러닝 알고리즘에는 레이블 인코딩을 사용하는 것이 바람직하지 않습니다. 숫자의 크고 작음에 대한 특성이 작용하기 때문입니다. 선형 회귀와 같은 알고리즘에는 레이블 인코딩을 사용해선 안 되며, 트리 계열의 머신러닝 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 레이블 인코딩을 사용해도 문제가 없습니다.

 

 

 

원-핫 인코딩은 레이블 인코딩의 이러한 문제점을 해결합니다. 원-핫 인코딩은 피처 값의 유형에 따라 새로운 피처를 추가해 고유 값에 해당하는 칼럼에만 1을 부여하고, 나머지 칼럼에는 0을 부여합니다.

 

 

 

 

 

 

 

 

 

 

사이킷런에서 OneHotEncoder 클래스로 원-핫 인코딩을 수행할 수 있습니다. LabelEncoder와 다르게 주의해야 할 점이 있습니다. 입력값으로 2차원 데이터가 필요하다는 것과, 인코딩을 수행한 결과가 희소 행렬 객체이므로 이를 다시 toarray() 메서드를 통해 밀집 행렬로 변환해야 하는 것입니다.

 

 

 

 

 

 

 

 

 

 

희소 행렬 객체는 위와 같이 행렬에서 1인 요소의 좌표만을 가지고 있습니다. 희소 행렬로 다시 밀집 행렬을 구성할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

판다스는 원-핫 인코딩을 더 간편하게 제공하는 get_dummies() 메서드를 제공합니다.

 

 

 

 

 

 

 

 

 

이제 피처 스케일링에 대해 알아봅시다. 서로 다른 변수의 값 범위를 일정한 수준으로 맞추는 작업을 피처 스케일링이라고 합니다. 피처 스케일링에는 대표적으로 표준화(Standardization)와 정규화(Normalization)가 있습니다.

 

 

 

 

표준화는 각 피처를 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환하는 것입니다. 위의 식을 적용하여 표준화를 할 수 있습니다.

 

 

 

 

 

정규화는 서로 다른 피처의 크기를 통일하기 위해 크기를 변환해주는 개념입니다. 예를들어 거리를 나타내는 피처의 단위가 0 ~ 100Km이고, 금액을 나타내는 피처가 0 ~ 100,000,000원으로 주어진다면, 두 피처를 동일한 크기 단위로 비교하기 위해 값의 범위를 0 ~ 1로 변환하는 것입니다.

 

 

 

 

그런데, 사이킷런의 전처리에서 제공하는 Normalizer 모듈과 방금 설명한 일반적인 정규화에는 약간의 차이가 있습니다. Normalizer 모듈은 선형대수의 정규화 개념이 적용됐으며, 개별 벡터의 크기를 맞추기 위한 변환을 의미합니다. 혼란을 피하기 위해, 일반적인 표준화와 정규화를 피처 스케일링으로 통칭하고 선형대수 개념의 정규화를 벡터 정규화라고 지칭하겠습니다.

 

 

 

 

 

 

 

 

 

붓꽃 품종 예측 데이터 세트를 가져와서, 각 피처의 평균과 분산을 출력했습니다. 각 피처가 가우시안 정규 분포를 가질 수 있도록 변환하는 것은 특정 알고리즘(예 : SVM, 선형 회귀, 로지스틱 회귀)에서 매우 중요합니다. 해당 알고리즘은 데이터가 정규 분포를 가지고 있다고 가정하고 구현됐기 때문에 사전에 피처를 표준화하는 것이 예측 성능 향상에 중요한 요소가 될 수 있습니다.

 

 

 

 

 

 

 

 

 

 

사이킷런의 StandardScaler API로 표준화를 수행할 수 있습니다. fit(), transform() 메서드에 피처 데이터 세트를 입력하면 됩니다. transform()으로 실제 표준화가 수행될 때 반환값이 ndarray이므로 이를 DataFrame으로 변환하여 평균과 분산을 다시 출력했습니다. 각 피처의 평균이 0, 분산이 1에 매우 가까운 값으로 변환된 것을 볼 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

MinMaxScaler API는 정규화를 수행합니다. 데이터의 분포가 가우시안 분포가 아닐 경우에 Min, Max Scale를 적용해 볼 수 있습니다. 적용 방법은 표준화 하는 법과 같습니다.

 

 

 

케라스의 Scaler 객체를 이용해 데이터를 스케일링 변환 시 fit(), transform(), fit_transform() 메서드를 이용할 수 있습니다. fit()은 데이터 변환을 위한 기준 정보 설정(최댓값/최솟값 등)을 적용하며 transform()은 이렇게 설정한 정보를 이용해 실제로 데이터를 변환합니다. fit_transform()은 두 절차를 한 번에 수행합니다.

 

 

 

그런데 학습 데이터 세트와 테스트 데이터 세트로 fit()과 transform()을 적용할 때 주의해야 할 점이 있습니다. Scaler 객체를 학습 데이터 세트에 fit() 시켰다면, 테스트 데이터 세트에 대해 다시 fit()을 수행하지 않아야 한다는 점입니다. 즉, 학습 데이터로 fit()이 적용된 스케일링 기준 정보를 그대로 학습 데이터와 테스트 데이터를 변환할 때 사용해야 합니다. 학습 데이터와 테스트 데이터를 변환할 때, fit()의 기준이 서로 다르다면 스케일링이 서로 다르게 수행될 수 있고, 모델은 결국 올바른 예측 결과를 도출하지 못할 수 있습니다.

 

 

 

머신러닝 모델은 학습 데이터를 기반으로 학습되므로 테스트 데이터는 반드시 학습 데이터의 스케일링 기준을 따라야 합니다. 이와 같은 이유로, 테스트 데이터에 대해선 fit_transform() 메서드를 절대로 사용하면 안 됩니다. 가장 바람직한 것은 학습/테스트 데이터를 분리하기 전에 전체 데이터에 대해 스케일링을 적용하는 것입니다.

 

 

 

 

«   2025/08   »
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