【pandas】get_dummies对特征进行onehot encoder测试集特征的一致性等坑

在对分类特征进行处理时,我们经常会把这类特征转成独热编码(onehot)

在sklearn中有OneHotEncoder,但是使用比较麻烦,万幸是pandas有对应的get_dummies

pandas.get_dummies(dataprefix=Noneprefix_sep='_'dummy_na=Falsecolumns=Nonesparse=Falsedrop_first=Falsedtype=None)[source]

Convert categorical variable into dummy/indicator variables

使用get_dummies可以参考pandas文档,这里不做赘述 

这里讲讲我在ML项目中使用独热编码遇到的一些坑和解决办法。

问题:拆分训练集和测试集之后各自dummy,因为有些特征可能只在两个set各自出现,于是会导致两个集的特征不一致

我参考了这篇的解决办法

第一种办法

合并进行dummy,pd.concat(( train, test ))get_dummies() ,之后再拆分train test set

第二种办法

对测试集的特征进行处理,如果存在 在训练集出现但在测试集中没有出现的特征值,就补充该dummy列且填充0,如果出现在测试集出现但在训练集没出现的特征值,那么就删除。

这种办法实际上就是以训练集特征值为准,少补多删

#columns是训练集经过dummy的feature名,d是测试集经过dummy之后的数据集
#这个函数增加缺少的dummy列
def add_missing_dummy_columns( d, columns ):
    missing_cols = set( columns ) - set( d.columns )
    for c in missing_cols:
        d[c] = 0

def fix_columns( d, columns ):  
    #增加缺少的dummy列
    add_missing_dummy_columns( d, columns )

    # make sure we have all the columns we need
    assert( set( columns ) - set( d.columns ) == set())

    extra_cols = set( d.columns ) - set( columns )
    if extra_cols:
        print "extra columns:", extra_cols

    d = d[ columns ]
    return d

因为我的某些特征值有上千个,这样dummy就会多了上千个的特征,经过训练集和测试集特征一致化后,在xgb运行时会报如下错ValueError: feature_names mismatch

ValueError: feature_names mismatch

但实际上特征名应该是match的,我在google上搜到了这篇stackoverflow,发现问题差不多,xbgoost的GitHub 上也有这个issue

这个bug实际上很蠢。。就是应该传numpy的矩阵格式,所以使用dataframe.values转换一下即可

贴一下我自己的dummy特征一致化过程代码:

主要流程:

1 训练集和测试集分别dummy

2 把训练集多的特征值feature加到测试集上

3 把测试集多的特征值feature删掉

4 测试两个features集是否一致

#deel with dummy features
X_train = pd.get_dummies(X_train,columns=['xkkh','zy','xy','constellation','course_type','zzmm','instituteType','xb'])
X_test = pd.get_dummies(X_test,columns=['xkkh','zy','xy','constellation','course_type','zzmm','instituteType','xb'])

#X_test = X_test[X_train.columns]
miss_columns = set(X_train.columns) - set(X_test.columns)

#add missing dummy columns
for col in miss_columns:
    X_test[col] = 0
    
adu_columns = set(X_test.columns) - set(X_train.columns)
#delete adundant columns:
X_test.drop(list(adu_columns),axis=1,inplace=True)

print("after deeling with dummy columns,trainset and testset keep same:",set(X_train.columns)-set(X_test.columns) == set([]))

 

 

你可能感兴趣的:(机器学习,python,pandas)