使用Keras中的样本权重进行序列标注

2024-04-27 08:00:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在研究一个带有不平衡类的序列标记问题,我想使用sample_weight来解决不平衡问题。基本上,如果我把模型训练10个阶段,我会得到很好的结果。如果我为更多的时代而训练,val_loss继续下降,但我会得到更糟糕的结果。我猜这个模型只是检测到更多的统治阶级,而损害了更小的阶级。

该模型有两个输入:字嵌入和字符嵌入,输入是从0到6的7个可能类之一。

有了填充,单词嵌入的输入层的形状是(3000, 150),单词嵌入的输入层是(3000, 150, 15)。我使用0.3分割来测试和训练数据,这意味着单词嵌入的X_train(2000, 150),字符嵌入的(2000, 150, 15)y包含每个单词的正确类,编码在维度7的一个热向量中,因此其形状为(3000, 150, 7)y同样被分成训练和测试集。然后,将每个输入馈入双向LSTM。

输出是一个矩阵,2000个训练样本中每个单词有7个类别,因此大小为(2000, 150, 7)


起初,我只是试图将sample_weight定义为长度为7的np.array,其中包含每个类的权重:

count = [list(array).index(1) for arrays in y for array in arrays]
count = dict(Counter(count))
count[0] = 0
total = sum([count[key] for key in count])
count = {k: count[key] / total for key in count}
category_weights = np.zeros(7)
for f in count:
    category_weights[f] = count[f]

但我得到以下错误ValueError: Found a sample_weight array with shape (7,) for an input with shape (2000, 150, 7). sample_weight cannot be broadcast.

看着这些文档,我似乎应该传递a 2D array with shape (samples, sequence_length)。因此,我创建了一个(3000, 150)数组,其中串联了每个序列中每个单词的权重:

weights = []

for sample in y:
    current_weight = []
    for line in sample:
        current_weight.append(frequency[list(line).index(1)])
    weights.append(current_weight)

weights = np.array(weights)

compile()中添加sample_weight_mode="temporal"选项后,通过sample_weight参数将其传递给fit函数。

我第一次得到一个错误,告诉我维度是错误的,但是在只为训练样本生成权重之后,我得到了一个(2000, 150)数组,可以用来拟合我的模型。


  • 这是定义样本权重的正确方法吗?还是我做得不对?我不能说我注意到增加重量有什么进步,所以我一定漏掉了一些东西。

Tags: samplekeyin模型forcount错误with
1条回答
网友
1楼 · 发布于 2024-04-27 08:00:33

我认为你混淆了sample_weightsclass_weights。稍微检查一下docs我们可以看到它们之间的区别:

sample_weights用于为每个训练样本提供权重。这意味着您应该传递一个1D数组,该数组的元素数与您的训练样本数相同(指示每个样本的权重)。如果使用的是时态数据,则可以传递一个二维数组,使您能够为每个样本的每个时间步赋予权重。

class_weights用于为每个输出类提供权重或偏差。这意味着您应该为尝试分类的每个类传递权重。此外,此参数期望向其传递字典(而不是数组,这就是为什么出现此错误的原因)。例如,考虑这种情况:

class_weight = {0 : 1. , 1: 50.}

在这种情况下(一个二进制分类问题),您对类1的样本赋予的权重(或“相关性”)是类0的50倍。这样可以补偿不平衡的数据集。这里有另一个有用的post解释了在处理不平衡数据集时需要考虑的关于这个和其他选项的更多信息。

If I train for more epochs, val_loss keeps dropping, but I get worse results.

可能是你太过合适了,而导致这种情况的原因可能是你的数据集所拥有的不平衡类,正如你正确地怀疑的那样。对类权重进行补偿有助于缓解这种情况,但是可能还有其他因素会导致过度拟合,从而超出此问题/答案的范围(因此,请确保在解决此问题后注意这些因素)。


从你的帖子来看,在我看来,你需要的是使用class_weight来平衡你的训练数据集,为此你需要通过一个字典来指示你7个班级之间的权重比率。考虑使用sample_weight仅当您想给每个样本一个自定义权重以供考虑时。

如果你想更详细地比较这两个问题,请考虑查看我发布的一个相关问题。扰流器:sample_weight覆盖class_weight,因此必须使用其中一个,但不能同时使用两个,因此小心不要将它们混合。

相关问题 更多 >