(已添加此问题的更新.)
我是比利时根特大学的研究生; 我的研究是用深度卷积神经网络进行情感识别.我正在使用Caffe框架来实现CNN.
最近我遇到了关于班级失衡的问题.我正在使用9216个训练样本,约 5%标记为阳性(1),其余样品标记为阴性(0).
我正在使用SigmoidCrossEntropyLoss图层来计算损失.在训练时,即使在几个时期之后,损失也会减少并且准确度非常高.这是由于不平衡:网络总是预测为负(0).(精确度和召回率均为零,支持此声明)
为了解决这个问题,我想根据预测 - 真值组合来衡量对损失的贡献(严厉惩罚假阴性).我的导师/教练还建议我在通过随机梯度下降(sgd)反向传播时使用比例因子:该因子将与批次中的不平衡相关联.仅包含负样本的批次根本不会更新权重.
我只向Caffe添加了一个自定义图层:报告其他指标,如精度和召回.我对Caffe代码的经验有限,但我有很多编写C++代码的专业知识.
任何人都可以帮助我或指出我如何调整SigmoidCrossEntropyLoss和Sigmoid层以适应以下变化:
提前致谢!
我按照Shai的建议加入了InfogainLossLayer.我还添加了另一个自定义层,H根据当前批次中的不平衡构建了infogain矩阵.
目前,矩阵配置如下:
H(i, j) = 0 if i != j
H(i, j) = 1 - f(i) if i == j (with f(i) = the frequency of class i in the batch)
Run Code Online (Sandbox Code Playgroud)
我计划将来为矩阵试验不同的配置.
我已经用10:1的不平衡测试了这个.结果表明网络现在正在学习有用的东西:( 30个时期后的结果)
我希望InfogainLoss在我的模型中使用类型的损失层.但我很难正确定义它.
关于INFOGAIN_LOSS图层的使用是否有任何教程/示例?
这个层的输入,类概率,应该是SOFTMAX层的输出,还是足以输入完全连接层的"顶部"?
INFOGAIN_LOSS需要三个输入:类概率,标签和矩阵H.矩阵H可以作为层参数提供infogain_loss_param { source: "fiename" }.
假设我有一个计算一个Python脚本H的numpy.array形状(L,L)与dtype='f4'(其中L是标签在我的模型的数量).
如何将我转换numpy.array为binproto可以作为infogain_loss_param { source }模型提供的文件?
假设我想H作为损失层的第三个输入(底部)提供(而不是作为模型参数).我怎样才能做到这一点?
我是否定义了一个"顶部"的新数据层H?如果是这样,那么每次训练迭代都不会增加该层的数据,就像训练数据增加一样?如何定义多个不相关的输入"数据"层,以及caffe如何知道从批处理批量读取训练/测试"数据"层,而从H"数据"层知道只读一次所有的训练过程?
如果我Softmax Activation像这样设置最后一层,我正在用unet进行图像语义分割工作:
...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
conv10 = (Activation('softmax'))(conv9)
model = Model(inputs, conv10)
return model
...
Run Code Online (Sandbox Code Playgroud)
然后使用即使只有一个训练图像loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False)
,训练也不会收敛。
但是,如果我没有Softmax Activation像这样设置最后一层:
...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
model = Model(inputs, conv9)
return model
...
Run Code Online (Sandbox Code Playgroud)
然后使用loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
训练将收敛为一个训练图像。
我的groundtruth数据集是这样生成的:
X = []
Y = []
im = cv2.imread(impath)
X.append(im)
seg_labels = np.zeros((height, width, n_classes))
for spath in segpaths:
mask = cv2.imread(spath, 0)
seg_labels[:, …Run Code Online (Sandbox Code Playgroud) 我有一个多标签分类,其中每个目标都是一个不互斥的 1 和 0 向量(为了清楚起见,我的目标类似于[0, 1, 0, 0, 1, 1, ... ])。
到目前为止我的理解是:
我应该使用二元交叉熵函数。(如本答案所述)
另外,我知道这tf.keras.losses.BinaryCrossentropy()是围绕 tensorflow 的sigmoid_cross_entropy_with_logits. 这可以与from_logits True或一起使用False。(如本问题所述)
由于sigmoid_cross_entropy_with_logits自己执行 sigmoid,它期望输入在 [-inf,+inf] 范围内。
tf.keras.losses.BinaryCrossentropy(),当网络实现自己最后一层的 sigmoid 激活时,必须与 一起使用from_logits=False。然后它将推断 sigmoid 函数并将输出传递给sigmoid_cross_entropy_with_logits将再次执行 sigmoid的输出。然而,由于 sigmoid/logit 函数的渐近线,这可能会导致数值问题。
为了提高数值稳定性,我们可以避免最后一个 sigmoid 层并使用 tf.keras.losses.BinaryCrossentropy(from_logits=False)
题:
如果我们使用tf.keras.losses.BinaryCrossentropy(from_logits=False),我应该使用什么目标?我是否需要更改 one-hot 向量的目标?
我想我应该在推理时将 sigmoid 激活应用于网络输出。有没有办法添加仅在推理模式下而不是在训练模式下活动的 sigmoid 层?