작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
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
을 사용하여 적용하려고 하지만, 훈련 데이터셋에는 없는 새로운 값이 테스트 데이터셋에 존재하여, 이 값에 대한 인코딩 정보가 없어 오류가 발생한 것입니다.
해결책으로는 다음과 같은 방법이 있습니다:
훈련 데이터셋과 테스트 데이터셋을 모두 포함하는 전체 데이터셋에 라벨 인코더를 맞추어(fit
) 전체 값에 대한 인코딩 정보를 가지도록 하고, 그 후 해당 인코더를 각각의 데이터셋에 적용(transform
)합니다. 이렇게 하면, 모든 가능한 유니크한 값을 처리할 수 있으므로 ‘KeyError’ 문제를 방지할 수 있습니다.
혹은 transform
메서드를 호출하기 전에 테스트 데이터셋에 훈련 데이터셋에 없는 값을 확인하고, 이를 처리하는 로직을 추가합니다. 예를 들어, 해당 값을 ‘unknown’과 같은 일반적인 카테고리로 대체하거나, 라벨 인코딩에서 제외할 수 있습니다.
또 다른 방법은 간단하게 사이킷런의 LabelEncoder
대신 pandas
의 factorize
메서드를 사용하는 것인데, 이 메서드는 새로운 라벨에 대해서는 -1
로 인코딩하게 됩니다.
이러한 방법 중 하나를 선택하여 적용해보시면 문제가 해결될 것입니다.
인프런의 다양한 강의와 자료를 참고하여 더 많은 지식을 습득하실 수 있습니다. 추가적인 질문이 있으시다면 언제든지 문의주세요!