我希望在我的模型中使用InfogainLoss
类型的丢失层。但我在定义它时遇到了困难。
是否有关于INFOGAIN_LOSS
图层使用的教程/示例?
此层的输入,类概率,应该是SOFTMAX
图层的输出,还是足以输入" top"完全连接的层?
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
作为第三个输入(底部)提供给损失层(而不是作为模型参数)。我怎么能这样做?
我是否定义了一个新的数据层" top"是H
?如果是这样,那么每次训练迭代都不会增加该层的数据,就像训练数据增加一样?
如何定义多个不相关的输入"数据"层,以及咖啡如何知道从培训/测试中读取数据"一批又一批,而来自H
"数据"它知道在所有培训过程中只读一次吗?
答案 0 :(得分:10)
1。是否有关于 InfogainLoss 图层使用的教程/示例?:
可以找到一个很好的例子here:使用 InfogainLoss 来解决类不平衡问题。
2。该层的输入(类概率)应该是 Softmax 层的输出吗?
从历史上看,根据Yair's answer,答案过去是 YES 。 "InfogainLoss"
的旧实现需要是"Softmax"
图层或任何其他图层的输出,以确保输入值在[0..1]范围内。
OP注意到在"InfogainLoss"
图层上使用"Softmax"
会导致数值不稳定。 His pull request,将这两个层组合成一个层(很像"SoftmaxWithLoss"
层),于2017年4月14日被接受并合并到官方Caffe存储库中。该组合层的数学给出here。
升级后的图层"外观和感觉"除了不再需要通过"Softmax"
层明确传递输入之外,它与旧版本完全相同。
3。如何将numpy.array转换为binproto文件:
在python中
H = np.eye( L, dtype = 'f4' )
import caffe
blob = caffe.io.array_to_blobproto( H.reshape( (1,1,L,L) ) )
with open( 'infogainH.binaryproto', 'wb' ) as f :
f.write( blob.SerializeToString() )
现在,您可以使用INFOGAIN_LOSS
作为参数将H
图层添加到模型原型文本中:
layer {
bottom: "topOfPrevLayer"
bottom: "label"
top: "infoGainLoss"
name: "infoGainLoss"
type: "InfogainLoss"
infogain_loss_param {
source: "infogainH.binaryproto"
}
}
4。如何加载H
作为数据层的一部分
目前还没有办法让数据层以不同的速率加载输入。每个前向传递所有数据层都将前进。但是,常量H输入可以通过使输入lmdb / leveldb / hdf5文件仅为H来完成,因为数据层将循环并继续加载相同的H.这显然浪费了磁盘IO。
答案 1 :(得分:2)
该图层正在总结
-log(p_i)
所以p_i需要在(0,1)中作为损失函数才有意义(否则更高的置信度得分会产生更高的损失)。请参阅下面的曲线,了解log的值(p )。
我认为他们不得不总结为1,但是通过Softmax图层传递它们将实现这两个属性。
答案 2 :(得分:1)
因为我不得不搜索许多网站才能迷惑整个网站 代码,我以为我分享我的实现:
用于计算每个类别的权重的H矩阵的Python层:
import numpy as np
import caffe
class ComputeH(caffe.Layer):
def __init__(self, p_object, *args, **kwargs):
super(ComputeH, self).__init__(p_object, *args, **kwargs)
self.n_classes = -1
def setup(self, bottom, top):
if len(bottom) != 1:
raise Exception("Need (only) one input to compute H matrix.")
params = eval(self.param_str)
if 'n_classes' in params:
self.n_classes = int(params['n_classes'])
else:
raise Exception('The number of classes (n_classes) must be specified.')
def reshape(self, bottom, top):
top[0].reshape(1, 1, self.n_classes, self.n_classes)
def forward(self, bottom, top):
classes, cls_num = np.unique(bottom[0].data, return_counts=True)
if np.size(classes) != self.n_classes or self.n_classes == -1:
raise Exception("Invalid number of classes")
cls_num = cls_num.astype(float)
cls_num = cls_num.max() / cls_num
weights = cls_num / np.sum(cls_num)
top[0].data[...] = np.diag(weights)
def backward(self, top, propagate_down, bottom):
pass
和来自train_val.prototxt的相关部分:
layer {
name: "computeH"
bottom: "label"
top: "H"
type: "Python"
python_param {
module: "digits_python_layers"
layer: "ComputeH"
param_str: '{"n_classes": 7}'
}
exclude { stage: "deploy" }
}
layer {
name: "loss"
type: "InfogainLoss"
bottom: "score"
bottom: "label"
bottom: "H"
top: "loss"
infogain_loss_param {
axis: 1 # compute loss and probability along axis
}
loss_param {
normalization: 0
}
exclude {
stage: "deploy"
}
}