如何在多类分类中利用描述数据(降维)

数据挖掘 Python 分类 分类数据 降维
2022-02-22 20:57:42

我目前正在处理一个包含 55k 条记录和七列(一个目标变量)的数据集,其中三个是名义分类的。其他三个是具有高基数的“描述”字段,正如在描述数据的许多情况下所预期的那样:

in>>
df[['size description', 'weight Description', 'height Description']].nunique()

out>>
 size Description       4066
 weight Description      736
 height Description     3173
 dtype: int64

这些值的一些示例可能是:

   Product                  Product Description
  ---------               ------------------------
   Ball                 Round bouncy toy for kids
   Bat                  Stick that kids use to hit a ball
   Go-Kart red/black    Small motorized vehicle for kids
   Go-Kart blue/green   Small motorized vehicle for kids
   Wrench               Tool for tightening or loosening bolts
   Ratchet              Tool for tightening or loosening bolts
   Reclining arm-chair  Cushioned seat for lounging

如果描述属于特定类别,我认为描述是标准化的,但目前我无法确认唯一描述的数量是否有限。此时,我的假设是将这些视为名义分类,因为它们是字面上的描述性而不是定性的。

为此,我的问题是处理诸如此类的分类特征的一些最佳实践是什么?

我考虑过的事情:

  1. 在这种情况下,标签编码显然是不可行的,因为描述没有层次结构。

  2. One-hot 编码似乎不太可能解决,因为由于其他变量的高基数,它会将数据集的形状从 (55300 , 6) 膨胀到 (55300 , 65223)。然而,我还是尝试了它,并在我的测试集上产生了 98% 的准确度,但在样本外验证集上的结果却非常糟糕(5k 条记录,0-5% 的准确度)。似乎很明显它过度拟合,因此不可行。

  3. 无论出于何种原因,散列不适用于其中一列,但我认为它仍然可行。我只需要弄清楚为什么它没有散列我的所有功能(我想这最适合单独的问题?)

  4. PCA - 可能是可行的,但如果我正确理解单热编码后的基数太大,PCA 会抛出错误。公平地说,我还没有尝试过。

  5. 分箱似乎不可行,因为我的值可能是 3.5 或 3 和 1/2。每个都将被视为一个单独的垃圾箱,因此不能解决我的问题。

感谢所有可以分享他们的见解/意见的人。

2个回答

你有文字描述,即非结构化数据。因此,您可能应该使用一种标准的文本表示方法。有很多选项,包括句子嵌入和这种高级方法,但我将描述简单的传统选项:

  • 每个描述值都可以表示为一个特征向量,一个用于完整词汇表中的每个单词(即该字段的所有值)。
  • 每个特征的值可以是布尔值(即这个词是否出现在这个描述中)或更好的词的 TF-IDF 权重。
  • 显然这会导致功能过多,因此需要应用选择最相关的功能。这部分是非常实验性的,您可能需要尝试各种选项才能找到正确的选项:
    • 去掉停用词,因为它们不提供语义信息。
    • 丢弃所有只出现一次的单词,可能还有所有出现频率低于某个最小频率的单词N(尝试使用 $N=2,3,4...)。理由是稀有词更可能导致过度拟合,而不是真正帮助任何类型的分类。
    • 除此之外,您可以使用一般特征选择(例如信息增益)或特征聚类。

[对问题的第一个版本的过时答案]

我肯定会尝试对这些值进行规范化,因为从语义上讲它们是数字的,并且在它们的原始形式中它们几乎是无用的,无论采用何种分类方法。将它们分类会丢失很多信息,尤其是那些实际提供数字的信息。由于使用的一些字符串非常模糊,我可能会尝试使用间隔,即每个原始输入值的两个数值:

  • 三英寸半,三又 1/2 英寸 -> 最小 3.4 - 最大 3.6
  • 27.6234 英寸 -> 最小 27.6234 - 最大 27.6234
  • 高 -> 大范围高值
  • 短,有点短 -> 大范围低值

通常,将数字表示为单词的方法并不多,只有几个模式就足以捕获所有变体。对于其他非标准情况,例如“有点短”,我将从查看数据的分布开始:如果一个值足够频繁(例如,可能是“短”、“高”),则手动预定义范围。可以忽略不频繁的值,例如用 NA 替换(因为它们不频繁,不会对数据产生太大影响)。

您对标签编码、单热编码等的考虑是相当准确的。对于处理描述性数据,将每个描述转换为有意义的向量肯定会有所帮助。

有意义的向量是捕捉描述中所说内容的本质的向量。

让,

football = "round bouncy toy for kids to kick"
basketball = "round bouncy toy for kids to dribble"
spark_plug = "device for delivering electric current from an ignition system to the combustion chamber of a spark-ignition engine"

有意义的向量将具有这样的性质,

dist(vector(football), vector(basketball)) < dist(vector(football), vector(spark_plug))

对于在普通英语语料库上学习的向量表示,出现如下属性 -

vector('king') - vector('male') + vector('female') = vector('queen')

Word2Vec是一种计算词向量的有效方法——向量可以捕捉单个词的含义。要使用 Word2Vec,您可以 -

  1. 使用通过在大型公共语料库(如 Wikipedia)上预训练 Word2Vec 获得的向量。由于您的描述包含没有特定领域含义的单词,这似乎更可取。然而,这种方法有一个缺点。本着获得整个英语词汇表的准确表示的精神,这些学习向量往往具有高维度(300 和 1000 更常见),这可能使它们无法用于您的任务。
  2. 用你自己的词汇训练 Word2Vec使用这种方法,您可以设置足够的学习向量维度来捕获单词含义,但不会破坏您的特征空间。

对于您的描述,您可以平均其组成词的向量,从而将每个描述视为一个词袋,或者您可以使用复杂的技术,如Doc2Vec,它基于 Word2Vec,但试图捕获词的相对顺序。

Gensim 的Word2Vec 和 Doc2Vec 实现有一个相当简单的 API 公开,您可以快速学习将其用于您的特定任务。