Python 具有多个输入的SMOTE

Python 具有多个输入的SMOTE,python,keras,scikit-learn,huggingface-transformers,smote,Python,Keras,Scikit Learn,Huggingface Transformers,Smote,我正在使用Keras和Bert(HuggingFace)构建一个多类文本分类模型,但我有一个非常不平衡的数据集。我使用了Sklearn中的SMOTE来为欠平衡类生成额外的样本(我总共有45个),当我使用来自Bert标记器的输入id时,它工作得很好 但是,我希望能够对输入掩码ID使用smote,以便允许模型确定填充值的位置 我的问题是如何对输入ID和掩码ID使用smote?到目前为止,我已经做了以下工作,模型没有抱怨,但我不确定重采样的掩码是否与重采样的输入ID行相对应。 Smote需要两个输入,

我正在使用Keras和Bert(HuggingFace)构建一个多类文本分类模型,但我有一个非常不平衡的数据集。我使用了Sklearn中的SMOTE来为欠平衡类生成额外的样本(我总共有45个),当我使用来自Bert标记器的输入id时,它工作得很好

但是,我希望能够对输入掩码ID使用smote,以便允许模型确定填充值的位置

我的问题是如何对输入ID和掩码ID使用smote?到目前为止,我已经做了以下工作,模型没有抱怨,但我不确定重采样的掩码是否与重采样的输入ID行相对应。 Smote需要两个输入,输入和标签,因此我用相同的随机状态复制了流程,并返回了所需的元素:

def smote(input_ids, input_masks, labels):

    smote = SMOTE("not majority", random_state=27)

    input_ids_resampled, labels_resampled = smote.fit_sample(input_ids, labels)
    input_masks_resampled, _ = smote.fit_sample(input_masks, labels)

    return input_ids_resampled, input_masks_resampled, labels_resampled

这可以接受吗?有更好的方法吗?

我认为给出的代码不是一个好主意

由于掩码ID告诉您哪些标记是真实的,哪些标记来自填充,如果您独立于输入ID对它们进行采样,那么最终将得到来自真实输入ID的合成输入ID,而模型将忽略这些ID,因为相应的合成掩码ID(由完全独立的标记生成)指示合成输入ID正在填充

愚蠢的例子:

  • t_1:input id=[120980183290],mask id=[1,1,0,]
  • t_2:input id=[39103381092931],mask id=[1,1,1]
  • t_3:input id=[12421294323],mask id=[1,0,0]
为了简单起见,假设合成是通过平均两个张量来完成的。如果您的随机smote采样平均了
t_1
t_2
的输入ID,但平均了
t_2
t_3
,则生成的合成
t_4
没有任何意义:它不是任何实际观测的平均值

解决上述问题的一个合理方法是:只对输入ID进行抽样,作为合成令牌的掩码ID,取相同掩码ID的平均值。我说的是平均值,但我认为掩码id向量的每个条目的中值可能更合适。我们可以通过将输入ID和掩码ID展平为一维张量并将smote应用于这些ID(我认为,假设smote在组件方面工作)来安排

然而,我认为上述修正仍然没有太多意义。我远非伯特专家,但我的理解是,每个标记都对应于一个精确的整数(最多可能是散列冲突)。如果是这样的话,通过简单地对代币取平均值,你最终将陷入完全的胡言乱语。即使为每个标记(例如,同一类中的5个张量)选择中位数,也会导致一个完全胡言乱语的句子

所以结论是,我不知道如何解决这个问题。也许人们可以在BERT模型中途的某个点进行攻击,此时令牌已经被部分处理为浮点数。或者甚至在标准伯特模型退出时,在微调到特定任务之前


最后,我想留给下一个遇到这个问题的人:显然有一个SMOTE的修改,SMOTENC,它(在其他任务中)适用于整数值向量。出于上述原因,我认为它不适合此用途,但很高兴知道。

我只想澄清一下,将SMOTE应用于输入ID是一种错误的方法。您需要将相应的嵌入带到CLS。使用BERT获取每条tweet的CLS令牌,然后对其应用SMOTE。然后从分类器(任何分类器)传递它。这应该在不进行微调的情况下完成