为何dask_ml.preprocessing.OrdinalEncoder.transform未生成正确序数编码结果
原因说明
dask_ml.preprocessing.OrdinalEncoder 和 sklearn 版本的默认行为存在核心差异:sklearn 的 OrdinalEncoder 会默认将所有输入的非数值列视为分类特征做编码,而 dask-ml 的实现默认仅会对数据类型为 category 的列做编码处理,你测试代码中的cat1、cat2都是object类型的字符串列,会被编码器直接跳过原样返回,所以才会出现返回结果和原输入完全相等的情况。
修复方案
有两种常用的方案可以实现和sklearn一致的编码效果:
方案1:提前将分类列转为category类型
这是dask生态推荐的标准写法,dask可以更好的针对分类类型做性能优化:
# 补全原测试代码缺失的导入 import string import dask.dataframe as dd from sklearn.preprocessing import OrdinalEncoder from dask_ml.preprocessing import OrdinalEncoder as DaskOrdinalEncoder import numpy as np import pandas as pd N = 10 np.random.seed(1234) df = pd.DataFrame({ "cat1": np.random.choice(list(string.ascii_uppercase)[0:3], size=N), "cat2": np.random.choice(list(string.ascii_uppercase)[0:3], size=N), }) # 将待编码的object类型列转为category类型 df["cat1"] = df["cat1"].astype("category") df["cat2"] = df["cat2"].astype("category") df_dd = dd.from_pandas(df, npartitions=3) # 此时编码结果和sklearn完全对齐 encoded_result = DaskOrdinalEncoder().fit_transform(df_dd).compute() # 如果需要numpy数组格式,调用.values即可 encoded_array = encoded_result.values
方案2:手动指定需要编码的列
如果不想修改原数据类型,可以在初始化编码器时通过columns参数手动指定待编码的列名,编码器会对指定列做强制编码:
import string import dask.dataframe as dd from sklearn.preprocessing import OrdinalEncoder from dask_ml.preprocessing import OrdinalEncoder as DaskOrdinalEncoder import numpy as np import pandas as pd N = 10 np.random.seed(1234) df = pd.DataFrame({ "cat1": np.random.choice(list(string.ascii_uppercase)[0:3], size=N), "cat2": np.random.choice(list(string.ascii_uppercase)[0:3], size=N), }) df_dd = dd.from_pandas(df, npartitions=3) # 手动指定要编码的列,无需提前转换类型 encoder = DaskOrdinalEncoder(columns=["cat1", "cat2"]) encoded_result = encoder.fit_transform(df_dd).compute()
内容的提问来源于stack exchange,提问作者Raffael
相关产品推荐
相关产品推荐

