參考:An Overview of Encoding Techniques | Kaggle
Method 1: Label encoding
給每個類別以一個數字label,作為分類。將類別對映到自然數數值空間上
from sklearn.preprocessing import LabelEncoder train=pd.DataFrame() label=LabelEncoder() for c in X.columns: if(X[c].dtype=='object'): train[c]=label.fit_transform(X[c]) else: train[c]=X[c]
Method 2 : One hot encoding
即獨熱碼,每一個category對應特徵向量中的一位,對應位置是否為1判定是否為該類。
可以使用pd.get_dummies()或sklearn.preprocessing中OneHotEncoder
from sklearn.preprocessing import OneHotEncoder one=OneHotEncoder( one.fit(X) train=one.transform(X)
Method 3 : Feature Hashing/Hashing Trick
一個“one hot encoding style” 的編碼方式,將資料編入特定維數的散度矩陣中,降維中使用了hash方法。
from sklearn.feature_extraction import FeatureHasher X_train_hash=X.copy() for c in X.columns: X_train_hash[c]=X[c].astype('str') hashing=FeatureHasher(input_type='string') train=hashing.transform(X_train_hash.values)
Method 4 :Encoding categories with dataset statistics
嘗試為模型提供較低維的每個類別的表示,且其中類似的類別的表示相近。 最簡單的方法是將每個類別替換為我們在資料集中看到它的次數,即用出現頻率作為他們的embedding。
X_train_stat=X.copy() for c in X_train_stat.columns: if(X_train_stat[c].dtype=='object'): X_train_stat[c]=X_train_stat[c].astype('category') counts=X_train_stat[c].value_counts() counts=counts.sort_index() counts=counts.fillna(0) counts += np.random.rand(len(counts))/1000 X_train_stat[c].cat.categories=counts
對於迴圈出現的特徵,例如日期,星期等,常用sin\cos將其轉為二維空間中的資料。這是基於“迴圈”的性質,類似於對圓進行分割。
X_train_cyclic=X.copy() columns=['day','month'] for col in columns: X_train_cyclic[col+'_sin']=np.sin((2*np.pi*X_train_cyclic[col])/max(X_train_cyclic[col])) X_train_cyclic[col+'_cos']=np.cos((2*np.pi*X_train_cyclic[col])/max(X_train_cyclic[col])) X_train_cyclic=X_train_cyclic.drop(columns,axis=1)
one=OneHotEncoder()
one.fit(X_train_cyclic)
train=one.transform(X_train_cyclic)
Method 5 : Target encoding
Target encoding 通過目標資料對類別變數進行編碼,使用目標對應概率或平均概率替換該類別,即出現頻次相近的被視為同一類(大城市,熱門項等)。這個方法比較依賴訓練集與測試集合的分佈,要求他們資料分佈一致。另外,這種方法可能會導致過擬合。
X_target=df_train.copy() X_target['day']=X_target['day'].astype('object') X_target['month']=X_target['month'].astype('object') for col in X_target.columns: if (X_target[col].dtype=='object'): target= dict ( X_target.groupby(col)['target'].agg('sum')/X_target.groupby(col)['target'].agg('count')) X_target[col]=X_target[col].replace(target).values
為了減輕過擬合可能帶來的影響,可以使用K-Fold Validation ,每次對一份樣本進行目標編碼時,使用的都是其他K-1份資料之中的資料。
X['target']=y cols=X.drop(['target','id'],axis=1).columns %%time X_fold=X.copy() X_fold[['ord_0','day','month']]=X_fold[['ord_0','day','month']].astype('object') X_fold[['bin_3','bin_4']]=X_fold[['bin_3','bin_4']].replace({'Y':1,'N':0,'T':1,"F":0}) kf = KFold(n_splits = 5, shuffle = False, random_state=2019) for train_ind,val_ind in kf.split(X): for col in cols: if(X_fold[col].dtype=='object'): replaced=dict(X.iloc[train_ind][[col,'target']].groupby(col)['target'].mean()) X_fold.loc[val_ind,col]=X_fold.iloc[val_ind][col].replace(replaced).values
此外,在對特徵進行編碼前也需要進行特徵種類的區分。常分為:
- 0-1數值:只有兩種取值,可對映到0,1
- 類別數值:多個類別,這也是最常見的資料。
- 時序資料:時間戳等,隱含了順序資訊,可以反應趨勢。