一种可能性是采用具有独立分类和回归头的障碍模型。分类应理解为产品是否已售出(非零回归值)或未售出(回归值为零)。好处是可以手动将回归值归零,以防分类器投票给负类。tf.keras例如,这是一个适用于图像回归的双头模型。
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.applications import ResNet50
...
input_shape = (256,256,3)
inputs = Input(input_shape)
# feature extration
base_model = ResNet50(
input_shape=input_shape,
weights='imagenet',
include_top=False,
)
base_model = base_model(inputs)
# bottleneck
bottleneck = GlobalAveragePooling2D()(base_model)
bottleneck = Dense(256, activation='relu')(bottleneck)
bottleneck = Dropout(0.25)(bottleneck)
# classification head
clf = Dense(32, activation='relu')(bottleneck)
clf = Dropout(0.5)(clf)
clf = Dense(1, use_bias=False)(clf)
clf_output = Activation("sigmoid", name="clf_head_output")(clf)
# regression head
regr = Dense(32, activation='relu')(bottleneck)
regr = Dropout(0.5)(regr)
regr = Dense(1, use_bias=False)(regr)
regr_output = Activation("relu", name="regr_head_output")(regr) #<- change activation according to your task
# build model
model = Model(inputs=[inputs], outputs=[regr_output, clf_output,])
通常会选择mean_absolute_error或mean_squared_error作为回归输出损失。在 ZIP(零膨胀泊松)分布的情况下,您可能面临的问题是模型的预测可能往往低于基本事实,尤其是对于最高回归值。如果是这种情况,那么这可能是因为模型因预测错误的高回归值而受到最大的惩罚。
标准化回归输出很重要,可以尝试诸如boxcox 之类的技巧,但这可能很困难,请记住零在分布中具有特殊作用。如果回归任务有一定的下限(L)和上限(U),对我来说效果很好的一个技巧是将输出标准化为区间 [0,1] 并改用角度回归。这个想法是,然后原始 L 和 U 将彼此相同(回归值位于单位圆上)并且模型无论尝试从“上方”还是“下方”接近高/稀有值都会受到同等惩罚. 这也是我对tf.keras. 我建议使用这种方法使用sigmoid或剪裁relu(with max_value=1.)。
import tensorflow as tf
import tensorflow.keras.backend as K
PI = tf.constant(math.pi)
def angular_l1(y_true, y_pred): #y_true and y_pred should be in the inteval [0,1]
y_true = y_true*2*PI #<- scale values to [0,2pi]
y_pred = y_pred*2*PI #<- scale values to [0,2pi]
return K.mean(K.abs(tf.math.atan2(K.sin(y_true - y_pred), K.cos(y_true - y_pred))))