在Keras中使用sample_weight进行序列标记

use*_*402 7 python deep-learning keras data-science

我正在处理不平衡类的顺序标签问题,我想用它sample_weight来解决不平衡问题。基本上,如果我训练模型约10个时期,我会得到很好的结果。如果我训练更多的纪元,val_loss会不断下降,但结果会更糟。我猜测该模型只会检测到更多的主导类,从而损害较小的类。

该模型有两个输入,分别用于单词嵌入和字符嵌入,并且输入是从0到6的7种可能的类之一。

使用填充,我的词嵌入输入层的形状为,而词嵌入的输入层的形状(3000, 150)(3000, 150, 15)。我将0.3拆分用于测试和训练数据,这意味着X_train用于单词嵌入(2000, 150)(2000, 150, 15)用于char嵌入。y包含每个单词的正确类,并以7维的单热点向量编码,因此其形状为(3000, 150, 7)y同样分为训练和测试集。然后将每个输入馈入双向LSTM。

输出是一个矩阵,为2000个训练样本的每个单词分配了7个类别之一,因此大小为(2000, 150, 7)


首先,我只是尝试将长度定义sample_weightnp.array7,其中包含每个类的权重:

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]
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误 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)
Run Code Online (Sandbox Code Playgroud)

并传递到拟合函数通过sample_weight参数已经加入后sample_weight_mode="temporal"在选项compile()

我首先遇到一个错误,告诉我尺寸是错误的,但是只为训练样本生成了权重后,我得到了一个(2000, 150)数组,可以用来拟合我的模型。


  • 这是定义sample_weights还是我做的一切都是错的一个适当的方式?我不能说我已经注意到增加权重的任何改进,所以我一定错过了一些东西。

Dar*_*nus 8

我认为你很困惑sample_weightsclass_weights。检查一下文档,我们可以看到它们之间的差异:

sample_weights用于为每个训练样本提供权重。这意味着您应该传递一维数组,该数组具有与训练样本相同数量的元素(指示每个样本的权重)。如果您使用的是时间数据,则可以改为传递2D数组,从而使您可以权衡每个样本的每个时间步长。

class_weights用于为每个输出类提供权重或偏差。这意味着您应该为要分类的每个类传递权重。此外,此参数希望将字典传递给它(不是数组,这就是为什么会出现此错误)。例如,考虑这种情况:

class_weight = {0 : 1. , 1: 50.}
Run Code Online (Sandbox Code Playgroud)

在这种情况下(二进制分类问题),你给50倍的重量(或“相关性”)将类的样品1相比类0。这样,您可以补偿不平衡的数据集。这是另一篇有用的文章,解释了有关此问题以及在处理不平衡数据集时要考虑的其他选项的更多信息。

如果我训练更多的纪元,则val_loss会不断下降,但结果会更糟。

正如您正确怀疑的那样,可能是您过度拟合,并且可能导致数据集类不平衡的原因。补偿班级权重应该可以减轻这种情况,但是,仍然可能有其他因素导致过度拟合,从而超出了该问题/答案的范围(因此请确保在解决此问题后要当心)。


从您的帖子来看,在我看来,您需要使用的class_weight是平衡训练数据集的方法,为此您需要传递一个字典,指示您7个班级之间的重量比。考虑使用sample_weight只有当你想给每个样品定制重量审议。

如果您想在两者之间进行更详细的比较,请考虑检查我在相关问题上发布的答案扰流器:sample_weight覆盖class_weight,因此您必须使用一个或另一个,但不能同时使用两者,因此请注意不要混合使用。