【问题标题】:When is it appropriate to use sample_weights in keras?什么时候在 keras 中使用 sample_weights 比较合适?
【发布时间】:2019-08-22 13:45:14
【问题描述】:

根据这个question,我了解到keras 中的class_weight 在训练期间应用了加权损失,如果我对所有训练没有同样的信心,sample_weight 正在做一些样本明智的事情样本。

所以我的问题是,

  1. 验证期间的损失是否由class_weight 加权,还是仅在训练期间加权?
  2. 我的数据集有 2 个类,我实际上并没有严重不平衡的类分布。比例约为。 1.7:1.是否需要使用class_weight来平衡损失甚至使用过采样?可以将稍微不平衡的数据保留为通常的数据集处理吗?
  3. 我可以简单地将sample_weight 视为我赋予每个火车样本的权重吗?而且我的训练样本可以得到同等的信心,所以我可能不需要使用它。

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:
    1. 从 keras 文档中说

    class_weight:可选字典将类索引(整数)映射到权重(浮点)值,用于加权损失函数(仅在训练期间)。这对于告诉模型“更加关注”来自代表性不足的类的样本很有用。

    所以class_weight 只会影响训练过程中的损失。我本人一直有兴趣了解在测试和培训期间如何处理类和样本权重。查看 keras github repo 和 metric 和 loss 的代码,似乎 loss 或 metric 都不受它们的影响。在model.fit() 等训练代码及其相应的 tensorflow 后端训练函数中很难跟踪打印的值。所以我决定做一个测试代码来测试可能的场景,见下面的代码。结论是class_weightsample_weight 都只影响训练损失,对任何指标或验证损失没有影响。 val_sample_weights(您可以指定)似乎什么都不做(??)。

    1. 此类问题始终取决于您的问题、日期的偏差程度以及您尝试优化模型的方式。您是否针对准确性进行了优化,那么只要训练数据与模型在生产中时一样倾斜,那么只需在没有任何过度/不足采样和/或类权重的情况下进行训练即可获得最佳结果。 另一方面,如果您有一个类比另一个类更重要(或更昂贵)的东西,那么您应该对数据进行加权。例如在欺诈预防中,欺诈通常比非欺诈的收入昂贵得多。我建议您尝试未加权类、加权类和一些欠/过采样,并检查哪个可以提供最佳验证结果。使用最能比较不同模型的验证函数(或自己编写)(例如,根据成本对真阳性、假阳性、真阴性和假阴性进行不同的加权)。 一个相对较新的损失函数是Focal-lossFocal-loss 减少过采样/欠采样的需要。不幸的是,Focal-loss 还不是 keras 中的内置函数,但可以手动编程。

    2. 是的,我认为你是正确的。我通常使用sample_weight 有两个原因。 1,训练数据具有某种测量不确定性,如果已知,可以使用比不准确测量更多的权重准确数据。或者 2,我们可以比旧数据更多地加权新数据,迫使模型更快地适应新行为,而不会忽略有价值的旧数据。

    比较有和没有class_weightssample_weights 的代码,同时保持模型和其他一切都是静态的。

    import tensorflow as tf
    import numpy as np
    
    data_size = 100
    input_size=3
    classes=3
    
    x_train = np.random.rand(data_size ,input_size)
    y_train= np.random.randint(0,classes,data_size )
    #sample_weight_train = np.random.rand(data_size)
    x_val = np.random.rand(data_size ,input_size)
    y_val= np.random.randint(0,classes,data_size )
    #sample_weight_val = np.random.rand(data_size )
    
    inputs = tf.keras.layers.Input(shape=(input_size))
    pred=tf.keras.layers.Dense(classes, activation='softmax')(inputs)
    
    model = tf.keras.models.Model(inputs=inputs, outputs=pred)
    
    loss = tf.keras.losses.sparse_categorical_crossentropy
    metrics = tf.keras.metrics.sparse_categorical_accuracy
    
    model.compile(loss=loss , metrics=[metrics], optimizer='adam')
    
    # Make model static, so we can compare it between different scenarios
    for layer in model.layers:
        layer.trainable = False
    
    # base model no weights (same result as without class_weights)
    # model.fit(x=x_train,y=y_train, validation_data=(x_val,y_val))
    class_weights={0:1.,1:1.,2:1.}
    model.fit(x=x_train,y=y_train, class_weight=class_weights, validation_data=(x_val,y_val))
    # which outputs:
    > loss: 1.1882 - sparse_categorical_accuracy: 0.3300 - val_loss: 1.1965 - val_sparse_categorical_accuracy: 0.3100
    
    #changing the class weights to zero, to check which loss and metric that is affected
    class_weights={0:0,1:0,2:0}
    model.fit(x=x_train,y=y_train, class_weight=class_weights, validation_data=(x_val,y_val))
    # which outputs:
    > loss: 0.0000e+00 - sparse_categorical_accuracy: 0.3300 - val_loss: 1.1945 - val_sparse_categorical_accuracy: 0.3100
    
    #changing the sample_weights to zero, to check which loss and metric that is affected
    sample_weight_train = np.zeros(100)
    sample_weight_val = np.zeros(100)
    model.fit(x=x_train,y=y_train,sample_weight=sample_weight_train, validation_data=(x_val,y_val,sample_weight_val))
    # which outputs:
    > loss: 0.0000e+00 - sparse_categorical_accuracy: 0.3300 - val_loss: 1.1931 - val_sparse_categorical_accuracy: 0.3100
    

    使用权重与不使用权重之间存在一些小的偏差(即使所有权重都为 1),这可能是由于对加权和未加权数据使用不同的后端函数进行拟合,还是由于舍入误差?

    【讨论】:

    • 感谢您的详细解答。我对问题 2 有进一步的疑问,我觉得我很难理解,但我会为此发布另一个问题。顺便说一句,你会推荐一些关于评估不同模型性能的验证函数的材料吗?任何像 github repos 或 kaggle 内核之类的东西都将不胜感激。
    • 我正在使用 sample_weight 并发现它实际上并没有在训练期间传递给计算指标 (.fit)。 stackoverflow.com/questions/64380057/…
    • 作为参考,如果您指定 weighted_metrics 而不是指标,那么它们确实会被传递。有关示例,请参阅上面链接中的@kawingkelvin 的答案
    猜你喜欢
    • 2015-02-11
    • 2010-10-22
    • 2011-01-06
    • 1970-01-01
    • 2011-09-13
    • 2011-02-21
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    相关资源
    最近更新 更多