우리는 어떤 일을 하기 전에 준비과정이 필요합니다.
본격적으로 운동을 하기 위해서는 스트레칭 과정이 필요하고, 건물을 짓기 위해서는 땅을 고르게 펴는 토목공사의 작업이 필요해요. 어떤 프로젝트를 시작할 때에는 청사진을 그리면서 필요한 준비물과 인력들을 모으죠.
머신러닝도 마찬가지입니다.
머신러닝의 알고리즘만큼 중요한 것이 바로 데이터의 전처리 입니다.
머신러닝 알고리즘은 데이터에 기반하여 학습을 하는 것이기 때문에 어떤 데이터를 입력값으로 가지느냐에 따라 결과도 크게 달라질 수 있습니다.
이번에는 데이터 전처리 과정 중 인코딩 과정에 대해서 알아볼게요.
데이터 전처리
(1) 결손값 NaN
머신러닝에서 NuN, Null 값은 허용되지 않습니다. 따라서 Null 값은 고정된 다른 값으로 변환해야 합니다.
Null 값을 어떻게 처리해야 할지는 경우에 따라 다릅니다.
만약 나이값이 NuN 일 경우 나이의 평균값 등으로 간단하게 대체할 수 있겠죠.
하지만 대부분의 값이 Null 이라면 오히려 해당 피처는 드롭하는 것이 더 좋습니다.
이처럼 전처리 과정에서 결정의 난제를 주는 것이 Null 값입니다.
중요도가 높은 피처의 경우 단순히 피처의 평균값으로 대체를 할 경우 예측 왜곡이 심할 수 있기 때문이에요.
(2) 문자열값
사이킷런의 머신러닝 알고리즘은 문자열 값을 입력값으로 허용하지 않습니다.
모든 문자열값은 인코딩하여 숫자형으로 변환하거나 불필요한 값은 삭제하여야 합니다.
- 카테고리형 피처 : 코드형 숫자 값으로 변환 (레이블 인코딩)
- 텍스트 피처 : 피처의 백터화 feature vectorization
가령 개인정보에 대한 데이터의 경우 주민등록번호나 사용자의 아이디, 비밀번호 같은 경우에는 삭제하는 것이 좋겠죠.
이렇게 개인이나 사물, 데이터를 식별하기 위한 식별자 피처는 단순히 데이터의 로우를 식별하는 용도로만 사용되기 때문에 알고리즘을 복잡하게 만들어 오히려 예측 성능을 떨어뜨릴 수 있기 때문이에요.
이제 전처리 과정 중에 사용하는 인코딩 방식들을 알아보겠습니다.
데이터 인코딩
기계는 자연어(우리가 쓰는 한국어, 영어 등) 을 이해할 수 없기 때문에, 데이터를 기계가 이해할 수 있도록 숫자 등으로 변환해주는 작업이 필요합니다. 이러한 작업을 인코딩Encoding 이라고 합니다.
머신러닝 인코딩 방식은 데이터 인코딩 label encoding 과 원-핫 인코딩 Ond Hot encoding 방식이 있습니다.
차례대로 알아볼게요.
(1) 레이블 인코딩
카테고리 피처를 코드형 숫자 값으로 변환하는 것이에요. (주의! 01, 02 와 같은 숫자는 문자열이므로 1, 2로 표시)
즉, 피처의 유형에 따라 숫자를 부여합니다.
카테고리 | 코드형 숫자 값 |
아메리카노 | 1 |
카페라떼 | 2 |
카라멜 마끼아또 | 3 |
카페모카 | 4 |
레이블 인코딩 Label encoding 은 LabelEncoder 클래스로 구현합니다.
LabelEncoder 객체 생성 후 -> fit() 과 transform() 을 각각 호출해서 레이블 인코딩을 수행합니다.
from sklearn.preprocessing import LabelEncoder
items=['Tv', '냉장고', '전자레인지', '컴퓨터', '선풍기','선풍기', '믹서', '믹서']
encoder = LabelEncoder()
encoder.fit(items)
labels = encoder.transform(items) # items 에 따라 인코딩
print('인코딩 변환값 : ', labels)
transform(items) 는 items 리스트에 따라 레이블 인코딩을 하는 것이에요.
이제 각각 전자제품들이 각자의 고유 번호로 변환되었습니다.
중복이 되는 선풍기와 믹서는 같은 번호로 할당되었어요.
지금은 데이터가 작아서 어떤 문자열이 어떤 숫자 값으로 인코딩 되었는지 알 수 있지만, 데이터 양이 많아지면 그것을 알기 어렵습니다. 그 경우에는 LabelEncoder 의 classes_ 속성값으로 확인합니다.
여기에서 클래스 속성은 0번부터 원본 값들을 차례대로 가지고 있습니다.
inverse_transform 으로 인코딩 값을 다시 디코딩하는 것도 가능합니다.
레이블 인코딩의 문제점
이렇게 문자열값 -> 숫자형 카테고리 값으로 변환했을 때
어떤 머신러닝 알고리즘에서는 1보다 2가 더 큰 값이기 때문에 예측 오류 등이 발생할 수도 있습니다.
그렇기 때문에 앞으로 우리가 배울 선형회귀 알고리즘에서는 적용하지 않아야 합니다.
트리 계열의 머신러닝 알고리즘의 경우에는 이러한 숫자값의 특성치를 반영하지 않기 때문에 레이블 인코딩을을 해도 문제가 없습니다.
위와 같은 문제점을 개선하기 위해 원-핫 인코딩 방식이 있습니다.
(2) 원-핫 인코딩(One-Hot Encoding)
원-핫 인코딩은 행 형태로 되어 있는 피처를 열 형태로 차원을 변환한 뒤,
고유값에 해당하는 칼럼에만 1을 표시하고 나머지 칼럼에는 0을 표시합니다.
즉, 피처의 유형에 따라 새로운 피처를 추가하고 고유값에 해당하는 칼럼에만 1을 표시하는 거예요.
전체 카테고리의 개수만큼 길이를 가진 배열에 해당 해당 카테고리를 가진 위치는 1, 나머지는 0을 가진 벡터로 변환해요.
다음 예시를 같이 볼게요.
레이블 인코딩은 과일 카테고리의 값들이 0, 1, 2로 변환이 되었다면
원-핫 인코딩은 카테고리의 열 목록이 새로운 피처가 되어 컬럼을 이루고, 그 컬럼에서 해당 고유 값에만 1 이 부여됩니다.
이러한 특성으로 원-핫(여러 개의 속성 중 단 한 개의 속성만 1) 인코딩으로 이름 붙여진 것이에요.
원-핫 인코딩을 하는 방법은 두 가지가 있습니다.
- sklearn 을 이용한 원-핫 인코딩
- pd.get_dummies() -> 원-핫 인코딩을 더 쉽게 지원하는 API
두 방법 모두 하나씩 알아볼게요.
1) sklearn 을 이용한 원-핫 인코딩
사이킷런의 OneHotEncoder 클래스로 변환이 가능합니다.
주의할 점은 다음과 같습니다.
- 입력값으로 2차원 데이터가 필요합니다.
- 레이블 인코딩이 선행되어야 합니다. (모든 문자열 값이 숫자형 값으로 변환되어야 합니다.)
- OneHotEncoder 를 이용한 변환값은 희소 행렬 형태이므로 다시 toarray() 메소드를 이용해 밀집 행렬로 변환해야 합니다.
예제를 통해 같이 알아볼게요.
from sklearn.preprocessing import OneHotEncoder
import numpy as np
items=['Tv', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']
# 2차원 ndarray 변환
items = np.array(items).reshape(-1,1)
#원-핫 인코딩 실행
en = OneHotEncoder()
en.fit(items)
label = en.transform(items)
#원-핫 인코더로 변환한 결과는 희소행렬이므로 toarray()를 이용해서 밀집 행렬로 변환
print(label.toarray())
8개의 레코드와 1개의 칼럼을 가졌던 원본의 데이터가
8개의 레코드와 6개의 칼럼을 가진 데이터로 변환되었습니다.
그럼 이보다 더 쉽게 지원하는 API 를 살펴볼게요.
2) get_dummies() API
사이킷런의 OneHotEncoder 와 다르게 문자열 카테고리 값을 숫자형으로 변환할 필요 없이 바로 변환할 수 있습니다.
import pandas as pd
df = pd.DataFrame({'item' : ['Tv', '냉장고', '전자레인지', '컴퓨터', '선풍기', '선풍기', '믹서', '믹서']})
pd.get_dummies(df)
이렇게 간단하고 쉽게 숫자형 값으로 변환 없이 바로 변환이 가능합니다.
여기까지 NuN 결손값 처리와 문자열 인코딩까지 알아보았습니다.
이 다음에는 피처 스케일링 정규화에 대해서 알아보겠습니다.
'AI 머신러닝 딥러닝 > 파이썬 머신러닝 입문 공부일지' 카테고리의 다른 글
파이썬 머신러닝 입문 공부일지 17. 사이킷런으로 캐글 타이타닉 생존자 예측하기 (1) (0) | 2023.01.06 |
---|---|
파이썬 머신러닝 입문 공부일지 16. 데이터 전처리 (2) 피처 스케일링 (StandardScaler, MinMaxScaler) (0) | 2023.01.06 |
파이썬 머신러닝 입문 공부일지 14. 교차 검증 (3) cross_val_score(), GridSearchCV (0) | 2023.01.05 |
파이썬 머신러닝 입문 공부일지 13. 교차 검증 (2) Stratified K 클래스 (0) | 2023.01.05 |
파이썬 머신러닝 입문 공부일지 12. train_test_split(), 교차 검증 (1) KFold 클래스 (0) | 2023.01.05 |