Home > Net >  Slicing Error when using custom cost function in Keras
Slicing Error when using custom cost function in Keras

Time:02-11

I have example data. This data is used to set the predictor (x) and response (y) variables:

x has an Age_Years feature and y has Age_Years and target features:

enter image description here

enter image description here

I have a custom cost function that accepts multiple parameters:

# 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

Ultimately, I want an output that builds a 3-parameter model that minimizes the brier_score() function. If I try to build and run the model, I get an error:

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>.

CodePudding user response:

You are mixing up the order of y_true and y_pred in brier_score. Here is a working example:

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))
  • Related