首先声明的是,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