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
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).
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)
Replace len(y_true)
with y_true.shape[0]
If on an older version of TensorFlow use y_true.get_shape()