복붙노트

[PYTHON] 전에는 볼 수 없었던 sklearn.LabelEncoder

PYTHON

전에는 볼 수 없었던 sklearn.LabelEncoder

sklearn.LabelEncoder가 교육 세트에 설치된 경우 테스트 세트에서 새 값을 발견하면 끊어 질 수 있습니다.

이 문제를 해결할 수있는 유일한 해결책은 테스트 세트에있는 모든 새로운 항목 (예 : 기존 클래스에 속하지 않은 항목)을 ""에 매핑 한 다음 나중에 LabelEncoder에 해당 클래스를 명시 적으로 추가하는 것입니다.

# train and test are pandas.DataFrame's and c is whatever column
le = LabelEncoder()
le.fit(train[c])
test[c] = test[c].map(lambda s: '<unknown>' if s not in le.classes_ else s)
le.classes_ = np.append(le.classes_, '<unknown>')
train[c] = le.transform(train[c])
test[c] = le.transform(test[c])

이 방법이 효과적이지만 더 좋은 해결책이 있습니까?

최신 정보

@sapo_cosmico가 주석에서 지적했듯이, LabelEncoder.transform의 구현 변경으로 인해 위의 내용이 더 이상 작동하지 않는 것으로 보입니다. LabelEncoder.transform에서 np.searchsorted를 사용하는 것으로 보입니다. 그 전에). 따라서 LabelEncoder의 이미 추출 된 클래스 목록에 클래스를 추가하는 대신 정렬 된 순서로 삽입해야합니다.

import bisect
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, '<unknown>')
le.classes_ = le_classes

그러나이 모든 것이 꽤 어색해 보이기 때문에 더 나은 방법이있을 것이라고 확신합니다.

해결법

  1. ==============================

    1.나는이 보이지 않는 데이터 때문에 팬더의 get_dummies로 전환했다.

    나는이 보이지 않는 데이터 때문에 팬더의 get_dummies로 전환했다.

    효과적으로 범주화 된 모든 새 기능은 분류기에 포함되지 않지만 문제가 발생해서는 안되기 때문에 문제가 발생하지 않아야한다고 생각합니다.

  2. ==============================

    2.나는 당신이 한 일이이 상황에 직면했을 때 다른 사람들이하는 것과 매우 비슷하다는 인상을받습니다.

    나는 당신이 한 일이이 상황에 직면했을 때 다른 사람들이하는 것과 매우 비슷하다는 인상을받습니다.

    보이지 않는 레이블을 LabelEncoder로 인코딩하는 기능을 추가하려는 노력이있었습니다 (특히 https://github.com/scikit-learn/scikit-learn/pull/3483 및 https://github.com/scikit-learn/ 참조). scikit-learn / pull / 3599). 그러나 기존 행동을 변경하는 것은 사실 언뜻보기보다 어렵습니다.

    지금은 scikit-learn의 개별 사용자에게 "out-of-vocabulary"라벨을 처리하는 것처럼 보입니다.

  3. ==============================

    3.모델을 교육하고 테스트하는 경우 전체 데이터 세트에 labelencode를 사용하는 것이 좋습니다. 그런 다음 인코더 개체에서 생성 된 클래스를 사용하십시오.

    모델을 교육하고 테스트하는 경우 전체 데이터 세트에 labelencode를 사용하는 것이 좋습니다. 그런 다음 인코더 개체에서 생성 된 클래스를 사용하십시오.

    encoder = LabelEncoder()
    encoder.fit_transform(df["label"])
    train_y = encoder.transform(train_y)
    test_y = encoder.transform(test_y)
    
  4. ==============================

    4.나는 변압기와 Sklearn 파이프 라인 주변에 포장지를 만드는 작업을하는 두 명의 개발자를 알고 있습니다. 그들은 보이지 않는 값을 처리 할 수있는 2 개의 견고한 엔코더 변압기 (하나의 더미 및 하나의 레이블 엔코더)를 가지고 있습니다. 다음은 skutil 라이브러리에 대한 문서입니다. skutil.preprocessing.OneHotCategoricalEncoder 또는 skutil.preprocessing.SafeLabelEncoder를 검색하십시오. SafeLabelEncoder ()에서 보이지 않는 값은 자동으로 999999로 인코딩됩니다.

    나는 변압기와 Sklearn 파이프 라인 주변에 포장지를 만드는 작업을하는 두 명의 개발자를 알고 있습니다. 그들은 보이지 않는 값을 처리 할 수있는 2 개의 견고한 엔코더 변압기 (하나의 더미 및 하나의 레이블 엔코더)를 가지고 있습니다. 다음은 skutil 라이브러리에 대한 문서입니다. skutil.preprocessing.OneHotCategoricalEncoder 또는 skutil.preprocessing.SafeLabelEncoder를 검색하십시오. SafeLabelEncoder ()에서 보이지 않는 값은 자동으로 999999로 인코딩됩니다.

  5. ==============================

    5.이 문제를 해결하기 위해 노력하고 있었고 LabelEncoder를 사용하거나 사용하지 않고 열차 및 테스트 세트의 카테고리 데이터를 인코딩하는 두 가지 편리한 방법을 발견했습니다. 새로운 카테고리는 "c"( "기타"또는 "누락"과 같은) 알려진 일부 cetegory로 채워집니다. 첫 번째 방법은 더 빨리 작동하는 것 같습니다. 희망이 당신을 도울 것입니다.

    이 문제를 해결하기 위해 노력하고 있었고 LabelEncoder를 사용하거나 사용하지 않고 열차 및 테스트 세트의 카테고리 데이터를 인코딩하는 두 가지 편리한 방법을 발견했습니다. 새로운 카테고리는 "c"( "기타"또는 "누락"과 같은) 알려진 일부 cetegory로 채워집니다. 첫 번째 방법은 더 빨리 작동하는 것 같습니다. 희망이 당신을 도울 것입니다.

    import pandas as pd
    import time
    df=pd.DataFrame()
    
    df["a"]=['a','b', 'c', 'd']
    df["b"]=['a','b', 'e', 'd']
    
    
    #LabelEncoder + map
    t=time.clock()
    from sklearn.preprocessing import LabelEncoder
    le = LabelEncoder()
    suf="_le"
    col="a"
    df[col+suf] = le.fit_transform(df[col])
    dic = dict(zip(le.classes_, le.transform(le.classes_)))
    col='b'
    df[col+suf]=df[col].map(dic).fillna(dic["c"]).astype(int)
    print(time.clock()-t)
    
    #---
    #pandas category
    
    t=time.clock()
    df["d"] = df["a"].astype('category').cat.codes
    dic =df["a"].astype('category').cat.categories.tolist()
    df['f']=df['b'].astype('category',categories=dic).fillna("c").cat.codes
    df.dtypes
    print(time.clock()-t)
    
  6. ==============================

    6.나는 최근에이 문제에 부딪 혔고 문제에 대한 아주 빠른 해결책을 제시 할 수있었습니다. 내 대답은이 문제를 해결하는 데 그치지 않지만 문제도 쉽게 해결할 것입니다. (나는 그 아주 근사하다고 생각한다)

    나는 최근에이 문제에 부딪 혔고 문제에 대한 아주 빠른 해결책을 제시 할 수있었습니다. 내 대답은이 문제를 해결하는 데 그치지 않지만 문제도 쉽게 해결할 것입니다. (나는 그 아주 근사하다고 생각한다)

    나는 pandas 데이터 프레임을 사용하고 있으며 원래 sklearns labelencoder ()를 사용하여 내 프로그램의 다른 모듈에서 사용하기 위해 피클링 할 데이터를 인코딩했습니다.

    그러나 sklearn의 전처리에있는 레이블 인코더에는 인코딩 알고리즘에 새 값을 추가 할 수있는 기능이 없습니다. 여러 값을 인코딩하는 문제를 해결하고 새로운 값을 엔코더에 추가 할 수있는 매핑 값을 저장합니다 (여기에 대한 대략적인 내용은 다음과 같습니다).

    encoding_dict = dict()
    for col in cols_to_encode:
        #get unique values in the column to encode
        values = df[col].value_counts().index.tolist()
    
        # create a dictionary of values and corresponding number {value, number}
        dict_values = {value: count for value, count in zip(values, range(1,len(values)+1))}
    
        # save the values to encode in the dictionary
        encoding_dict[col] = dict_values
    
        # replace the values with the corresponding number from the dictionary
        df[col] = df[col].map(lambda x: dict_values.get(x))
    

    그런 다음 사전을 JSON 파일에 간단히 저장할 수 있으며이를 가져 와서 새 값과 해당 정수 값을 추가하여 원하는 값을 추가 할 수 있습니다.

    replace () 대신 map ()을 사용하는 추론에 대해 설명하겠습니다. pandas replace () 함수를 사용하면 약 117,000 줄의 코드를 반복하는 데 1 분 이상이 걸렸습니다. 지도를 사용하면 그 시간이 100ms가 넘게 걸렸습니다.

    TLDR : sklearns를 사용하는 대신 전처리는 매핑 사전을 만들고 값을 직접 매핑하여 데이터 프레임과 함께 작업합니다.

  7. ==============================

    7.LabelEncoder는 기본적으로 사전입니다. 나중에 인코딩 할 때 추출하여 사용할 수 있습니다.

    LabelEncoder는 기본적으로 사전입니다. 나중에 인코딩 할 때 추출하여 사용할 수 있습니다.

    from sklearn.preprocessing import LabelEncoder
    
    le = preprocessing.LabelEncoder()
    le.fit(X)
    
    le_dict = dict(zip(le.classes_, le.transform(le.classes_)))
    

    하나의 새 항목에 대한 레이블 검색, 항목이 없으면 알 수 없음으로 설정

    le_dict.get(new_item, '<Unknown>')
    

    데이터 프레임 열의 레이블 검색 :

    df[your_col].apply(lambda x: le_dict.get(x, <unknown_value>))
    
  8. from https://stackoverflow.com/questions/21057621/sklearn-labelencoder-with-never-seen-before-values by cc-by-sa and MIT license