【问题标题】:Custom weighted loss in cntkcntk中的自定义加权损失
【发布时间】:2017-09-11 09:23:40
【问题描述】:

我喜欢在下面计算加权误差:

def calc_err(pred, targets, weights) :
    nClass = np.size(pred, axis=0) 

    Is = [1.0 for i in range(nClass)]
    nonTargets = C.minus(Is, targets)
    wrongPred = C.minus(Is, pred)
    wColumn = C.times(targets, weights)
    wTarget = C.element_times(wColumn, targets)
    wNonTarget = C.element_times(wColumn, nonTargets)
    c1 = C.negate(C.reduce_sum(C.element_times(wTarget, C.log(pred)), axis = -1))
    c2 = C.negate(C.reduce_sum(C.element_times(wNonTarget, C.log(wrongPred)), axis = -1))
    ce = c1 + c2

    return ce.eval()

pred 是预测概率,targets 是 one-hot 数组,weights 是 2D 数组。我在下面创建了一个相应的自定义损失:

def WeightedCrossEntropy(z, targets):
    pred = C.softmax(z)
    nClass = np.size(pred, axis=0) 
    Is = [1 for i in range(nClass)]

    nonTargets = C.minus(Is, targets)
    wrongPred = C.minus(Is, pred)
    wColumn = C.times(targets, weights)
    wTarget = C.element_times(wColumn, targets)
    wNonTarget = C.element_times(wColumn, nonTargets)
    c1 = C.negate(C.reduce_sum(C.element_times(wTarget, C.log(pred)), axis=-1))
    c2 = C.negate(C.reduce_sum(C.element_times(wNonTarget, C.log(wrongPred)), axis=-1))
    ce = c1 + c2

    return ce

当我尝试训练时,我注意到虽然自定义损失确实在减少,但来自 calc_err(pred, targets, weights) 的测试误差只减少一两个时期或根本不减少。我的 WeightedCrossEntropy(z, targets) 是否正常或我做错了什么?

【问题讨论】:

    标签: python cntk loss


    【解决方案1】:

    权重是常数还是参数?请确保这两个函数采用相同的输入、参数和常量。

    【讨论】:

    • 权重如上预先计算。如何验证这两个函数采用相同的输入、参数和常量?我已将代码修改为 def WeightedCrossEntropy(z, targets): return calc_err(z, targets, weights) 所以测试和损失函数都调用 calc_err,但仍然得到相同的结果。请指教。谢谢!
    • 如果输入相同,训练数据和测试数据的差异可能来自overfitting。您应该验证 calc_err 是否为训练数据输出与第一次训练相同的指标,如果是,则这是一个典型的过度拟合问题。有几种方法可以解决过拟合问题,包括但不限于在模型中添加 dropout、在学习器中使用 L1/L2 正则化等。
    • 你是对的,KeD。这似乎确实是由过度拟合引起的。我将 L2 正则化从 0.0001 增加到 1.0,测试误差将持续减少 10 个 epoch。我尝试了其他几个值,但都在 10 个时期以下。我们使用 ResNet 20 层,有 14000 个样本和 64x64x3 输入,我们还能做些什么来减少过拟合?
    • 请查看this slide
    【解决方案2】:

    以下是预先计算权重的方式:

    def ColBasedCustomWeight(nClass) :
        ratio = 1.0
        pfSum = [0] * nClass
        pWs = [[0 for x in range(nClass)] for y in range(nClass)]
        for j in range(nClass):
            for i in range(nClass):
                n = i - j
                if n > 0: 
                    # false negative if j = 0
                    pWs[j][i] = math.pow(1.5,ratio*n) if j == 0 else math.pow(1.2,ratio*n) 
                elif n < 0:
                    # false positive if i = 0
                    pWs[j][i] = math.pow(1.5, -ratio*n) if i == 0 else math.pow(1.2, -ratio*n)
                else: 
                    pWs[j][i] = 1.0
                pfSum[i] += pWs[j][i]
    
        #normalize the weights to nClass
        for  j in range(nClass):
            for i in range(nClass):
                pWs[j][i] *= nClass / pfSum[i]
    
        return pWs
    

    权重定义或计算有什么问题吗?

    【讨论】:

      猜你喜欢
      • 2021-09-27
      • 2020-12-21
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 2018-02-24
      • 2019-07-28
      • 2020-10-05
      • 1970-01-01
      相关资源
      最近更新 更多