Keras自定义指标迭代

时间:2017-04-23 21:53:17

标签: python neural-network deep-learning keras

我对Keras很新,我正在尝试定义自己的指标。它计算一致性指数,这是衡量回归问题的指标。

def cindex_score(y_true, y_pred):
    sum = 0
    pair = 0    
    for i in range(1, len(y_true)):
        for j in range(0, i):
            if i is not j:
                if(y_true[i] > y_true[j]):
                  pair +=1
                  sum +=  1* (y_pred[i] > y_pred[j]) + 0.5 * (y_pred[i] == y_pred[j])
    if pair is not 0:
        return sum/pair
    else:
        return 0


def baseline_model(hidden_neurons, inputdim):
    model = Sequential()
    model.add(Dense(hidden_neurons, input_dim=inputdim, init='normal', activation='relu'))
    model.add(Dense(hidden_neurons, init='normal', activation='relu'))
    model.add(Dense(1, init='normal')) #output layer

    model.compile(loss='mean_squared_error', optimizer='adam', metrics=[cindex_score])
    return model

def run_model(P_train, Y_train, P_test, model):
    history = model.fit(numpy.array(P_train), numpy.array(Y_train), batch_size=50, nb_epoch=200)
    plotLoss(history)
    return model.predict(P_test)

baseline_model,run_model和cindex_score函数在one.py中,以下函数在two.py中我调用模型,

def experiment():
    hidden_neurons = 250
    dmodel=baseline_model(hidden_neurons, train_pair.shape[1])
    predicted_Y = run_model(train_pair,train_Y, test_pair, dmodel)

但我得到以下错误,“类型'Tensor'的对象没有len()”。它也不适用于shape属性。

例如,y_true表示为Tensor(“dense_4_target:0”,shape =(?,?),dtype = float32),其形状为Tensor(“strided_slice:0”,shape =(),dtype = int32 )。

请问你如何在Tensor对象中进行迭代?

最佳,

3 个答案:

答案 0 :(得分:2)

如果您习惯使用tensorflow,则可以尝试使用此代码:

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)

以下是一些验证两种方法都是等效的代码:

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)

请注意,这仅适用于1D张量(很少会出现在keras中)。

答案 1 :(得分:2)

我使用@Pedia代码进行3D张量计算,以计算多标签分类的等级损失:

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)

答案 2 :(得分:1)

len(y_true)替换为y_true.shape[0]

如果旧版TensorFlow使用y_true.get_shape()