[特征工程] encoding
参考:An Overview of Encoding Techniques | Kaggle
Method 1: Label encoding
给每个类别以一个数字label,作为分类。将类别映射到自然数数值空间上
from 域名rocessing import LabelEncoder train=域名Frame() label=LabelEncoder() for c in 域名mns: if(X[c].dtype==\'object\'): train[c]=域名transform(X[c]) else: train[c]=X[c]
Method 2 : One hot encoding
即独热码,每一个category对应特征向量中的一位,对应位置是否为1判定是否为该类。
可以使用域名dummies()或域名rocessing中OneHotEncoder
from 域名rocessing import OneHotEncoder one=OneHotEncoder( 域名(X) train=域名sform(X)
Method 3 : Feature Hashing/Hashing Trick
一个“one hot encoding style” 的编码方式,将数据编入特定维数的散度矩阵中,降维中使用了hash方法。
from 域名ure_extraction import FeatureHasher X_train_hash=域名() for c in 域名mns: X_train_hash[c]=X[c].astype(\'str\') hashing=FeatureHasher(input_type=\'string\') train=域名sform(域名es)
Method 4 :Encoding categories with dataset statistics
尝试为模型提供较低维的每个类别的表示,且其中类似的类别的表示相近。 最简单的方法是将每个类别替换为我们在数据集中看到它的次数,即用出现频率作为他们的embedding。
X_train_stat=域名() for c in 域名mns: 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=域名_index() counts=域名na(0) counts += 域名(len(counts))/1000 X_train_stat[c].域名gories=counts
对于循环出现的特征,例如日期,星期等,常用sin\cos将其转为二维空间中的数据。这是基于“循环”的性质,类似于对圆进行分割。
X_train_cyclic=域名() columns=[\'day\',\'month\'] for col in columns: X_train_cyclic[col+\'_sin\']=域名((2*域名*X_train_cyclic[col])/max(X_train_cyclic[col])) X_train_cyclic[col+\'_cos\']=域名((2*域名*X_train_cyclic[col])/max(X_train_cyclic[col])) X_train_cyclic=域名(columns,axis=1)
one=OneHotEncoder() 域名(X_train_cyclic) train=域名sform(X_train_cyclic)
Method 5 : Target encoding
Target encoding 通过目标数据对类别变量进行编码,使用目标对应概率或平均概率替换该类别,即出现频次相近的被视为同一类(大城市,热门项等)。这个方法比较依赖训练集与测试集合的分布,要求他们数据分布一致。另外,这种方法可能会导致过拟合。
X_target=域名() X_target[\'day\']=X_target[\'day\'].astype(\'object\') X_target[\'month\']=X_target[\'month\'].astype(\'object\') for col in 域名mns: if (X_target[col].dtype==\'object\'): target= dict ( 域名pby(col)[\'target\'].agg(\'sum\')/域名pby(col)[\'target\'].agg(\'count\')) X_target[col]=X_target[col].replace(target).values
为了减轻过拟合可能带来的影响,可以使用K-Fold Validation ,每次对一份样本进行目标编码时,使用的都是其他K-1份数据之中的数据。
X[\'target\']=y cols=域名([\'target\',\'id\'],axis=1).columns %%time X_fold=域名() 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 域名t(X): for col in cols: if(X_fold[col].dtype==\'object\'): replaced=dict(域名[train_ind][[col,\'target\']].groupby(col)[\'target\'].mean()) 域名[val_ind,col]=域名[val_ind][col].replace(replaced).values
此外,在对特征进行编码前也需要进行特征种类的区分。常分为:
- 0-1数值:只有两种取值,可映射到0,1
- 类别数值:多个类别,这也是最常见的数据。
- 时序数据:时间戳等,隐含了顺序信息,可以反应趋势。