具有多个伯特输入的 SMOTE
SMOTE with multiple bert inputs
我正在使用 Keras 和 Bert (HuggingFace) 构建多类文本分类模型,但我的数据集非常不平衡。我使用了 Sklearn 的 SMOTE 来为欠平衡 类 生成额外的样本(我总共有 45 个),当我使用来自 Bert Tokenizer 的输入 id 时它工作正常。
但是,我希望也能够对输入掩码 ID 使用 smote,以便让模型确定填充值的位置。
我的问题是如何对输入 ID 和遮罩 ID 使用 Smote?到目前为止,我已经完成了以下操作,并且模型没有抱怨,但我不确定重新采样的掩码是否与逐行的重新采样输入 ids 匹配。
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 对它们进行采样,你将结束来自 real 输入 id 的合成输入 id 被模型忽略,因为相应的合成掩码 id(从完全独立的标记生成)表明您的合成输入 id 正在填充。
愚蠢的例子:
t_1: input ids = [1209, 80183, 290], mask ids = [1,1,0,]
t_2: input ids = [39103, 38109, 2931], mask ids = [1,1,1]
t_3: input ids = [1242, 1294, 3233], mask ids = [1,0, 0]
为简单起见,假设合成创建是通过对两个张量进行平均来完成的。如果您的随机击打采样对 t_1
和 t_2
的输入 ID 进行平均,但对 t_2
和 t_3
的掩码 ID 进行平均,则生成的合成 t_4
没有无论如何:它不是任何实际观察的平均值。
针对上述问题的合理修复:您仅对输入 ID 进行采样,并且作为合成令牌的掩码 ID,您采用相同掩码 ID 的 平均值。我说 average,但我认为 mask id 向量的每个条目的 median 值可能更合适。可以通过将输入 id 和掩码 id 展平为一维张量并将 smote 应用于它们来安排(我认为,假设 smote 在组件方面工作)。
不过,我觉得上面的修复还是没有太大的意义。我远不是 BERT 专家,但我的理解是每个标记都对应一个精确的整数(最多可能是哈希冲突)。如果是这样的话,通过简单地平均令牌,你最终会得到完全的胡言乱语。即使为每个标记(例如,同一 class 中的 5 个张量)选择中位数也会导致一个完整的乱码句子。
所以结论是,我不知道如何解决这个问题。也许人们可以在 BERT 模型中途的某个时刻进行攻击,此时令牌已经被部分处理为浮点数。或者甚至可能在标准 Bert 模型退出时和针对您的特定任务进行微调之前。
最后,我想留给下一个遇到此问题的人:显然有 SMOTE 的修改版 SMOTENC,它适用于(在其他任务中)整数值向量。由于上面解释的原因,我认为它不适合这个目的,但很高兴知道。
我只是想澄清一下,这是将 SMOTE 应用于 input_id 的错误方法。您需要将相应的嵌入到 CLS 中。使用 BERT 为每条推文获取 CLS 令牌,然后对其应用 SMOTE。然后从分类器(任何分类器)传递它。这应该在没有 fine-tuning.
的情况下完成
我正在使用 Keras 和 Bert (HuggingFace) 构建多类文本分类模型,但我的数据集非常不平衡。我使用了 Sklearn 的 SMOTE 来为欠平衡 类 生成额外的样本(我总共有 45 个),当我使用来自 Bert Tokenizer 的输入 id 时它工作正常。
但是,我希望也能够对输入掩码 ID 使用 smote,以便让模型确定填充值的位置。
我的问题是如何对输入 ID 和遮罩 ID 使用 Smote?到目前为止,我已经完成了以下操作,并且模型没有抱怨,但我不确定重新采样的掩码是否与逐行的重新采样输入 ids 匹配。 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 对它们进行采样,你将结束来自 real 输入 id 的合成输入 id 被模型忽略,因为相应的合成掩码 id(从完全独立的标记生成)表明您的合成输入 id 正在填充。
愚蠢的例子:
t_1: input ids = [1209, 80183, 290], mask ids = [1,1,0,]
t_2: input ids = [39103, 38109, 2931], mask ids = [1,1,1]
t_3: input ids = [1242, 1294, 3233], mask ids = [1,0, 0]
为简单起见,假设合成创建是通过对两个张量进行平均来完成的。如果您的随机击打采样对 t_1
和 t_2
的输入 ID 进行平均,但对 t_2
和 t_3
的掩码 ID 进行平均,则生成的合成 t_4
没有无论如何:它不是任何实际观察的平均值。
针对上述问题的合理修复:您仅对输入 ID 进行采样,并且作为合成令牌的掩码 ID,您采用相同掩码 ID 的 平均值。我说 average,但我认为 mask id 向量的每个条目的 median 值可能更合适。可以通过将输入 id 和掩码 id 展平为一维张量并将 smote 应用于它们来安排(我认为,假设 smote 在组件方面工作)。
不过,我觉得上面的修复还是没有太大的意义。我远不是 BERT 专家,但我的理解是每个标记都对应一个精确的整数(最多可能是哈希冲突)。如果是这样的话,通过简单地平均令牌,你最终会得到完全的胡言乱语。即使为每个标记(例如,同一 class 中的 5 个张量)选择中位数也会导致一个完整的乱码句子。
所以结论是,我不知道如何解决这个问题。也许人们可以在 BERT 模型中途的某个时刻进行攻击,此时令牌已经被部分处理为浮点数。或者甚至可能在标准 Bert 模型退出时和针对您的特定任务进行微调之前。
最后,我想留给下一个遇到此问题的人:显然有 SMOTE 的修改版 SMOTENC,它适用于(在其他任务中)整数值向量。由于上面解释的原因,我认为它不适合这个目的,但很高兴知道。
我只是想澄清一下,这是将 SMOTE 应用于 input_id 的错误方法。您需要将相应的嵌入到 CLS 中。使用 BERT 为每条推文获取 CLS 令牌,然后对其应用 SMOTE。然后从分类器(任何分类器)传递它。这应该在没有 fine-tuning.
的情况下完成