Làm thế nào tôi có thể mã hóa nóng trong Python?


132

Tôi có một vấn đề phân loại học máy với 80% biến phân loại. Tôi phải sử dụng một mã hóa nóng nếu tôi muốn sử dụng một số phân loại để phân loại? Tôi có thể chuyển dữ liệu đến một bộ phân loại mà không cần mã hóa không?

Tôi đang cố gắng làm như sau để lựa chọn tính năng:

  1. Tôi đọc tập tin xe lửa:

    num_rows_to_read = 10000
    train_small = pd.read_csv("../../dataset/train.csv",   nrows=num_rows_to_read)
  2. Tôi thay đổi loại tính năng phân loại thành 'loại':

    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. Tôi sử dụng một mã hóa nóng:

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

Vấn đề là phần thứ 3 thường bị kẹt, mặc dù tôi đang sử dụng một máy mạnh.

Do đó, không có một mã hóa nóng nào, tôi không thể thực hiện bất kỳ lựa chọn tính năng nào, để xác định tầm quan trọng của các tính năng.

Bạn đề xuất món gì?

Câu trả lời:


159

Cách tiếp cận 1: Bạn có thể sử dụng get_dummies trên khung dữ liệu gấu trúc.

Ví dụ 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

Ví dụ 2:

Sau đây sẽ chuyển đổi một cột nhất định thành một nóng. Sử dụng tiền tố để có nhiều hình nộm.

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

Cách tiếp cận 2: Sử dụng Scikit-learn

Đưa ra một tập dữ liệu với ba tính năng và bốn mẫu, chúng tôi cho phép bộ mã hóa tìm giá trị tối đa cho mỗi tính năng và chuyển đổi dữ liệu thành mã hóa một lần nóng.

>>> 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.]])

Đây là liên kết cho ví dụ này: http://scikit-learn.org/urdy/modules/generated/sklearn.pre Processing.OneHotEncoder.html


20
thiết lập drop_first=Truevới get_dummiesloại bỏ sự cần thiết phải bỏ riêng cột ban đầu
Tràn tràn TheGlass

1
Trong ví dụ 2, có cách nào để nối các cột mới vào khung dữ liệu mà không cần sử dụng phép nối không? Tôi đang xử lý một bộ dữ liệu thực sự lớn và nhận MemoryError khi tôi cố gắng làm điều đó.
J.Dahlgren

Bạn có thể thêm cột mới vào khung dữ liệu mà không cần sử dụng phép nối nếu bạn có df2 với cùng một hàng. bạn có thể sao chép bằng cách sử dụng: df [Thời gian mớiColname] = df2 [
Lễ

1
Sử dụng một hình ảnh cho ví dụ 2 là xấu xa
biệt thự

9
@ OverflowingTheGlass- drop-first = True không xóa cột ban đầu. Nó giảm cấp độ đầu tiên của tính năng phân loại để bạn kết thúc với các cột k-1 thay vì các cột k, k là giá trị chính của tính năng phân loại.
Garima Jain

41

Dễ dàng hơn nhiều để sử dụng Pandas cho mã hóa một nóng cơ bản. Nếu bạn đang tìm kiếm nhiều lựa chọn hơn, bạn có thể sử dụng scikit-learn.

Đối với mã hóa một nóng cơ bản với Pandas, bạn chỉ cần chuyển khung dữ liệu của mình vào hàm get_dummies .

Ví dụ: nếu tôi có một khung dữ liệu được gọi là imdb_movies :

nhập mô tả hình ảnh ở đây

... và tôi muốn mã hóa một cột nóng, tôi chỉ cần làm điều này:

pd.get_dummies(imdb_movies.Rated)

nhập mô tả hình ảnh ở đây

Điều này trả về một điểm mới dataframevới một cột cho mỗi " mức " xếp hạng tồn tại, cùng với 1 hoặc 0 chỉ định sự hiện diện của xếp hạng đó cho một quan sát nhất định.

Thông thường, chúng tôi muốn đây là một phần của bản gốc dataframe. Trong trường hợp này, chúng tôi chỉ cần gắn khung mã hóa giả mới của chúng tôi vào khung ban đầu bằng cách sử dụng " liên kết cột .

Chúng ta có thể cột-ràng buộc bằng cách sử dụng Pandas concat chức năng:

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

nhập mô tả hình ảnh ở đây

Bây giờ chúng ta có thể chạy một phân tích trên đầy đủ của chúng tôi dataframe.

CHỨC NĂNG TIỆN ÍCH ĐƠN GIẢN

Tôi khuyên bạn nên tạo cho mình một chức năng tiện ích để thực hiện việc này một cách nhanh chóng:

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)

Cách sử dụng :

encode_and_bind(imdb_movies, 'Rated')

Kết quả :

nhập mô tả hình ảnh ở đây

Ngoài ra, theo nhận xét @pmalbu, nếu bạn muốn chức năng xóa tính năng gốc_to_encode thì hãy sử dụng phiên bản này:

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) 

Bạn có thể mã hóa nhiều tính năng cùng một lúc như sau:

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

1
Tôi sẽ đề nghị bỏ tính năng gốc_to_encode sau khi bạn ghép nối một cột kết thúc nóng với khung dữ liệu gốc.
pmalbu

Đã thêm tùy chọn này để trả lời. Cảm ơn.
Từ trường

28

Bạn có thể làm điều đó với numpy.eyevà sử dụng cơ chế chọn thành phần mảng:

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]

Giá trị trả về của indices_to_one_hot(nb_classes, data)bây giờ

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)để đảm bảo bạn có định dạng nhãn phù hợp (bạn cũng có thể có [[2], [3], [4], [0]]).


1
Điều này sẽ không hoạt động cho OHE của các cột có giá trị chuỗi.
Abhilash Awasthi

2
@AbhilashAwasthi Chắc chắn ... nhưng tại sao bạn lại mong đợi nó hoạt động?
Martin Thoma

22

Thứ nhất, cách dễ nhất để mã hóa nóng: sử dụng Sklearn.

http://scikit-learn.org/urdy/modules/generated/sklearn.pre Processing.OneHotEncoder.html

Thứ hai, tôi không nghĩ việc sử dụng gấu trúc cho một mã hóa nóng là đơn giản (mặc dù chưa được xác nhận)

Tạo các biến giả trong gấu trúc cho trăn

Cuối cùng, có cần thiết cho bạn một mã hóa nóng không? Một mã hóa nóng tăng theo cấp số nhân số lượng tính năng, tăng đáng kể thời gian chạy của bất kỳ trình phân loại hoặc bất kỳ thứ gì khác mà bạn sẽ chạy. Đặc biệt là khi mỗi tính năng phân loại có nhiều cấp độ. Thay vào đó bạn có thể làm mã hóa giả.

Sử dụng mã hóa giả thường hoạt động tốt, cho thời gian chạy và độ phức tạp ít hơn nhiều. Một giáo sư thông thái đã từng nói với tôi, 'Ít hơn là nhiều hơn'.

Đây là mã cho chức năng mã hóa tùy chỉnh của tôi nếu bạn muốn.

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

EDIT: So sánh để rõ ràng hơn:

Mã hóa một nóng: chuyển đổi n cấp thành cột n-1.

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

Bạn có thể thấy điều này sẽ bùng nổ bộ nhớ của bạn như thế nào nếu bạn có nhiều loại (hoặc cấp độ) khác nhau trong tính năng phân loại của bạn. Hãy ghi nhớ, đây chỉ là MỘT cột.

Mã hóa giả:

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

Chuyển đổi sang đại diện số thay thế. Tuyệt vời tiết kiệm không gian tính năng, với chi phí của một chút chính xác.


1
1. Tôi có một bộ dữ liệu có 80% biến phân loại. Theo hiểu biết của tôi, tôi phải sử dụng một mã hóa nóng nếu tôi muốn sử dụng một trình phân loại cho dữ liệu này, trong trường hợp không thực hiện một mã hóa nóng, trình phân loại sẽ không xử lý các biến phân loại theo cách chính xác? Có một tùy chọn không mã hóa? 2. Nếu tôi sử dụng pd.get_dummies (train_small, spzzy = True) với saprse = True - không giải quyết được vấn đề bộ nhớ? 3. Làm thế nào tôi nên tiếp cận một vấn đề như vậy?
avicohen

Như tôi đã nói, có hai lựa chọn. 1) Một mã hóa nóng -> chuyển đổi mọi cấp độ trong các tính năng phân loại sang một cột mới. 2) Mã hóa giả -> chuyển đổi mọi cột thành biểu diễn số. Tôi sẽ chỉnh sửa câu trả lời của tôi ở trên để rõ ràng hơn. Nhưng bạn chỉ có thể chạy chức năng tôi cung cấp và nó sẽ hoạt động
Wboy

17
"với chi phí của một chút chính xác." Làm thế nào bạn có thể nói "một chút"? Có thể trong một số trường hợp, nhưng trong những trường hợp khác, độ chính xác có thể bị tổn thương rất nhiều. Giải pháp này dẫn đến việc xử lý các tính năng định tính là liên tục, điều đó có nghĩa là mô hình của bạn sẽ không học được từ dữ liệu đúng cách.
Josh Morel

2
Như Josh đã nói ở trên, trong ví dụ thứ hai của bạn, cuối cùng bạn nói với người mẫu rằng mouse > cat > dognhưng đây không phải là trường hợp. get_dummieslà cách đơn giản nhất để chuyển các biến phân loại thành dữ liệu thân thiện với mô hình từ kinh nghiệm của tôi (mặc dù rất hạn chế)
Martin O Leary

5
Giải pháp này rất nguy hiểm như được chỉ ra bởi một số ý kiến ​​khác. Nó tự ý gán các đơn đặt hàng và khoảng cách cho các biến phân loại. Làm như vậy làm giảm tính linh hoạt của mô hình một cách ngẫu nhiên. Đối với các mô hình dựa trên cây, mã hóa như vậy làm giảm khả năng đặt lại có thể. Ví dụ: bạn chỉ có thể nhận được hai mối nối có thể ngay bây giờ [(0), (1,2)] và [(0,1), (2)] và phân tách [(0,2), (1)] là Không thể nào. Sự mất mát có ý nghĩa hơn nhiều khi số lượng danh mục cao.
Sự chắc chắn ngẫu nhiên

19

Một mã hóa nóng với gấu trúc rất dễ dàng:

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

BIÊN TẬP:

Một cách khác để one_hot sử dụng sklearn 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)

14

Bạn có thể sử dụng hàm 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()

Kết quả

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.]]

2
Bạn vừa sao chép câu trả lời của tôi?
Martin Thoma

@Martin Thoma - Tôi nghĩ rằng, tôi đã không
Dieter

5

gấu trúc có chức năng "get_dummies" để có được một mã hóa nóng của cột / s cụ thể đó.

mã một dòng cho mã hóa một nóng:

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

4

Đây là một giải pháp sử dụng DictVectorizerDataFrame.to_dict('records')phương pháp Pandas .

>>> import pandas as pd
>>> X = pd.DataFrame({'income': [100000,110000,90000,30000,14000,50000],
                      'country':['US', 'CAN', 'US', 'CAN', 'MEX', 'US'],
                      'race':['White', 'Black', 'Latino', 'White', 'White', 'Black']
                     })

>>> from sklearn.feature_extraction import DictVectorizer
>>> v = DictVectorizer()
>>> qualitative_features = ['country','race']
>>> X_qual = v.fit_transform(X[qualitative_features].to_dict('records'))
>>> v.vocabulary_
{'country=CAN': 0,
 'country=MEX': 1,
 'country=US': 2,
 'race=Black': 3,
 'race=Latino': 4,
 'race=White': 5}

>>> X_qual.toarray()
array([[ 0.,  0.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  1.,  0.],
       [ 1.,  0.,  0.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  0.,  0.,  1.],
       [ 0.,  0.,  1.,  1.,  0.,  0.]])

3

Mã hóa một nóng đòi hỏi nhiều hơn một chút so với chuyển đổi các giá trị thành các biến chỉ báo. Thông thường quy trình ML yêu cầu bạn áp dụng mã hóa này nhiều lần để xác thực hoặc kiểm tra các bộ dữ liệu và áp dụng mô hình bạn xây dựng cho dữ liệu được quan sát theo thời gian thực. Bạn nên lưu trữ ánh xạ (biến đổi) đã được sử dụng để xây dựng mô hình. Một giải pháp tốt sẽ sử dụng DictVectorizerhoặc LabelEncoder(theo sau get_dummies. Đây là một chức năng mà bạn có thể sử dụng:

def oneHotEncode2(df, le_dict = {}):
    if not le_dict:
        columnsToEncode = list(df.select_dtypes(include=['category','object']))
        train = True;
    else:
        columnsToEncode = le_dict.keys()   
        train = False;

    for feature in columnsToEncode:
        if train:
            le_dict[feature] = LabelEncoder()
        try:
            if train:
                df[feature] = le_dict[feature].fit_transform(df[feature])
            else:
                df[feature] = le_dict[feature].transform(df[feature])

            df = pd.concat([df, 
                              pd.get_dummies(df[feature]).rename(columns=lambda x: feature + '_' + str(x))], axis=1)
            df = df.drop(feature, axis=1)
        except:
            print('Error encoding '+feature)
            #df[feature]  = df[feature].convert_objects(convert_numeric='force')
            df[feature]  = df[feature].apply(pd.to_numeric, errors='coerce')
    return (df, le_dict)

Điều này hoạt động trên một khung dữ liệu gấu trúc và cho mỗi cột của khung dữ liệu mà nó tạo ra và trả về ánh xạ trở lại. Vì vậy, bạn sẽ gọi nó như thế này:

train_data, le_dict = oneHotEncode2(train_data)

Sau đó, trên dữ liệu thử nghiệm, cuộc gọi được thực hiện bằng cách chuyển từ điển trở lại từ đào tạo:

test_data, _ = oneHotEncode2(test_data, le_dict)

Một phương pháp tương đương là sử dụng DictVectorizer. Một bài viết liên quan trên cùng là trên blog của tôi. Tôi đề cập đến nó ở đây vì nó cung cấp một số lý do đằng sau cách tiếp cận này chỉ đơn giản là sử dụng bài đăng get_dummies (tiết lộ: đây là blog của riêng tôi).


3

Bạn có thể chuyển dữ liệu đến phân loại catboost mà không cần mã hóa. Catboost tự xử lý các biến phân loại bằng cách thực hiện mã hóa trung bình mở rộng một mục tiêu và mở rộng mục tiêu.


3

Bạn có thể làm như sau là tốt. Lưu ý cho những điều dưới đây bạn không phải sử dụng pd.concat.

import pandas as pd 
# intialise data of lists. 
data = {'Color':['Red', 'Yellow', 'Red', 'Yellow'], 'Length':[20.1, 21.1, 19.1, 18.1],
       'Group':[1,2,1,2]} 

# Create DataFrame 
df = pd.DataFrame(data) 

for _c in df.select_dtypes(include=['object']).columns:
    print(_c)
    df[_c]  = pd.Categorical(df[_c])
df_transformed = pd.get_dummies(df)
df_transformed

Bạn cũng có thể thay đổi các cột rõ ràng để phân loại. Ví dụ, ở đây tôi đang thay đổi ColorGroup

import pandas as pd 
# intialise data of lists. 
data = {'Color':['Red', 'Yellow', 'Red', 'Yellow'], 'Length':[20.1, 21.1, 19.1, 18.1],
       'Group':[1,2,1,2]} 

# Create DataFrame 
df = pd.DataFrame(data) 
columns_to_change = list(df.select_dtypes(include=['object']).columns)
columns_to_change.append('Group')
for _c in columns_to_change:
    print(_c)
    df[_c]  = pd.Categorical(df[_c])
df_transformed = pd.get_dummies(df)
df_transformed

2

Tôi biết tôi đến bữa tiệc muộn này, nhưng cách đơn giản nhất để mã hóa dữ liệu theo khung dữ liệu theo cách tự động là sử dụng chức năng này:

def hot_encode(df):
    obj_df = df.select_dtypes(include=['object'])
    return pd.get_dummies(df, columns=obj_df.columns).values

1

Tôi đã sử dụng điều này trong mô hình âm thanh của mình: có lẽ điều này giúp ích cho mô hình ur.

def one_hot_encoding(x, n_out):
    x = x.astype(int)  
    shape = x.shape
    x = x.flatten()
    N = len(x)
    x_categ = np.zeros((N,n_out))
    x_categ[np.arange(N), x] = 1
    return x_categ.reshape((shape)+(n_out,))

0

Để thêm vào các câu hỏi khác, hãy để tôi cung cấp cách tôi đã thực hiện với hàm Python 2.0 bằng Numpy:

def one_hot(y_):
    # Function to encode output labels from number indexes 
    # e.g.: [[5], [0], [3]] --> [[0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0]]

    y_ = y_.reshape(len(y_))
    n_values = np.max(y_) + 1
    return np.eye(n_values)[np.array(y_, dtype=np.int32)]  # Returns FLOATS

Dòng n_values = np.max(y_) + 1này có thể được mã hóa cứng để bạn sử dụng số lượng nơ-ron tốt trong trường hợp bạn sử dụng các lô nhỏ chẳng hạn.

Dự án demo / hướng dẫn sử dụng chức năng này: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition


0

Điều này làm việc cho tôi:

pandas.factorize( ['B', 'C', 'D', 'B'] )[0]

Đầu ra:

[0, 1, 2, 0]

0

Nó có thể và nó phải dễ dàng như:

class OneHotEncoder:
    def __init__(self,optionKeys):
        length=len(optionKeys)
        self.__dict__={optionKeys[j]:[0 if i!=j else 1 for i in range(length)] for j in range(length)}

Sử dụng :

ohe=OneHotEncoder(["A","B","C","D"])
print(ohe.A)
print(ohe.D)

0

Mở rộng câu trả lời của @Martin Thoma

def one_hot_encode(y):
    """Convert an iterable of indices to one-hot encoded labels."""
    y = y.flatten() # Sometimes not flattened vector is passed e.g (118,1) in these cases
    # the function ends up creating a tensor e.g. (118, 2, 1). flatten removes this issue
    nb_classes = len(np.unique(y)) # get the number of unique classes
    standardised_labels = dict(zip(np.unique(y), np.arange(nb_classes))) # get the class labels as a dictionary
    # which then is standardised. E.g imagine class labels are (4,7,9) if a vector of y containing 4,7 and 9 is
    # directly passed then np.eye(nb_classes)[4] or 7,9 throws an out of index error.
    # standardised labels fixes this issue by returning a dictionary;
    # standardised_labels = {4:0, 7:1, 9:2}. The values of the dictionary are mapped to keys in y array.
    # standardised_labels also removes the error that is raised if the labels are floats. E.g. 1.0; element
    # cannot be called by an integer index e.g y[1.0] - throws an index error.
    targets = np.vectorize(standardised_labels.get)(y) # map the dictionary values to array.
    return np.eye(nb_classes)[targets]

0

Câu trả lời ngắn

Đây là một chức năng để thực hiện mã hóa một nóng mà không cần sử dụng numpy, gấu trúc hoặc các gói khác. Nó nhận một danh sách các số nguyên, booleans hoặc chuỗi (và có lẽ các loại khác nữa).

import typing


def one_hot_encode(items: list) -> typing.List[list]:
    results = []
    # find the unique items (we want to unique items b/c duplicate items will have the same encoding)
    unique_items = list(set(items))
    # sort the unique items
    sorted_items = sorted(unique_items)
    # find how long the list of each item should be
    max_index = len(unique_items)

    for item in items:
        # create a list of zeros the appropriate length
        one_hot_encoded_result = [0 for i in range(0, max_index)]
        # find the index of the item
        one_hot_index = sorted_items.index(item)
        # change the zero at the index from the previous line to a one
        one_hot_encoded_result[one_hot_index] = 1
        # add the result
        results.append(one_hot_encoded_result)

    return results

Thí dụ:

one_hot_encode([2, 1, 1, 2, 5, 3])

# [[0, 1, 0, 0],
#  [1, 0, 0, 0],
#  [1, 0, 0, 0],
#  [0, 1, 0, 0],
#  [0, 0, 0, 1],
#  [0, 0, 1, 0]]
one_hot_encode([True, False, True])

# [[0, 1], [1, 0], [0, 1]]
one_hot_encode(['a', 'b', 'c', 'a', 'e'])

# [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [1, 0, 0, 0], [0, 0, 0, 1]]

Long (er) Trả lời

Tôi biết đã có rất nhiều câu trả lời cho câu hỏi này, nhưng tôi nhận thấy hai điều. Đầu tiên, hầu hết các câu trả lời sử dụng các gói như numpy và / hoặc gấu trúc. Và đây là một điều tốt. Nếu bạn đang viết mã sản xuất, có lẽ bạn nên sử dụng các thuật toán mạnh mẽ, nhanh chóng như các thuật toán được cung cấp trong các gói numpy / pandas. Nhưng, vì lợi ích của giáo dục, tôi nghĩ ai đó nên cung cấp một câu trả lời có thuật toán minh bạch và không chỉ là việc thực hiện thuật toán của người khác. Thứ hai, tôi nhận thấy rằng nhiều câu trả lời không cung cấp triển khai mạnh mẽ mã hóa một nóng vì chúng không đáp ứng một trong các yêu cầu dưới đây. Dưới đây là một số yêu cầu (như tôi thấy chúng) về chức năng mã hóa một nóng hữu ích, chính xác và mạnh mẽ:

Hàm mã hóa một nóng phải:

  • xử lý danh sách các loại khác nhau (ví dụ: số nguyên, chuỗi, số float, v.v.) làm đầu vào
  • xử lý một danh sách đầu vào với các bản sao
  • trả về một danh sách các danh sách tương ứng (theo thứ tự như) cho các đầu vào
  • trả về một danh sách các danh sách trong đó mỗi danh sách càng ngắn càng tốt

Tôi đã thử nghiệm nhiều câu trả lời cho câu hỏi này và hầu hết chúng đều thất bại ở một trong những yêu cầu trên.


0

Thử cái này:

!pip install category_encoders
import category_encoders as ce

categorical_columns = [...the list of names of the columns you want to one-hot-encode ...]
encoder = ce.OneHotEncoder(cols=categorical_columns, use_cat_names=True)
df_train_encoded = encoder.fit_transform(df_train_small)

df_encoding.head ()

Khung dữ liệu kết quả df_train_encoded giống như bản gốc, nhưng các tính năng phân loại hiện được thay thế bằng các phiên bản được mã hóa nóng.

Thêm thông tin category_encoders ở đây .


-1

Ở đây tôi đã thử với phương pháp này:

import numpy as np
#converting to one_hot





def one_hot_encoder(value, datal):

    datal[value] = 1

    return datal


def _one_hot_values(labels_data):
    encoded = [0] * len(labels_data)

    for j, i in enumerate(labels_data):
        max_value = [0] * (np.max(labels_data) + 1)

        encoded[j] = one_hot_encoder(i, max_value)

    return np.array(encoded)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.