Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define pinball loss function in keras with tensorflow backend

I'm trying to define a pinbal loss function for implementing a 'quantile regression' in neural network with Keras (with Tensorflow as backend).

The definition is here: pinball loss

It's hard to implement traditional K.means() etc. function since they deal with the whole batch of y_pred, y_true, yet I have to consider each component of y_pred, y_true, and here's my original code:

def pinball_1(y_true, y_pred):
    loss = 0.1
    with tf.Session() as sess:
        y_true = sess.run(y_true)
        y_pred = sess.run(y_pred)
    y_pin = np.zeros((len(y_true), 1))
    y_pin = tf.placeholder(tf.float32, [None, 1])
    for i in range((len(y_true))):
        if y_true[i] >= y_pred[i]:
            y_pin[i] = loss * (y_true[i] - y_pred[i])
        else:
            y_pin[i] = (1 - loss) * (y_pred[i] - y_true[i])
    pinball = tf.reduce_mean(y_pin, axis=-1)
    return K.mean(pinball, axis=-1)

sgd = SGD(lr=0.1, clipvalue=0.5)
model.compile(loss=pinball_1, optimizer=sgd)
model.fit(Train_X, Train_Y, nb_epoch=10, batch_size=20, verbose=2)

I attempted to transfer y_pred, y_true is to vectorized data structure so I can cite them with index, and deal with individual components, yet it seems problem occurs due to the lack of knowledge in treating y_pred, y_true individually.

I tried to dive into lines directed by errors, yet I almost get lost.

InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'dense_16_target' with dtype float
 [[Node: dense_16_target = Placeholder[dtype=DT_FLOAT, shape=[], _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

How can I fix it? Thanks!

like image 622
Dahua Gan Avatar asked Apr 01 '17 01:04

Dahua Gan


2 Answers

I’ve figured this out by myself with Keras backend:

def pinball(y_true, y_pred):
    global i
    tao = (i + 1) / 10
    pin = K.mean(K.maximum(y_true - y_pred, 0) * tao +
                 K.maximum(y_pred - y_true, 0) * (1 - tao))
    return pin
like image 160
Dahua Gan Avatar answered Nov 13 '22 15:11

Dahua Gan


This is a more efficient version:

def pinball_loss(y_true, y_pred, tau):
    err = y_true - y_pred
    return K.mean(K.maximum(tau * err, (tau - 1) * err), axis=-1)

Using an additional parameter and the functools.partial function is IMHO the cleanest way of setting different values for tau:

model.compile(loss=functools.partial(pinball_loss, tau=0.1), optimizer=sgd)
like image 39
Daniel Sch. Avatar answered Nov 13 '22 13:11

Daniel Sch.