【问题标题】:pandas categories new levels熊猫分类新关卡
【发布时间】:2017-08-17 06:23:51
【问题描述】:

pandas categorical https://pandas.pydata.org/pandas-docs/stable/categorical.html 如何处理新的和看不见的关卡?我正在考虑一个类似 scikit-learn 的设置。目前,我有类似的东西: https://gist.github.com/geoHeil/5caff5236b4850d673b2c9b0799dc2ce

def: fit() 
  for each column:
   fit a label encoder:
def: transform()
  for each column:
     check if column was unseen
       yes(unseen) replace 
       no: label encode

但这很慢。

显然,像 xgboost 或 lightbm 这样的决策树可以直接处理分类数据,也就是说,人们不需要手动摆弄这种缓慢的转换。 但是当查看他们的代码时 https://github.com/Microsoft/LightGBM/blob/master/python-package/lightgbm/sklearn.py#L532 他们似乎使用LGBMLabelEncoder这是一个标准的scikit-learn LabelEncoder

我想知道它如何处理看不见的数据。

如果需要手动转换,pandas.Categorical 是否允许更快的转换 - 即使新数据中有未见过的级别?

编辑

请参阅https://github.com/geoHeil/pythonQuestions/blob/master/categorical-encoding.ipynb 了解我如何无法让 scikit-learn 的常见嫌疑人工作的概述。 仍在寻找比我的解决方案更高效的东西。另外 lightGBM https://github.com/Microsoft/LightGBM/issues/789 建议使用自定义编码策略。

【问题讨论】:

  • Pandas.Categorical 只是用 Nan 填充它们。 Scikit-learn 也不处理新数据,它们很可能会被删除或替换为 Nan。尝试对未见数据使用 LabelEncoder,您将获得 ValueError: y contains new labels:
  • 为什么这个问题被否决了?我想一个小的可重复数据集和一个期望的数据集可以帮助更好地理解问题......
  • @MaxU 也许是因为在我看来它更多的是算法方法问题而不是编程问题。这是机器学习中关于如何处理看不见的数据的常见问题,Cross-validated 是解决此问题的正确位置。
  • 我没有足够的权限自己这样做。如果其他人也有这种感觉,那么只有它可以被移动。这只是我的看法,但我认为这可能会得到更好的关注。
  • 真正的解决方案是在github.com/scikit-learn/scikit-learn/pull/9151github.com/scikit-learn/scikit-learn/pull/9012 中,遗憾的是它们还没有合并。 LabelEncoder + OneHotEncoder 或 LabelBinarizer 或 CountVectorizer(tokenizer=lambda x: x) 都是可能的解决方法(尽管没有一个很好)。

标签: python pandas scikit-learn categorical-data lightgbm


【解决方案1】:

可能有 pandas 解决方案,但它可能最适合 sklearns LabelBinarizer

from sklearn.preprocessing import LabelBinarizer
df= pd.DataFrame({'A':['a','b','c','a']})
lb = LabelBinarizer()
lb.fit(df["A"])
lb.transform(df["A"])

[[1 0 0]
 [0 1 0]
 [0 0 1]
 [1 0 0]]

df2 = pd.DataFrame({'A':['a','b','d']})
lb.transform(df2['A'])
[[1 0 0]
 [0 1 0]
 [0 0 0]]

所以我们看到'd'本质上既不映射到'a'、'b'或'c'。 但是请注意,bug 可能会在下一个 sklearn 版本中得到解决。

LabelBinarizer 在训练期间适合并调用传递给它的值。新值被映射到全零。使用 pandas get_dummies 编写一个转换器(如编辑前所见)可能更可行。

由于列的名称匹配,这可能非常简单。在第一步中拟合并存储列名,而不仅仅是在转换步骤中进行转换,而是只保留您在拟合中标识的列名(如果测试集中不存在训练级别,可能会添加 zome zero 列)。然后你就完成了;)

【讨论】:

  • 但这缺少 focabulary - 您不能保证第二个具有潜在看不见的分类级别或不同顺序的级别的 df 被正确编码。
  • 你说得对,可能缺少排序,但是,在处理具有离散值的列时,每列中的新类别/值将映射为零。
  • 关于排序,如果 df_1 包含 a,b 并且这被映射到 1,2 并且 df_2 包含 b,c 这应该被映射到 2,0 所以这应该不是问题吗?还是我误解了这个?
  • 我在答案里加个例子,给我一会,fit函数好像有错误;)
  • 对其进行了更新并删除了以前的类,而不是使用 sklearn 中的 labelbinarizer。但是,如果您有兴趣,我也可以使用 pandas get_dummies 构建相关解决方案(或自己尝试)
猜你喜欢
  • 2017-11-03
  • 2019-08-30
  • 2013-02-23
  • 2018-06-02
  • 2015-01-29
  • 1970-01-01
  • 2021-03-02
  • 2022-12-09
  • 1970-01-01
相关资源
最近更新 更多