解决sklearn中使用OrdinalEncoder编码测试集的类别特征中的未知类别时会报错的问题

解决sklearn中使用OrdinalEncoder方法将类别特征(categorical/discrete features)变为有序数值特征(ordinal integers)时无法编码测试集的类别特征中的未知类别的问题

当数据集中存在类别特征时(categorical/discrete features),我们一般的想法是将其转变为数值型的特征,比如如果是不存在内在高低顺序的类别特征,便可以使用sklearn中的OneHotEncoder方法将其转变为数值型的特征,但是OneHotEncoder也会令数据集中的特征数量激增,以至于模型复杂度升高。

而另一种将类别特征转变为数值型特征的方法则为OrdinalEncoder。OrdinalEncoder方法的一个特点是其可以根据标签y来对类别特征进行顺序编码,比如[ [“北京”, 9], [“上海”,11], [“深圳”, 8] ]这个数据中,第一个特征为地点类别特征,第二个假设为标签,在这里可以看出不同的地点其标签是有顺序上的差异的,这种情况下的类别特征就很适合使用OrdinalEncoder方法来进行数值型编码。

但是sklearn中的OrdinalEncoder方法根据训练集的数据调用其内部的fit_transform()函数进行拟合之后,如果在用其对测试集中的类别特征进行数值型编码转换时,测试集的类别特征中有未知类别(即训练集中此类别特征中未出现过的类别)时,OrdinalEncoder方法内的transform函数则会报错。sklearn中的OrdinalEncoder方法如下所示,在初始化时是没有指定怎么处理测试集中未见类别的参数的 (而OneHotEncoder方法在初始化时则有指定处理测试集中未见类别的参数)。
在这里插入图片描述

解决这个问题的方法可以从OrdinalEncoder的源码中找到, OrdinalEncoder方法中的transform函数如下所示:
在这里插入图片描述
从上图可以看出OrdinalEncoder类中的transform函数是直接调用OrdinalEncoder类的父类中的self._transform()函数以及一些后续操作来对测试集中的类别特征进行转化的,而OrdinalEncoder类则是继承自_BaseEncoder类:
在这里插入图片描述
因此去查看_BaseEncoder类中的_transform()函数时可以发现其实_BaseEncoder类中的_transform()函数中是有指定怎么处理测试集中未见类别的参数 handle_unknown 的,如下图:
在这里插入图片描述
从_BaseEncoder类中的_transform()函数源码中可以看出,当将handle_unknown参数由"error"值改成别的任意值时,测试集类别特征中的未见类别将被编码为0,而不是直接报错。
因此当使用OrdinalEncoder去对含有未见类别特征的测试集进行编码时,可以不使用OrdinalEncoder类中的transform()函数,而是直接调用OrdinalEncoder类所继承的_BaseEncoder类中的_transform()函数来对测试集进行编码。此时_transform()函数返回的为一个元组对象,这个元组对象中的第一个元素为我们想要的对于测试集的编码结果;而第二个元素则为编码过程中的副产品mask矩阵,可以舍弃。再对测试集的编码结果进行astype()操作,最后得到的即为最终的测试集编码结果。

详细操作代码如下:
初始化训练集与测试集:

from sklearn.preprocessing import OrdinalEncoder
import pandas as pd
import numpy as np

train_data = [["北京","互联网" ,9],
        ["北京"
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值