[python] Python에서 핫 인코딩을 어떻게 할 수 있습니까?

80 % 범주 형 변수가있는 기계 학습 분류 문제가 있습니다. 분류에 일부 분류자를 사용하려면 핫 인코딩을 하나 사용해야합니까? 인코딩없이 분류기에 데이터를 전달할 수 있습니까?

기능 선택을 위해 다음을 수행하려고합니다.

  1. 기차 파일을 읽었습니다.

    num_rows_to_read = 10000
    train_small = pd.read_csv("../../dataset/train.csv",   nrows=num_rows_to_read)
  2. 카테고리 기능의 유형을 ‘카테고리’로 변경합니다.

    non_categorial_features = ['orig_destination_distance',
                              'srch_adults_cnt',
                              'srch_children_cnt',
                              'srch_rm_cnt',
                              'cnt']
    
    for categorical_feature in list(train_small.columns):
        if categorical_feature not in non_categorial_features:
            train_small[categorical_feature] = train_small[categorical_feature].astype('category')
  3. 하나의 핫 인코딩을 사용합니다.

    train_small_with_dummies = pd.get_dummies(train_small, sparse=True)

문제는 내가 강한 기계를 사용하고 있는데도 세 번째 부분이 자주 막히는 것입니다.

따라서 하나의 핫 인코딩 없이는 기능의 중요성을 결정하기 위해 기능 선택을 할 수 없습니다.

추천 메뉴가 무엇인가요?



답변

접근 방식 1 : Pandas 데이터 프레임에서 get_dummies를 사용할 수 있습니다.

예 1 :

import pandas as pd
s = pd.Series(list('abca'))
pd.get_dummies(s)
Out[]:
     a    b    c
0  1.0  0.0  0.0
1  0.0  1.0  0.0
2  0.0  0.0  1.0
3  1.0  0.0  0.0

예 2 :

다음은 주어진 열을 하나의 핫으로 변환합니다. 여러 더미를 갖기 위해 접두사를 사용하십시오.

import pandas as pd

df = pd.DataFrame({
          'A':['a','b','a'],
          'B':['b','a','c']
        })
df
Out[]:
   A  B
0  a  b
1  b  a
2  a  c

# Get one hot encoding of columns B
one_hot = pd.get_dummies(df['B'])
# Drop column B as it is now encoded
df = df.drop('B',axis = 1)
# Join the encoded df
df = df.join(one_hot)
df
Out[]:
       A  a  b  c
    0  a  0  1  0
    1  b  1  0  0
    2  a  0  0  1

접근 방식 2 : Scikit-learn 사용

3 개의 기능과 4 개의 샘플이있는 데이터 세트가 주어지면 인코더가 기능 당 최대 값을 찾고 데이터를 이진 원-핫 인코딩으로 변환하도록합니다.

>>> from sklearn.preprocessing import OneHotEncoder
>>> enc = OneHotEncoder()
>>> enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
OneHotEncoder(categorical_features='all', dtype=<class 'numpy.float64'>,
   handle_unknown='error', n_values='auto', sparse=True)
>>> enc.n_values_
array([2, 3, 4])
>>> enc.feature_indices_
array([0, 2, 5, 9], dtype=int32)
>>> enc.transform([[0, 1, 1]]).toarray()
array([[ 1.,  0.,  0.,  1.,  0.,  0.,  1.,  0.,  0.]])

다음은이 예제에 대한 링크입니다. http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html


답변

기본 원-핫 인코딩에 Pandas를 훨씬 쉽게 사용할 수 있습니다. 더 많은 옵션을 찾고 있다면 scikit-learn.

Pandas 를 사용한 기본 원-핫 인코딩 의 경우 데이터 프레임을 get_dummies 함수에 전달하기 만하면 됩니다.

예를 들어 imdb_movies 라는 데이터 프레임이있는 경우 :

여기에 이미지 설명 입력

… 그리고 Rated 열을 원-핫 인코딩하고 싶습니다. 간단히 이렇게합니다.

pd.get_dummies(imdb_movies.Rated)

여기에 이미지 설명 입력

이것은 존재하는 평가의 dataframe모든 ” 수준 “에 대한 열 이있는 새 항목 을 반환하고 주어진 관찰에 대해 해당 평가의 존재를 지정하는 1 또는 0을 함께 반환합니다 .

일반적으로 우리는 이것이 원본의 일부가되기를 원합니다 dataframe. 이 경우 ” column-binding을 사용하여 새 더미 코딩 된 프레임을 원래 프레임에 연결하기 만하면 됩니다 .

Pandas concat 함수 를 사용하여 열 바인딩 할 수 있습니다 .

rated_dummies = pd.get_dummies(imdb_movies.Rated)
pd.concat([imdb_movies, rated_dummies], axis=1)

여기에 이미지 설명 입력

이제 전체 dataframe.

간단한 유틸리티 기능

이 작업을 빠르게 수행하려면 유틸리티 함수 로 만드는 것이 좋습니다 .

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    return(res)

사용법 :

encode_and_bind(imdb_movies, 'Rated')

결과 :

여기에 이미지 설명 입력

또한 @pmalbu 주석에 따라 원래 feature_to_encode제거하는 함수를 원한다면 이 버전을 사용하십시오.

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res) 

다음과 같이 여러 기능을 동시에 인코딩 할 수 있습니다.

features_to_encode = ['feature_1', 'feature_2', 'feature_3',
                      'feature_4']
for feature in features_to_encode:
    res = encode_and_bind(train_set, feature)


답변

numpy.eye배열 요소 선택 메커니즘을 사용하여 수행 할 수 있습니다 .

import numpy as np
nb_classes = 6
data = [[2, 3, 4, 0]]

def indices_to_one_hot(data, nb_classes):
    """Convert an iterable of indices to one-hot encoded labels."""
    targets = np.array(data).reshape(-1)
    return np.eye(nb_classes)[targets]

의 반환 값 indices_to_one_hot(nb_classes, data)은 이제

array([[[ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 1.,  0.,  0.,  0.,  0.,  0.]]])

.reshape(-1)(당신이 또한있을 수 있습니다 당신이 올바른 라벨 형식이 존재하는 것입니다 [[2], [3], [4], [0]]).


답변

첫째, 핫 인코딩을하는 가장 쉬운 방법은 Sklearn을 사용하는 것입니다.

http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

둘째, 팬더를 하나의 핫 인코딩에 사용하는 것이 그렇게 간단하다고 생각하지 않습니다 (확인되지 ​​않음)

Python 용 Pandas에서 더미 변수 만들기

마지막으로 핫 인코딩이 필요합니까? 하나의 핫 인코딩은 기능의 수를 기하 급수적으로 증가시켜 분류기 또는 실행하려는 다른 항목의 실행 시간을 대폭 증가시킵니다. 특히 각 범주 기능에 여러 수준이있을 때. 대신 더미 코딩을 할 수 있습니다.

더미 인코딩을 사용하면 일반적으로 실행 시간과 복잡성이 훨씬 줄어들어 잘 작동합니다. 한 현명한 교수가 ‘적은 것이 더 많다’고 말했습니다.

원하는 경우 내 사용자 지정 인코딩 기능에 대한 코드는 다음과 같습니다.

from sklearn.preprocessing import LabelEncoder

#Auto encodes any dataframe column of type category or object.
def dummyEncode(df):
        columnsToEncode = list(df.select_dtypes(include=['category','object']))
        le = LabelEncoder()
        for feature in columnsToEncode:
            try:
                df[feature] = le.fit_transform(df[feature])
            except:
                print('Error encoding '+feature)
        return df

편집 : 더 명확하게 비교 :

원-핫 인코딩 : n 레벨을 n-1 열로 변환합니다.

Index  Animal         Index  cat  mouse
  1     dog             1     0     0
  2     cat       -->   2     1     0
  3    mouse            3     0     1

범주 기능에 여러 유형 (또는 수준)이있는 경우 이것이 어떻게 메모리를 폭발 시킬지 알 수 있습니다. 이것은 하나의 열에 불과합니다.

더미 코딩 :

Index  Animal         Index  Animal
  1     dog             1      0
  2     cat       -->   2      1
  3    mouse            3      2

대신 수치 표현으로 변환하십시오. 약간의 정확성을 희생하면서 기능 공간을 크게 절약합니다.


답변

팬더를 사용한 핫 인코딩은 매우 쉽습니다.

def one_hot(df, cols):
    """
    @param df pandas DataFrame
    @param cols a list of columns to encode
    @return a DataFrame with one-hot encoding
    """
    for each in cols:
        dummies = pd.get_dummies(df[each], prefix=each, drop_first=False)
        df = pd.concat([df, dummies], axis=1)
    return df

편집하다:

sklearn을 사용하는 one_hot의 또 다른 방법 LabelBinarizer:

from sklearn.preprocessing import LabelBinarizer
label_binarizer = LabelBinarizer()
label_binarizer.fit(all_your_labels_list) # need to be global or remembered to use it later

def one_hot_encode(x):
    """
    One hot encode a list of sample labels. Return a one-hot encoded vector for each label.
    : x: List of sample Labels
    : return: Numpy array of one-hot encoded labels
    """
    return label_binarizer.transform(x)


답변

numpy.eye 함수를 사용할 수 있습니다.

import numpy as np

def one_hot_encode(x, n_classes):
    """
    One hot encode a list of sample labels. Return a one-hot encoded vector for each label.
    : x: List of sample Labels
    : return: Numpy array of one-hot encoded labels
     """
    return np.eye(n_classes)[x]

def main():
    list = [0,1,2,3,4,3,2,1,0]
    n_classes = 5
    one_hot_list = one_hot_encode(list, n_classes)
    print(one_hot_list)

if __name__ == "__main__":
    main()

결과

D:\Desktop>python test.py
[[ 1.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.]
 [ 0.  0.  1.  0.  0.]
 [ 0.  0.  0.  1.  0.]
 [ 0.  0.  0.  0.  1.]
 [ 0.  0.  0.  1.  0.]
 [ 0.  0.  1.  0.  0.]
 [ 0.  1.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.]]


답변

pandas는 “get_dummies”함수를 내장하여 특정 열의 핫 인코딩을 가져옵니다.

원-핫 인코딩을위한 한 줄 코드 :

df=pd.concat([df,pd.get_dummies(df['column name'],prefix='column name')],axis=1).drop(['column name'],axis=1)