ฉันจะเข้ารหัสร้อนใน Python ได้อย่างไร


133

ฉันมีปัญหาการจัดหมวดหมู่แมชชีนเลิร์นนิงที่มีตัวแปรตามหมวดหมู่ 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)

ปัญหาคือส่วนที่ 3 มักจะติดขัดแม้ว่าฉันจะใช้เครื่องแรง

ดังนั้นหากไม่มีการเข้ารหัสที่ร้อนแรงฉันไม่สามารถทำการเลือกคุณสมบัติใด ๆ เพื่อกำหนดความสำคัญของคุณสมบัติได้

คุณแนะนำเมนูใด?

คำตอบ:


159

แนวทางที่ 1: คุณสามารถใช้ 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

ด้วยชุดข้อมูลที่มีคุณลักษณะสามอย่างและสี่ตัวอย่างเราจึงปล่อยให้ตัวเข้ารหัสค้นหาค่าสูงสุดต่อคุณลักษณะและแปลงข้อมูลเป็นการเข้ารหัสแบบไบนารีแบบ one-hot

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


20
การตั้งค่าdrop_first=Trueโดยไม่get_dummiesจำเป็นต้องวางคอลัมน์เดิมแยกต่างหาก
OverflowTheGlass

1
ในตัวอย่างที่ 2 มีวิธีเข้าร่วมคอลัมน์ใหม่กับดาต้าเฟรมโดยไม่ใช้การเข้าร่วมหรือไม่ ฉันกำลังจัดการกับชุดข้อมูลขนาดใหญ่มากและได้รับ MemoryError เมื่อฉันพยายามทำเช่นนั้น
J.Dahlgren

คุณสามารถเพิ่มคอลัมน์ใหม่ใน dataframe โดยไม่ต้องใช้ join ถ้าคุณมี df2 ที่ไม่มีแถวเท่ากัน คุณสามารถคัดลอกโดยใช้: df [“ newColname”] = df2 [“ col”]
Sayali Sonawane

1
การใช้ภาพตัวอย่างที่ 2 เป็นสิ่งชั่วร้าย
Villasv

10
@ OverflowTheGlass- drop-first = True ไม่ลบคอลัมน์เดิม จะลดระดับแรกของคุณลักษณะหมวดหมู่เพื่อให้คุณลงเอยด้วยคอลัมน์ k-1 แทนที่จะเป็นคอลัมน์ k โดย k เป็นจำนวนสมาชิกของคุณลักษณะเชิงหมวดหมู่
Garima Jain

43

ง่ายกว่ามากในการใช้ Pandas สำหรับการเข้ารหัสแบบ one-hot ขั้นพื้นฐาน หากคุณกำลังมองหาตัวเลือกเพิ่มเติมที่คุณสามารถscikit-learnใช้ได้

สำหรับการเข้ารหัสแบบ one-hot ขั้นพื้นฐานด้วยPandasคุณเพียงแค่ส่ง data frame ไปยังฟังก์ชันget_dummies

ตัวอย่างเช่นถ้าฉันมี dataframe ชื่อimdb_movies :

ใส่คำอธิบายภาพที่นี่

... และฉันต้องการเข้ารหัสคอลัมน์ที่ได้รับการจัดอันดับแบบร้อนแรงฉันทำสิ่งนี้:

pd.get_dummies(imdb_movies.Rated)

ใส่คำอธิบายภาพที่นี่

สิ่งนี้จะส่งคืนใหม่dataframeพร้อมคอลัมน์สำหรับทุกระดับ " ระดับ " ที่มีอยู่พร้อมกับ 1 หรือ 0 ที่ระบุการมีอยู่ของการให้คะแนนนั้นสำหรับการสังเกตที่ระบุ

dataframeปกติเราอยากให้เรื่องนี้เป็นส่วนหนึ่งของเดิม ในกรณีนี้เราก็แนบหุ่นรหัสกรอบใหม่ของเราลงในกรอบเดิมที่ใช้ " คอลัมน์ที่มีผลผูกพัน

เราสามารถผูกคอลัมน์ได้โดยใช้ฟังก์ชัน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)

1
ฉันขอแนะนำให้ทิ้ง feature_to_encode เดิมหลังจากที่คุณเชื่อมต่อคอลัมน์ที่สิ้นสุดร้อนหนึ่งคอลัมน์กับดาต้าเฟรมเดิม
pmalbu

เพิ่มตัวเลือกนี้เพื่อตอบ ขอบคุณ
Cybernetic

28

คุณสามารถทำได้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]])


1
สิ่งนี้จะใช้ไม่ได้กับ OHE ของคอลัมน์ที่มีค่าสตริง
Abhilash Awasthi

2
@AbhilashAwasthi แน่นอน ... แต่ทำไมคุณถึงคาดหวังว่ามันจะทำงาน?
Martin Thoma

22

ประการแรกวิธีที่ง่ายที่สุดในการเข้ารหัสแบบร้อน: ใช้ Sklearn

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

ประการที่สองฉันไม่คิดว่าการใช้แพนด้ากับการเข้ารหัสร้อนเดียวนั้นง่ายขนาดนั้น (ยังไม่ได้รับการยืนยัน)

การสร้างตัวแปรดัมมี่ในแพนด้าสำหรับ python

สุดท้ายนี้จำเป็นสำหรับคุณที่จะต้องเข้ารหัสแบบร้อนครั้งเดียวหรือไม่? การเข้ารหัสแบบร้อนหนึ่งรายการจะเพิ่มจำนวนคุณลักษณะอย่างมากเพิ่มเวลาการทำงานของตัวจำแนกหรือสิ่งอื่น ๆ ที่คุณกำลังจะเรียกใช้อย่างมาก โดยเฉพาะอย่างยิ่งเมื่อคุณลักษณะที่เป็นหมวดหมู่มีหลายระดับ แต่คุณสามารถเขียนโค้ดหลอก

การใช้การเข้ารหัสแบบดัมมี่มักจะทำงานได้ดีโดยใช้เวลาและความซับซ้อนน้อยลงมาก ศาสตราจารย์ที่ชาญฉลาดเคยบอกฉันว่า 'Less is More'

นี่คือรหัสสำหรับฟังก์ชันการเข้ารหัสที่กำหนดเองของฉันหากคุณต้องการ

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

คุณสามารถดูว่าสิ่งนี้จะระเบิดความทรงจำของคุณได้อย่างไรหากคุณมีหลายประเภท (หรือระดับ) ในคุณลักษณะหมวดหมู่ของคุณ โปรดทราบว่านี่เป็นเพียงหนึ่งคอลัมน์

การเข้ารหัส Dummy:

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

แปลงเป็นการแสดงตัวเลขแทน ประหยัดพื้นที่ฟีเจอร์อย่างมากโดยเสียค่าใช้จ่ายเล็กน้อย


1
1. ฉันมีชุดข้อมูลที่มีตัวแปรเชิงหมวด 80% ตามความเข้าใจของฉันฉันต้องใช้การเข้ารหัสแบบร้อนหนึ่งรายการหากฉันต้องการใช้ตัวจำแนกสำหรับข้อมูลนี้มิฉะนั้นในกรณีที่ไม่ทำการเข้ารหัสแบบร้อนตัวลักษณนามจะไม่ปฏิบัติต่อตัวแปรจัดหมวดหมู่ในวิธีที่ถูกต้อง? มีตัวเลือกที่จะไม่เข้ารหัสหรือไม่? 2. ถ้าฉันใช้ pd.get_dummies (train_small, sparse = True) กับ saprse = True - นั่นจะไม่ช่วยแก้ปัญหาหน่วยความจำได้หรือไม่? 3. ฉันจะแก้ไขปัญหาดังกล่าวได้อย่างไร?
avicohen

อย่างที่บอกมีสองทางเลือก 1) การเข้ารหัสร้อนหนึ่งรายการ -> แปลงทุกระดับในคุณสมบัติหมวดหมู่เป็นคอลัมน์ใหม่ 2) การเข้ารหัส Dummy -> แปลงทุกคอลัมน์เป็นการแสดงตัวเลข ฉันจะแก้ไขคำตอบด้านบนให้ชัดเจนขึ้น แต่คุณสามารถเรียกใช้ฟังก์ชันที่ฉันให้มาและมันควรจะใช้งานได้
Wboy

17
"ในราคาที่ถูกต้อง" คุณพูดว่า "สักหน่อย" ได้อย่างไร? บางทีในบางกรณี แต่ในบางกรณีความแม่นยำอาจทำร้ายได้มาก โซลูชันนี้ส่งผลให้การปฏิบัติต่อคุณลักษณะเชิงคุณภาพเป็นไปอย่างต่อเนื่องซึ่งหมายความว่าโมเดลของคุณจะเรียนรู้จากข้อมูลไม่ถูกต้อง
Josh Morel

2
ดังที่ Josh ได้กล่าวไว้ข้างต้นในตัวอย่างที่สองของคุณคุณจะต้องบอกนางแบบว่าmouse > cat > dogแต่นี่ไม่ใช่กรณี get_dummiesเป็นวิธีที่ตรงไปตรงมาที่สุดในการถ่ายโอนตัวแปรเชิงหมวดหมู่ไปยังข้อมูลที่เป็นมิตรกับโมเดลจากประสบการณ์ของฉัน (แม้ว่าจะมีข้อ จำกัด มากก็ตาม)
Martin O Leary

5
วิธีนี้อันตรายมากตามที่แสดงความคิดเห็นอื่น ๆ กำหนดคำสั่งและระยะทางโดยพลการให้กับตัวแปรหมวดหมู่ การทำเช่นนี้จะลดความยืดหยุ่นของโมเดลในลักษณะสุ่ม สำหรับโมเดลแบบต้นไม้การเข้ารหัสดังกล่าวจะช่วยลดความเป็นไปได้ในการย่อยที่เป็นไปได้ ตัวอย่างเช่นตอนนี้คุณสามารถรับการต่อได้สองแบบเท่านั้นคือ [(0), (1,2)] และ [(0,1), (2)] และการแยก [(0,2), (1)] คือ เป็นไปไม่ได้ การสูญเสียมีความสำคัญมากขึ้นเมื่อจำนวนหมวดหมู่สูง
Random Certainty

19

การเข้ารหัสที่ร้อนแรงด้วยแพนด้านั้นง่ายมาก:

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

แก้ไข:

อีกวิธีหนึ่งในการ one_hot โดยใช้ sklearn's 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

คุณสามารถใช้ฟังก์ชัน 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.]]

2
คุณเพิ่งคัดลอกคำตอบของฉันหรือไม่?
Martin Thoma

@Martin Thoma - ฉันคิดว่าฉันไม่ได้
Dieter

5

แพนด้าตามที่มีฟังก์ชัน inbuilt "get_dummies" เพื่อรับการเข้ารหัสร้อนหนึ่งคอลัมน์ / วินาทีนั้น

รหัสบรรทัดเดียวสำหรับการเข้ารหัสแบบร้อนเดียว:

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

4

นี่คือวิธีแก้ปัญหาโดยใช้DictVectorizerและDataFrame.to_dict('records')วิธีการของนุ่น

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

การเข้ารหัสแบบ one-hot ต้องการบิตมากกว่าการแปลงค่าเป็นตัวแปรตัวบ่งชี้ โดยปกติกระบวนการ ML กำหนดให้คุณใช้การเข้ารหัสนี้หลายครั้งเพื่อตรวจสอบความถูกต้องหรือทดสอบชุดข้อมูลและใช้แบบจำลองที่คุณสร้างกับข้อมูลที่สังเกตได้แบบเรียลไทม์ คุณควรจัดเก็บการแมป (การแปลง) ที่ใช้ในการสร้างโมเดล ทางออกที่ดีควรใช้DictVectorizerหรือLabelEncoder(ตามด้วยget_dummiesนี่คือฟังก์ชันที่คุณสามารถใช้ได้:

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)

สิ่งนี้ใช้ได้กับดาต้าเฟรมของแพนด้าและสำหรับแต่ละคอลัมน์ของดาต้าเฟรมที่สร้างและส่งคืนการแมปกลับ คุณจะเรียกมันว่า:

train_data, le_dict = oneHotEncode2(train_data)

จากนั้นในข้อมูลการทดสอบจะทำการโทรโดยส่งพจนานุกรมที่ส่งคืนจากการฝึกอบรม:

test_data, _ = oneHotEncode2(test_data, le_dict)

DictVectorizerวิธีการที่เทียบเท่ากับการใช้งาน โพสต์ที่เกี่ยวข้องในเรื่องเดียวกันอยู่ในบล็อกของฉัน ฉันพูดถึงที่นี่เนื่องจากมีเหตุผลบางอย่างที่อยู่เบื้องหลังวิธีนี้โดยใช้เพียงแค่โพสต์ get_dummies (การเปิดเผย: นี่คือบล็อกของฉันเอง)


3

คุณสามารถส่งข้อมูลไปยัง catboost classifier โดยไม่ต้องเข้ารหัส Catboost จัดการตัวแปรตามหมวดหมู่ด้วยตัวเองโดยดำเนินการเข้ารหัสค่าเฉลี่ยแบบร้อนและขยายเป้าหมาย


3

คุณสามารถทำสิ่งต่อไปนี้ได้เช่นกัน 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

คุณยังสามารถเปลี่ยนคอลัมน์ที่โจ่งแจ้งเป็นหมวดหมู่ได้ ตัวอย่างเช่นที่นี่ฉันกำลังเปลี่ยนColorและGroup

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

ฉันรู้ว่าฉันมาสายปาร์ตี้นี้ แต่วิธีที่ง่ายที่สุดในการเข้ารหัสดาต้าเฟรมด้วยวิธีอัตโนมัติคือการใช้ฟังก์ชันนี้:

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

1

ฉันใช้สิ่งนี้ในโมเดลอะคูสติกของฉันซึ่งอาจช่วยได้ในแบบจำลองของคุณ

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

หากต้องการเพิ่มคำถามอื่น ๆ ให้ฉันระบุว่าฉันทำอย่างไรกับฟังก์ชัน Python 2.0 โดยใช้ 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

บรรทัดn_values = np.max(y_) + 1นี้อาจกำหนดให้คุณใช้จำนวนเซลล์ประสาทได้ดีในกรณีที่คุณใช้มินิแบทช์

โครงการสาธิต / บทช่วยสอนที่ใช้ฟังก์ชันนี้: https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition



0

ทำได้และควรจะง่ายเช่น:

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)}

การใช้งาน:

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

0

ขยายคำตอบของ @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

คำตอบสั้น ๆ

นี่คือฟังก์ชั่นในการเข้ารหัสแบบ hot-encoding โดยไม่ต้องใช้ numpy, pandas หรือแพ็คเกจอื่น ๆ รายการจำนวนเต็มบูลีนหรือสตริง (และอาจเป็นประเภทอื่น ๆ ด้วย)

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

ตัวอย่าง:

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

คำตอบยาว (เอ่อ)

ฉันรู้ว่ามีคำตอบมากมายสำหรับคำถามนี้ แต่ฉันสังเกตเห็นสองสิ่ง อันดับแรกคำตอบส่วนใหญ่ใช้แพ็กเกจเช่น numpy และ / หรือ pandas และนี่เป็นสิ่งที่ดี หากคุณกำลังเขียนโค้ดการผลิตคุณน่าจะใช้อัลกอริทึมที่รวดเร็วและแข็งแกร่งเช่นเดียวกับที่มีให้ในแพ็คเกจ numpy / pandas แต่เพื่อประโยชน์ในการศึกษาฉันคิดว่าใครบางคนควรให้คำตอบซึ่งมีอัลกอริทึมที่โปร่งใสไม่ใช่แค่การใช้อัลกอริทึมของคนอื่น ประการที่สองฉันสังเกตเห็นว่าคำตอบจำนวนมากไม่ได้นำเสนอการเข้ารหัสแบบร้อนแรงที่มีประสิทธิภาพเนื่องจากไม่ตรงตามข้อกำหนดด้านล่าง ด้านล่างนี้เป็นข้อกำหนดบางประการ (ตามที่ฉันเห็น) สำหรับฟังก์ชันการเข้ารหัสแบบ one-hot ที่มีประโยชน์ถูกต้องและมีประสิทธิภาพ:

ฟังก์ชันการเข้ารหัสแบบ one-hot ต้อง:

  • จัดการรายการประเภทต่างๆ (เช่นจำนวนเต็มสตริงลอย ฯลฯ ) เป็นอินพุต
  • จัดการรายการอินพุตที่มีรายการที่ซ้ำกัน
  • ส่งคืนลิสต์รายการที่เกี่ยวข้อง (ในลำดับเดียวกัน) ไปยังอินพุต
  • ส่งคืนรายการที่แต่ละรายการสั้นที่สุด

ฉันได้ทดสอบคำตอบหลายข้อสำหรับคำถามนี้และส่วนใหญ่ไม่ผ่านข้อกำหนดข้อใดข้อหนึ่งข้างต้น


0

ลองสิ่งนี้:

!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_encoded.head ()

ดาต้าเฟรมที่ได้df_train_encodedจะเหมือนกับต้นฉบับ แต่ตอนนี้คุณลักษณะที่เป็นหมวดหมู่จะถูกแทนที่ด้วยเวอร์ชันที่เข้ารหัสแบบฮอตฮิต

ข้อมูลเพิ่มเติมเกี่ยวกับที่นี่category_encoders


-1

ที่นี่ฉันลองใช้วิธีนี้:

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.