keras TensorFlow的自定义度量函数无法正常工作,它始终输出零

hjzp0vay  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(75)

<tf.Tensor:shape=(4,),dtype=float32,numpy=array([ 1.,1.1,57.9,1.0243483],type=float32)> custom_binary_crossentropy工作正常

def custom_binary_crossentropy(y_true, y_pred): 
    y_true_first = y_true[:, 0]
    y_pred_expanded = tf.expand_dims(y_pred, axis=-1)
    # Calculate binary crossentropy between y_true_first and y_pred
    loss = tf.keras.losses.binary_crossentropy(y_true_first, y_pred_expanded)
    return loss

字符串
但自定义度量函数不:

def up_profit_metric(y_true, y_pred):
    y_pred_class = tf.cast(tf.argmax(y_pred, axis=-1), tf.int32)
    answer = tf.cast(y_true[:, 0], tf.int32)
    go_high = y_true[:, 1]
    price_now = y_true[:, 2]
    perc_inH = y_true[:, 3]
    q_to_buy = tf.cast(tf.round(1000 / price_now), tf.float32)
    deal_amt = q_to_buy * price_now
    # True positive condition
    condition1 = tf.logical_and(tf.equal(answer, y_pred_class), tf.equal(y_pred_class, tf.constant([1])))
    profit1 = deal_amt * go_high / 100
    # False positive condition
    condition2 = tf.logical_and(tf.not_equal(answer, y_pred_class), tf.equal(y_pred_class, tf.constant([1])))
    profit2 = deal_amt * perc_inH / 100
    # Select the appropriate profit based on conditions
    profit = tf.where(condition1, profit1, tf.where(condition2, profit2, tf.cast(0, dtype=tf.float32)))
    # Sum the profits
    total_profit = tf.reduce_sum(profit)
    return total_profit


它确实适用于虚构的例子:

y_true_example = tf.constant([[1.0, 1.1, 45.91, 1.26], [1, 0.9, 30.0, 0.1], [0.0, 0.9, 30.0, 0]], dtype=tf.float32)
y_pred_example = tf.constant([[0.2, 0.8], [0.3, 0.7], [0.3, 0.7]], dtype=tf.float32)
profit_example = up_profit_metric(y_true_example, y_pred_example)


但在实际模型中不起作用,它在每个历元上输出零:

lstm_up2 = Sequential()
lstm_up2.add(LSTM(8, activation='LeakyReLU', dropout = .0))  #linear  relu , activation='relu' LeakyReLU
lstm_up2.add(Dense(1, activation='sigmoid'))
lstm_up2.compile(optimizer='adam', loss=custom_binary_crossentropy, metrics = [up_profit_metric]) 
es_up = EarlyStopping(monitor='val_precision', mode='max', min_delta = 0.01,verbose=1, patience=25)
lstm_up2.fit(
    X_train_reshaped, y_tr_h, y_tr_h, 
    validation_data=(X_val_reshaped, y_val_h), 
    epochs=70, batch_size=24, shuffle=False            )


我花了三天时间来解决它,为此我在这里注册了

wj8zmpe1

wj8zmpe11#

这是因为你的模型输出有1个单位和形状(n,),而你的示例输出有形状(n, 2)。所以你的自定义指标总是计算出相同的东西,因为argmax操作总是返回0。
如果你使用这个模型作为分类器,你需要n个输出单元来表示n个可能的类别。然后,根据类别的互斥性,可能需要sigmoid或softmax激活。
它总是返回0:

y_pred_class = tf.cast(tf.argmax(y_pred, axis=-1), tf.int32)

字符串
后面这一行总是计算为False

condition1 = tf.logical_and(
    tf.equal(answer, y_pred_class), 
    tf.equal(y_pred_class, tf.constant([1])) # this never is true
)


证据A -这行不通

for i in range(10):
    inputs = tf.random.uniform((3, 1))
    print(up_profit_metric(y_true_example, inputs))
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)

的字符串
证据B -这起作用

for i in range(10):
    inputs = tf.random.uniform((3, 2)) # if you had two output units
    print(up_profit_metric(y_true_example, inputs))
tf.Tensor(8.91, shape=(), dtype=float32)
tf.Tensor(20.020222, shape=(), dtype=float32)
tf.Tensor(11.110221, shape=(), dtype=float32)
tf.Tensor(20.020222, shape=(), dtype=float32)
tf.Tensor(8.91, shape=(), dtype=float32)
tf.Tensor(8.91, shape=(), dtype=float32)
tf.Tensor(8.91, shape=(), dtype=float32)
tf.Tensor(8.91, shape=(), dtype=float32)
tf.Tensor(11.110221, shape=(), dtype=float32)
tf.Tensor(20.020222, shape=(), dtype=float32)

的字符串

相关问题