LabelEncoder、OneHoeEncoder处理多列数据时使用注意事项

本文探讨了LabelEncoder在多列数据转换和生产部署中的使用问题,提出了解决方案,包括批量预处理、未知值处理和模型部署时的编码兼容性。还介绍了如何在不同场景下选择LabelEncoder或OneHot编码,并给出了离散特征编码的TopN实现和推荐的Embedding编码方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

更多关于采用labelEncoder还是Onehot编码的讨论可以参考:

机器学习-Label Encoding与One Hot的区别-20180513 - 知乎

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

以下场景存在的问题,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模型,建议将离线特征采用字典保存起来,同时填充unknown字段

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

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

->加载机器学习模型

->进行模型pred

附离散特征取TOPN实现逻辑

    top_n_obj_col = {}
    for col in obj_cols:
        if col not in data_iter.columns:
            feat_cols.remove(col)
            continue 

        print(f"{col}", len(data_iter[col].value_counts(dropna=False)))
        data_iter[col] = data_iter[col].fillna('unknown')
        if col == 'brand2':
            col_values = data_iter[col].value_counts(dropna=False).head(100).index.tolist()
        else:
            col_values = data_iter[col].value_counts(dropna=False).head(30).index.tolist()
        col_values_dict = {}
        for idx, v in enumerate(col_values):
            col_values_dict[v] = idx + 1
        # 默认填充 unknown对应的索引,否则填充0
        default_value = 0 if col_values_dict.get('unknown') is None else col_values_dict.get('unknown')
        data_iter[col] = data_iter[col].apply(lambda x: default_value if col_values_dict.get(x) is None else col_values_dict.get(x))
        # data_iter[col] = data_iter[col].apply(lambda x: 0 if col_values_dict.get(x) is None else col_values_dict.get(x))
        # print(f"{col}|{col_values}|{data_iter[col].nunique()}")
        top_n_obj_col[col] = col_values_dict

    # 枚举值特征字典保存到csv方便查看
    with open(f"{model_base_dir}/obj_feature_value_{version}.txt", mode='w') as f:
        for col, values in top_n_obj_col.items():
            f.write(col+"|" + str(values) + "\n")

说明如果离散特征取值非常多建议走Embedding进行编码。参见:Embedding理解与代码实现_海晨威的博客-优快云博客_embedding层代码实现

该代码中应该是用的tensorflow1.x版本,TensorFlow2.x

引用如下:

from tensorflow.keras.layers import Input,Flatten,Dense
from tensorflow.keras.models import Model

# from keras.layers import Dense, Flatten, Input
from tensorflow.python.keras.layers.embeddings import Embedding
# from keras.models import Model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.text import one_hot
import numpy as np
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mtj66

看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值