语义分割的样本权重



我尝试解决Keras和Tensorflow2后端的语义分割问题。我尝试将每个像素标记为具有分类交叉熵的 22 个类之一。我的输入和输出的形状是

Input: (None, 224, 224, 3)
Output: (None, 224, 224, 23) 22 and 1 for background

我想为每个样本添加权重,以尝试使用我的模型进行伪标记。对于样品重量,我尝试创建一个样品重量数组,它是一个一维数组,长度与批量大小相同。但它失败并给出了以下错误:

weights can not be broadcast to values. values.rank=3. weights.rank=1.

然后我尝试给出 3D 数组 (16, 224, 224( 作为样本权重,批量大小为 16,它给出了以下错误:

Found a sample_weight array with shape (16, 224, 224).
In order to use timestep-wise sample weights, you should specify sample_weight_mode="temporal" in compile(). 
If you just mean to use sample-wise weights, make sure your sample_weight array is 1D.

我设法解决了具有多个输出并在model.compile中使用loss_weights的 TF2 的类似问题。这样,用于训练网络的最终损失是每个损失的加权总和。就我而言,我有 2 个类而不是 23 个类,因此您需要修改这 23 个类的代码。另请注意,代码中的第c9层有 3 个过滤器,因此您可能需要增加它。

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.losses import BinaryCrossentropy
from tensorflow.keras.optimizers import Adam
# build your CNN
inputs = Input((224, 224, 1), name='inputs')
c1 = Conv2D(64, (3, 3), activation='relu', padding='same')(inputs)
...
c9 = Conv2D(3, (3, 3), activation='relu',padding='same')(c9)
output_0 = Conv2D(1, (1, 1), name='class0')(c9)
output_1 = Conv2D(1, (1, 1), name='class1')(c9)
model = Model(inputs=inputs, outputs=[output_0, output_1])
model.compile(optimizer=Adam(learning_rate=0.001, name='adam'),
loss=[BinaryCrossentropy(from_logits=True), BinaryCrossentropy(from_logits=True)],
loss_weights=[1, 1000],
metrics=[["accuracy"], ["accuracy", "mse"]])

此外,您可以在数据生成器中定义一个采样 pdf,以便例如,向网络提供属于一个类的更多对象而不是背景的对象。这种效果可能类似于使用加权损失函数。最后,网络尝试最小化平均损失值,因此,如果您添加一个类的更多样本,则该平均损失值将受到该类结果的精确影响。

最新更新