【发布时间】:2021-06-09 18:04:16
【问题描述】:
我想创建一个依赖于元数据的自定义损失函数。在最简单的形式中,我想将损失乘以每批次的权重(由元数据确定)。
为简单起见,请考虑直接传递所需的权重。以下是损失函数的两种尝试:
def three_arg_loss(loss_func):
""" a loss function that takes 3 args"""
def _loss(target,output,weight):
return weight*loss_func(target,output)
return _loss
def target_list_loss(loss_func):
""" a loss function that expects the target arg to be [target,weight]"""
def _loss(target,output):
weight=target[1]
target=target[0]
return weight*loss_func(target,output)
return _loss
当我尝试训练时,我得到了以下结果:
-
three_arg_loss:TypeError: tf___loss() missing 1 required positional argument: 'weight'
当然,我检查了三倍,并且确实通过了 3 个参数
-
target_list_loss:ValueError: Shapes (None, None, None) and (None, None, None, 4) are incompatible
在三重检查之后,我确实传递了[target,weight] 作为目标参数。我在这里担心我可能弄乱了损失函数的参数顺序,所以我翻转它们只是为了确定并得到ValueError: Shapes (None, None, 4) and (None, None, None, None) are incompatible
想法?具有依赖于其他数据(在我的情况下是地理位置)的损失函数的正确/最佳方法是什么?
按照下面的要求,这里是一个显示错误的完整(但愚蠢)示例
BATCH_SIZE=2
SIZE=3
STEPS=8
EPOCHS=3
NB_CLASSES=4
def gen_inpt(ch_in):
return tf.random.uniform((BATCH_SIZE,SIZE,SIZE,ch_in))
def gen_targ(nb_classes):
t=tf.random.uniform((BATCH_SIZE,SIZE,SIZE),maxval=nb_classes,dtype=tf.int32)
return tf.keras.utils.to_categorical(t,num_classes=nb_classes)
def gen(ch_in,ch_out):
return ( ( gen_inpt(ch_in), gen_targ(ch_out) ) for b in range(BATCH_SIZE*STEPS*EPOCHS) )
def gen_targ_list(ch_in,ch_out):
return ( ( gen_inpt(ch_in), [gen_targ(ch_out), tf.fill(1,2222)] ) for b in range(BATCH_SIZE*STEPS*EPOCHS) )
def gen_3args(ch_in,ch_out):
return ( ( gen_inpt(ch_in), gen_targ(ch_out), tf.fill(1,10000.0) ) for b in range(BATCH_SIZE*STEPS*EPOCHS) )
class Toy(tf.keras.Model):
def __init__(self,nb_classes):
super(Toy, self).__init__()
self.l1=layers.Conv2D(32,3,padding='same')
self.l2=layers.Conv2D(nb_classes,3,padding='same')
def call(self,x):
x=self.l1(x)
x=self.l2(x)
return x
def test_loss(loss_func):
def _loss(target,output):
return loss_func(target,output)
return _loss
def target_list_loss(loss_func):
def _loss(target,output):
weight=target[1]
target=target[0]
return weight*loss_func(target,output)
return _loss
def three_arg_loss(loss_func):
def _loss(target,output,weight):
return weight*loss_func(target,output)
return _loss
loss_func=tf.keras.losses.CategoricalCrossentropy()
loss_test=test_loss(loss_func)
loss_targ_list=target_list_loss(loss_func)
loss_3arg=three_arg_loss(loss_func)
def test_train(loss,gen):
try:
model=Toy(NB_CLASSES)
model.compile(optimizer='adam',
loss=loss,
metrics=['accuracy'])
model.fit(gen(6,NB_CLASSES),steps_per_epoch=STEPS,epochs=EPOCHS)
except Exception as e:
print(e)
#
# RUN TESTS
#
test_train(loss_test,gen)
test_train(loss_targ_list,gen_targ_list)
test_train(loss_3arg,gen_3args)
扩展损失的示例(给出相同的结果)
class TargListLoss(tf.keras.losses.Loss):
def __init__(self,loss_func):
super(TargListLoss,self).__init__()
self.loss_func=loss_func
def call(self,target,output):
weight=target[1]
target=target[0]
return weight*self.loss_func(target,output)
【问题讨论】:
标签: tensorflow machine-learning neural-network tensorflow2.0 loss-function