강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

작성자 없음

작성자 정보가 삭제된 글입니다.

T2-1 타이타닉 라벨인코딩,,

작성

·

522

0

# 시험환경 세팅 (코드 변경 X)
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

def exam_data_load(df, target, id_name="", null_name=""):
    if id_name == "":
        df = df.reset_index().rename(columns={"index": "id"})
        id_name = 'id'
    else:
        id_name = id_name
    
    if null_name != "":
        df[df == null_name] = np.nan
    
    X_train, X_test = train_test_split(df, test_size=0.2, random_state=2021)
    
    y_train = X_train[[id_name, target]]
    X_train = X_train.drop(columns=[target])

    
    y_test = X_test[[id_name, target]]
    X_test = X_test.drop(columns=[target])
    return X_train, X_test, y_train, y_test 
    
df = pd.read_csv("../input/titanic/train.csv")
X_train, X_test, y_train, y_test = exam_data_load(df, target='Survived', id_name='PassengerId')

X_train.shape, X_test.shape, y_train.shape, y_test.shape
((712, 11), (179, 11), (712, 2), (179, 2))

# print(X_train.head(20))
X_train['Age'] = X_train['Age'].fillna(X_train['Age'].mode()[0])
X_test['Age'] = X_test['Age'].fillna(X_test['Age'].mode()[0])
# print(X_train.head(20))

X_train['Cabin'] = X_train['Cabin'].fillna('X')
X_test['Cabin'] = X_test['Cabin'].fillna('X')
X_train.head()

X_train = X_train.drop('PassengerId', axis=1)
X_test_id = X_test.pop('PassengerId')
target = y_train.pop('Survived')

cols = X_train.select_dtypes(include='object').columns
cols
Index(['Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], dtype='object')

X_train = pd.get_dummies(X_train, columns=cols)
X_test = pd.get_dummies(X_test, columns=cols)

from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(X_train, target, test_size=0.2, random_state=2022)
X_tr.shape, X_val.shape, y_tr.shape, y_val.shape
((569, 1419), (143, 1419), (569,), (143,))

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, roc_auc_score, precision_score, recall_score, f1_score
rf = RandomForestClassifier(random_state=2022)
rf.fit(X_tr, y_tr)
pred = rf.predict_proba(X_val)
print(roc_auc_score(y_val, pred[:,1]))

0.8794421487603306

원핫 인코딩으로 roc_auc_score로 진행한 결과는 0.88로 우수한 점수인데,,

 

라벨 인코딩으로 하면 오류가 납니다 ㅜㅜ( cols 지정한 곳 까지는 위 코드와 동일하며 그 밑에 바로 라벨인코딩 진행한 결과가 아래와 같습니다...) 어떤게 문제일까요? 범주형데이터 설정 했고 라벨인코딩은 범주형데이터에서 작동해야 하는데 작동하질 않습니다,,

 


from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
for col in cols:
    X_train[col] = le.fit_transform(X_train[col])
    X_test[col] = le.transform(X_test[col])
X_train.head()


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/opt/conda/lib/python3.7/site-packages/sklearn/preprocessing/_label.py in _encode_python(values, uniques, encode)
     65         try:
---> 66             encoded = np.array([table[v] for v in values])
     67         except KeyError as e:

/opt/conda/lib/python3.7/site-packages/sklearn/preprocessing/_label.py in <listcomp>(.0)
     65         try:
---> 66             encoded = np.array([table[v] for v in values])
     67         except KeyError as e:

KeyError: 'Ali, Mr. Ahmed'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
/tmp/ipykernel_20/2703680230.py in <module>
      3 for col in cols:
      4     X_train[col] = le.fit_transform(X_train[col])
----> 5     X_test[col] = le.transform(X_test[col])
      6 X_train.head()

/opt/conda/lib/python3.7/site-packages/sklearn/preprocessing/_label.py in transform(self, y)
    275             return np.array([])
    276 
--> 277         _, y = _encode(y, uniques=self.classes_, encode=True)
    278         return y
    279 

/opt/conda/lib/python3.7/site-packages/sklearn/preprocessing/_label.py in _encode(values, uniques, encode, check_unknown)
    111     if values.dtype == object:
    112         try:
--> 113             res = _encode_python(values, uniques, encode)
    114         except TypeError:
    115             types = sorted(t.__qualname__

/opt/conda/lib/python3.7/site-packages/sklearn/preprocessing/_label.py in _encode_python(values, uniques, encode)
     67         except KeyError as e:
     68             raise ValueError("y contains previously unseen labels: %s"
---> 69                              % str(e))
     70         return uniques, encoded
     71     else:

ValueError: y contains previously unseen labels: 'Ali, Mr. Ahmed'

 

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

chandnd37님께서 질문하신 라벨 인코딩 시 발생하는 문제에 대해서 답변드리겠습니다.

주어진 코드에 따르면, LabelEncoder를 사용하여 훈련 데이터셋(X_train)에 라벨 인코딩을 적용한 뒤에 이와 동일한 변환을 테스트 데이터셋(X_test)에 적용하려고 시도하셨습니다. 그러나 "Ali, Mr. Ahmed"라는 새로운 값 때문에 KeyError가 발생했습니다. 문제는, fit_transform 메서드로 라벨 인코더를 훈련 데이터셋에 맞춰(fitting) 적용하면, 데이터셋에 존재하는 유니크한 값을 기반으로 라벨 인코딩을 합니다. 그 후 이 인코더를 테스트 데이터셋에 transform을 사용하여 적용하려고 하지만, 훈련 데이터셋에는 없는 새로운 값이 테스트 데이터셋에 존재하여, 이 값에 대한 인코딩 정보가 없어 오류가 발생한 것입니다.

해결책으로는 다음과 같은 방법이 있습니다:

  1. 훈련 데이터셋과 테스트 데이터셋을 모두 포함하는 전체 데이터셋에 라벨 인코더를 맞추어(fit) 전체 값에 대한 인코딩 정보를 가지도록 하고, 그 후 해당 인코더를 각각의 데이터셋에 적용(transform)합니다. 이렇게 하면, 모든 가능한 유니크한 값을 처리할 수 있으므로 ‘KeyError’ 문제를 방지할 수 있습니다.

  2. 혹은 transform 메서드를 호출하기 전에 테스트 데이터셋에 훈련 데이터셋에 없는 값을 확인하고, 이를 처리하는 로직을 추가합니다. 예를 들어, 해당 값을 ‘unknown’과 같은 일반적인 카테고리로 대체하거나, 라벨 인코딩에서 제외할 수 있습니다.

  3. 또 다른 방법은 간단하게 사이킷런의 LabelEncoder 대신 pandasfactorize 메서드를 사용하는 것인데, 이 메서드는 새로운 라벨에 대해서는 -1로 인코딩하게 됩니다.

이러한 방법 중 하나를 선택하여 적용해보시면 문제가 해결될 것입니다.

인프런의 다양한 강의와 자료를 참고하여 더 많은 지식을 습득하실 수 있습니다. 추가적인 질문이 있으시다면 언제든지 문의주세요!

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기