首先声明的是,LabelEncoder只适合用于目标变量的编码,不适合作为X的编码。

参见官方文档:


Encode target labels with value between 0 and n_classes-1.



This transformer should be used to encode target values, *i.e.* `y`, and not the input `X`.


可能使用的场景是X为有序的变量时候,比如分数,在进行编码的时候,可以自定义权重数值映射之后,可以使用from sklearn.preprocessing import OrdinalEncoder进行有序编码,或者自定义权重字典进行映射。

如果是想进行无序的类别编码,建议使用onehot或者是pd.get_dummy,或者是先labelEncoder然后进行onehot编码。

以下操作是基于变量有序的场景进行使用。

以下场景存在的问题,OneHotEncoder也同样适用。

一、对多列数据进行转换时候

在进行模型训练的时候会对数据进行统一的预处理,但是在生产部署的时候,模型需要数据按照数据清洗的流程进行转化,

但是此时就会遇到一个问题,一列值进行LabelEncoder的时候,需要进行fit_transform一次,多列不就意味着需要多个LabelEncoder .

也就是说,必须要把这些LabelEncoder进行保存,然后在生产调用过程中,加载这些LabelEncoder进行逐列的处理。

这种形式确实有一定的弊端,那就是需要保存多个LabelEncoder模型

那该如何进行权衡呢?

首先数据应该进行批量的ETL处理,进入到模型的数据尽量保证数据的规范性,控制,异常值,都进行处理好,或者是已经进行LabelEncoder处理

如果说在数据拿到之后没办法直接用于模型,或者说进行了labelEncoder进行处理之后,模型评估指标能够有效的提升,那么这时候,LabelEncoder就必须自己来处理了

也就意味着,数据的第二轮清洗必须在进入模型之前完成。

二、当生产数据列的取值与训练数据不一致的情况:

此时采用encoder进行transforme会出错的,这里提供一下兼容代码:

# le_models 是存放着列名和label_encoder元组的数组

for col,le in le_models :

    print("processing col:",col)

    # 先进行填充,防止原来的数据为空 ,但是训练的数据不为空 

    if(len(df[col].value_counts())==0) :

        continue;

    df[col] = df[col].fillna(df[col].value_counts().index[0])

    # 遍历列的取值,如果列的取值不再le的class_中的时候进行众数填充

    for idx in df[col].value_counts().index:

        if idx not in le.classes_:

            print("idx:",idx)

            # 如果当前列的取值不在之前的列表中,name采用频率最高的进行填充

            df.loc[df[col]==idx,col] = df[col].value_counts().index[0]

    df[col] = le.transform(df[col].astype(str))


df[feat_cols] = df[feat_cols].fillna(-999)

流程大概是:

数据采集

->数仓清洗完成

->EDA&数据预处理

->保存每一列对应的LabelEncoder模型

->模型训练,评估,保存机器学习模型

->生产中加载LabelEncoder模型,分别处理对应列的数据,如果遇到没有出现过的取值,则用上述代码进行替换

->加载机器学习模型

->进行模型pred