Keras custom metric iteration

前端 未结 3 2029
一整个雨季
一整个雨季 2021-01-18 11:16

I\'m pretty new to Keras and I\'m trying to define my own metric. It calculates concordance index which is a measure for regression problems.

def cindex_scor         


        
相关标签:
3条回答
  • 2021-01-18 11:32

    If you are comfortable using tensorflow, then you can try using this code instead:

    def cindex_score(y_true, y_pred):
    
        g = tf.subtract(tf.expand_dims(y_pred, -1), y_pred)
        g = tf.cast(g == 0.0, tf.float32) * 0.5 + tf.cast(g > 0.0, tf.float32)
    
        f = tf.subtract(tf.expand_dims(y_true, -1), y_true) > 0.0
        f = tf.matrix_band_part(tf.cast(f, tf.float32), -1, 0)
    
        g = tf.reduce_sum(tf.multiply(g, f))
        f = tf.reduce_sum(f)
    
        return tf.where(tf.equal(g, 0), 0.0, g/f)
    

    Here is some code that verifies that both approaches are equivalent:

    def _ref(J, K):
        _sum = 0
        _pair = 0
        for _i in range(1, len(J)):
            for _j in range(0, _i):
                if _i is not _j:
                    if(J[_i] > J[_j]):
                      _pair +=1
                      _sum +=  1* (K[_i] > K[_j]) + 0.5 * (K[_i] == K[_j])
        return 0 if _pair == 0 else _sum / _pair
    
    def _raw(J, K):
    
        g = tf.subtract(tf.expand_dims(K, -1), K)
        g = tf.cast(g == 0.0, tf.float32) * 0.5 + tf.cast(g > 0.0, tf.float32)
    
        f = tf.subtract(tf.expand_dims(J, -1), J) > 0.0
        f = tf.matrix_band_part(tf.cast(f, tf.float32), -1, 0)
    
        g = tf.reduce_sum(tf.multiply(g, f))
        f = tf.reduce_sum(f)
    
        return tf.where(tf.equal(g, 0), 0.0, g/f)
    
    
    for _ in range(100):
        with tf.Session() as sess:
            inputs = [tf.placeholder(dtype=tf.float32),
                      tf.placeholder(dtype=tf.float32)]
            D = np.random.randint(low=10, high=1000)
            data = [np.random.rand(D), np.random.rand(D)]
    
            r1 = sess.run(_raw(inputs[0], inputs[1]),
                          feed_dict={x: y for x, y in zip(inputs, data)})
            r2 = _ref(data[0], data[1])
    
            assert np.isclose(r1, r2)
    

    Please note that this only works for 1D-tensors (rarely a case you will have in keras).

    0 讨论(0)
  • 2021-01-18 11:41

    I used @Pedia code for 3D-tensors to compute Rank loss for multi label classification:

    def rloss(y_true, y_pred):
        g = tf.subtract(tf.expand_dims(y_pred[1], -1), y_pred[1])
        g = tf.cast(g == 0.0, tf.float32) * 0.5 + tf.cast(g > 0.0, tf.float32)
        f = tf.subtract(tf.expand_dims(y_true[1], -1), y_true[1]) > 0.0
        f = tf.matrix_band_part(tf.cast(f, tf.float32), -1, 0)
        g = tf.reduce_sum(tf.multiply(g, f))
        f = tf.reduce_sum(f)
    return tf.where(tf.equal(g, 0), 0.0, g/f)
    
    
    model = Sequential()
    model.add(Dense(label_length, activation='relu'))
    model.add(Dense(label_length, activation='relu'))
    model.add(Dense(label_length, activation='sigmoid'))
    model.summary()
    
    
    adgard = optimizers.Adagrad(lr=0.01, epsilon=1e-08, decay=0.0)
    model.compile(loss='binary_crossentropy',
              optimizer=adgard, metrics=[rloss])
    model.fit(X_train, y_train,
          batch_size=batch_size,
          epochs=n_epoch,
          validation_data=(X_test, y_test),
          shuffle=True)
    
    0 讨论(0)
  • 2021-01-18 11:41

    Replace len(y_true) with y_true.shape[0]

    If on an older version of TensorFlow use y_true.get_shape()

    0 讨论(0)
提交回复
热议问题