ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [scikit-learn] 사이킷런 레이블인코더, 원-핫 인코더로 기계학습 데이터 전처리하기
    Python/기계학습 2024. 3. 13. 10:21
    반응형

    사이킷런 레이블인코더, 원-핫 인코더를 이용해서 기계학습 데이터 전처리하기


    기계학습에 사용되는 데이터는 기본적으로 숫자 기반의 입력값을 가져야 합니다. 그런데, 이 세상의 모든 데이터가 숫자로만 이루어져 있지는 않지요. 그래서 레이블 인코딩(Label Encoding) 및 원-핫 인코딩(One-Hot Encoding)이라는 개념이 생겨나게 되었습니다. 각각의 인코딩은 아래와 같이 정의할 수 있습니다.

     

    • 레이블 인코딩이란, n개의 항목이 있다면, 각 항목을 0, 1, 2, ..., (n-1) 까지의 숫자로 항목의 이름을 대체하는 방법입니다. 이렇게 하면, 문자열이었던 이름을 차원 확장 없이 숫자로 처리할 수 있다는 장점이 있습니다.
    • 원-핫 인코딩은 n개의 항목이 있다면, 각각의 항목이 있는지 없는지를 0과 1로 표기하는 n개의 column을 생성합니다. 이 경우에는 레이블 인코딩의 단점인 각 항목의 대소 정보가 생겨난다는 점을 해소할 수 있습니다.

     

    파이썬(Python)에서는 사이킷런에서 이 기능을 지원하고 있습니다. sklearn.preprocessing.LabelEncodersklearn.preprocessing.OneHotEncoder 입니다.

     

     

    레이블인코더 이용하기


    사이킷런 레이블인코더는 다른 기계학습 모듈의 이용법과 마찬가지로 함수 실행으로 구현합니다. 아래에 설명드리는 세 가지 함수만 기억해 두면 레이블 인코딩을 구현하는데는 특별한 문제가 없을겁니다.

     

    • fit(): 입려된 항목에 따라 인코더를 생성합니다.
    • transform(): 인코딩한 뒤 해당 레이블을 반환시킵니다.

     

    # import package
    from sklearn.preprocessing import LabelEncoder
    
    input_data = ['멍멍', '야옹', '구구구', '찍찍', '멍멍', '멍멍', '구구구', '찍찍']
    
    # encoding
    encoder = LabelEncoder()
    encoder.fit(input_data)
    
    # transform
    print(encoder.transform(input_data))
    [1 2 0 3 1 1 0 3]

     

     

    위와 같이 레이블인코딩을 사용할 경우, 장단점이 하나씩 생겨나게 됩니다. 숫자 형태로 처리할 수 없던 데이터를 기계학습 모델 입력에 적합한 숫자 형태로 변환할 수 있다는 점은 장점이지만, 기존에 없던 정보인 대소관계가 생겨난다는 점이 단점입니다. 예를 들어, 멍멍구구구는 서로 대소관계가 없지만, 이 값이 인코딩된 결과인 10은 1이 더 크다는 대소관계가 생겨나지요.

     

     

    레이블인코더 기능 알아보기


    sklearn.preprocessing.LabelEncoder는 각 항목의 조회 또는 추가 데이터의 변환/복구를 지원합니다. 해당 기능은 함수로 구현되어 있기 때문에, 자주 쓸법한 이름은 외워두시는 것을 추천드립니다.

     

    • classes_: 현재 인코더가 처리할 수 있는 항목들입니다.
    • inverse_transform(): 인코딩된 레이블을 원본 값으로 변환한 뒤 반환시킵니다.
    • fit_transform(): fit()transform() 함수를 한꺼번에 적용할 수 있습니다.

     

    print('현재 인코더가 처리할 수 있는 항목: ', encoder.classes_, '\n')
    print('[0,1,2,3,3,1,2]는 각각 다음과 같은 항목에 해당합니다: ', encoder.inverse_transform([0,1,2,3,3,1,2]), '\n')
    print("['짹짹','삐약'] 인코딩 결과: ", encoder.fit_transform(['짹짹','삐약']), '\n')
    현재 인코더가 처리할 수 있는 항목:  ['구구구' '멍멍' '야옹' '찍찍'] 
    
    [0,1,2,3,3,1,2]는 각각 다음과 같은 항목에 해당합니다:  ['구구구' '멍멍' '야옹' '찍찍' '찍찍' '멍멍' '야옹'] 
    
    ['짹짹','삐약'] 인코딩 결과:  [1 0] 

     

     

    원-핫 인코더 이용하기


    사이킷런 원-핫 인코더는 레이블인코더와 마찬가지로 구현할 수 있습니다. 사용하는 과정에서 유일한 차이점을 꼽아보라고 한다면, sklearn.preprocessing.OneHotEncoder로 이름이 다르다는 점 정도네요. 사용할 데이터는 레이블인코딩에 활용한 것과 동일한 데이터를 써 보도록 하겠습니다. 원-핫 인코더도 레이블인코더와 기본 사용법은 동일합니다.

     

    • fit(): 입력된 항목에 따라 인코더를 생성합니다.
    • transform(): 인코딩한 뒤 해당 데이터를 반환시킵니다.
    • toarray(): 인코딩된 정보를 대상으로 사용할 수 있는 함수이며, 대상 정보를 numpy array 형태로 변환합니다.

     

    # import package
    from sklearn.preprocessing import OneHotEncoder
    import numpy as np
    
    # input data
    input_array = np.array(input_data).reshape(-1, 1)
    print(input_array)
    [['멍멍']
     ['야옹']
     ['구구구']
     ['찍찍']
     ['멍멍']
     ['멍멍']
     ['구구구']
     ['찍찍']]

     

    # encoding
    encoder = OneHotEncoder()
    encoder.fit(input_array)
    
    # transform
    encoder.transform(input_array).toarray()
    array([[0., 1., 0., 0.],
           [0., 0., 1., 0.],
           [1., 0., 0., 0.],
           [0., 0., 0., 1.],
           [0., 1., 0., 0.],
           [0., 1., 0., 0.],
           [1., 0., 0., 0.],
           [0., 0., 0., 1.]])

     

     

    위와 같이 원-핫인코딩을 사용할 수 있습니다. 원-핫 인코딩의 특성상 여러 column이 생겨나게 되는데, 각 column은 입력 데이터의 unique한 값을 오름차순으로 정렬한 것과 같습니다. 이번 입력 데이터로 설명해 보자면, 왼쪽부터 차례대로 ['구구구' '멍멍' '야옹' '찍찍']이라고 생각하면 됩니다.

     



    sklearn.preprocessing.OneHotEncoder를 이용한 변환 결과는 읽기 단순합니다. 각 column의 대상과 일치하는 경우 1, 그렇지 않은 경우 0입니다. 예를 들어, 위 결과는 구구구 와 일치하는 row가 2, 6번이라는 뜻이지요.

    그런데, 원-핫 인코딩 또한 완벽한 방법은 아니기 때문에 장단점이 하나씩 생겨나게 됩니다. 레이블인코딩에서 나타났던 단점인 대소관계가 생성된다는 특성을 해결할 수 있는게 원-핫 인코딩의 최대 장점이지만, 데이터의 column이 입력값에 따라 늘어난다는게 단점입니다. 위 결과에서는 ['구구구' '멍멍' '야옹' '찍찍']의 네 종류가 입력되었기 때문에, column이 하나에서 넷으로 늘어난 것을 확인할 수 있습니다.

     

     

    pandas.get_dummies()를 이용한 원-핫 인코딩


    sklearn.preprocessing.OneHotEncoder 이외에도 편리한 방법으로 원-핫 인코딩을 구현해 주는 함수가 있습니다. 바로 pandas.get_dummies()인데요, 우리가 흔히 쓰는 판다스에서 제공하는 기능이라는 점과, 결과가 데이터프레임으로 나오기 때문에 사람이 보기 편하다는 장점이 있습니다. 다만, 이 함수는 sklearn.preprocessing.OneHotEncoderfit_transform()에 대응하는 함수이기 때문에, 추후 데이터를 추가하면서 변환하는데 어려움이 있다는 점은 단점입니다.

     

     

    # import package
    import pandas as pd
    
    # input data
    input_df = pd.DataFrame(input_data, columns=['animal'])
    input_df
      animal
    0 멍멍
    1 야옹
    2 구구구
    3 찍찍
    4 멍멍
    5 멍멍
    6 구구구
    7 찍찍

     

    pd.get_dummies(input_df)
      animal_구구구 animal_멍멍 animal_야옹 animal_찍찍
    0 0 1 0 0
    1 0 0 1 0
    2 1 0 0 0
    3 0 0 0 1
    4 0 1 0 0
    5 0 1 0 0
    6 1 0 0 0
    7 0 0 0 1
    반응형

    댓글

문의: jwkang3929@naver.com