赞
踩
One-hot编码也叫独热编码,又称一位有效编码。方法就是用N位对N个状态进行表示,但是其中只有一位为1,剩下N-1位全为0。例如,特征为性别,就需要变成10和01。
在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的。而常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。使用独热编码(One-Hot Encoding),将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用独热编码(One-Hot Encoding),会让特征之间的距离计算更加合理。
举个例子,如果我们现在一个特征有五个取值,如果不采用One-Hot编码,则分别表示为演员=0,厨师=1,公务员=2,教师=3,律师=4,那么教师和厨师的距离为2,律师与厨师的距离为3,这显然是不合理的。比较合理的做法是将两个工作之间的距离表示为sqrt(2),即两个工作之间的距离是一样的。
总结一下,如果特征的大小表示如果有意义的话,比如我们用1-9表示年龄,这种特征的大小表示就是有意义的,所以这种情况下就不需要进行One-Hot编码;如果特征的大小没有意义,仅仅表示状态时则使用One-Hot编码。
pandas实现:首先对f3这个特征做One-Hot编码,接着将生成的df和原来的df进行拼接,最后删除原来的f3特征
df = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69] ], columns=['id', 'gender', 'age'] ) # step 1: using get_dummies to encode feature dummy_df = pd.get_dummies(df["gender"]) # step 2: concat dummy_df with original df df = pd.concat((df, dummy_df), axis=1) # step 3: remove original feature df = df.drop("gender", axis=1) # simplified form # df = pd.concat((df, pd.get_dummies(df["gender"])), axis=1) # df = df.drop("gender", axis=1)
存在问题:
df = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69] ], columns=['id', 'gender', 'age'] ) # step 1: using get_dummies to encode feature dummy_df = pd.get_dummies(df["gender"], drop_first=True) # step 2: concat dummy_df with original df df = pd.concat((df, dummy_df), axis=1) # step 3: remove original feature df = df.drop("gender", axis=1) # simplified form # df = pd.concat((df, pd.get_dummies(df["gender"], drop_first=True)), axis=1) # df = df.drop("gender", axis=1)
train = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69] ], columns=['id', 'gender', 'age'] ) test = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69], [1003, "unknown", 88] ], columns=['id', 'gender', 'age'] ) train = pd.concat((train, pd.get_dummies(train["gender"], drop_first=True)), axis=1) train.drop("gender", axis=1) test = pd.concat((test, pd.get_dummies(test["gender"], drop_first=True)), axis=1) test.drop("gender", axis=1) for col in list(test.columns.difference(train.columns)):#train没有的列 df_obj = pd.DataFrame({col:np.squeeze(np.zeros((1,train.shape[0])))}) train = pd.concat([train,df_obj], axis=1) for col in list(train.columns.difference(test.columns)):#test没有的列 df_obj = pd.DataFrame({col:np.squeeze(np.zeros((1,test.shape[0])))}) test = pd.concat([test,df_obj], axis=1)
sklearn实现:
from sklearn.preprocessing import OneHotEncoder train = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69] ], columns=['id', 'gender', 'age'] ) test = pd.DataFrame( [ [1000, "male", 23], [1001, "female", 22], [1002, "male", 69], [1003, "unknown", 88] ], columns=['id', 'gender', 'age'] ) # drop:k-1 to represent k; handle_unknown:for missing value encoder = OneHotEncoder(sparse=False, handle_unknown='ignore', drop="first") # fit enc = encoder.fit(train[["gender"]]) # 获取新列名 columns = enc.get_feature_names_out(["gender"]) # 转换测试数据 enc_arr = enc.transform(test[["gender"]]) # 生成dataframe enc_df = pd.DataFrame(enc_arr, columns=columns) new_data = pd.concat([test, enc_df], axis=1) new_data.drop(["gender"], axis=1, inplace=True) new_data
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。