在 Keras 中使用自定义成本函数时出现切片错误

Slicing Error when using custom cost function in Keras

我有示例数据。此数据用于设置预测变量 (x) 和响应变量 (y):

x 具有 Age_Years 特征,y 具有 Age_Yearstarget 特征:

我有一个接受多个参数的自定义成本函数:

# this gives the y_pred values
def calc_prob(param1, param2, param3, age):
    prob = (((100*param1*pow((100/param3),-(pow((age/param2),param1))))*pow(age/param2,param1)*math.log(100/param3))/age)/100
    return prob

# this serves as the custom cost function
def brier_score(y_pred, y_true):
  prob = calc_prob(y_pred[:, 0], y_pred[:, 1], y_pred[:, 2], y_true['Age_Years'])
  brier_score = tf.reduce_mean((prob - y_true['target']) ** 2, axis=1)
  return brier_score

最终,我想要一个输出来构建一个最小化 brier_score() 函数的 3 参数模型。如果我尝试构建和 运行 模型,我会收到错误消息:

from keras import models
from keras import layers


def build_model():
    model = models.Sequential()
    model.add(layers.Dense(1, activation='relu', input_shape=(x.shape[1],)))
    model.add(layers.Dense(5, activation='relu'))
    model.add(layers.Dense(3, activation='softmax'))
    model.compile(loss=losses, optimizer='adam', metrics=['accuracy'])
    return model

model = build_model()
losses=[brier_score]
model.compile(loss=losses, optimizer='adam', metrics=['accuracy'])
# this line causes the error
model.fit(x=x, y=y, epochs=100, verbose=0)

ValueError: slice index 2 of dimension 1 out of bounds. for '{{node brier_score/strided_slice_2}} = StridedSlice[Index=DT_INT32, T=DT_FLOAT, begin_mask=1, ellipsis_mask=0, end_mask=1, new_axis_mask=0, shrink_axis_mask=2](Cast, brier_score/strided_slice_2/stack, brier_score/strided_slice_2/stack_1, brier_score/strided_slice_2/stack_2)' with input shapes: [?,2], [2], [2], [2] and with computed input tensors: input[1] = <0 2>, input[2] = <0 3>, input[3] = <1 1>.

您混淆了 y_truey_predbrier_score 中的顺序。这是一个工作示例:

import tensorflow as tf
from keras import models
from keras import layers
import pandas as pd
import numpy as np

x = np.random.random((500, 1))
y = {'Age_Years': np.squeeze(x, axis=1), 'target': np.random.randint(2, size=500)}

def calc_prob(param1, param2, param3, age):
    prob = (((100*param1*tf.math.pow((100/param3),-(tf.math.pow((age/param2),param1))))*tf.math.pow(age/param2,param1)*tf.math.log(100/param3))/age)/100
    return prob

# this serves as the custom cost function
def brier_score(y_true, y_pred):
  prob = calc_prob(y_pred[:, 0], y_pred[:, 1], y_pred[:, 2], tf.cast(y_true['Age_Years'], dtype=tf.float32))
  brier_score = tf.reduce_mean((prob - tf.cast(y_true['target'], dtype=tf.float32)) ** 2, axis=-1, keepdims=True)
  return brier_score


def build_model():
    model = models.Sequential()
    model.add(layers.Dense(1, activation='relu', input_shape=(x.shape[1],)))
    model.add(layers.Dense(5, activation='relu'))
    model.add(layers.Dense(3, activation='softmax'))
    return model

model = build_model()
optimizer = tf.keras.optimizers.Adam()
batch_size = 10
dataset = tf.data.Dataset.from_tensor_slices((x,y)).batch(batch_size)

epochs = 2
for epoch in range(epochs):
    print("\nStart of epoch %d" % (epoch,))

    for step, (x_batch_train, y_batch_train) in enumerate(dataset):
        with tf.GradientTape() as tape:
            logits = model(x_batch_train, training=True)
            loss_value = brier_score(y_batch_train, logits)

        grads = tape.gradient(loss_value, model.trainable_weights)
        optimizer.apply_gradients(zip(grads, model.trainable_weights))