我想为我的模型创建一个新的评估指标(平均倒数排名) 假设我有:
'use strict';
var _ = require('lodash');
var Contact = require('./contact.model');
// Get list of contacts
exports.index = function(req, res) {
// Connect to the db
Contact.find(function (err, contacts) {
if(err) { return handleError(res, err); }
return res.json(200, contacts);
});
} ;
// Creates a new contact in datastore.
exports.create = function(req, res) {
Contact.create(req.body, function(err, contact) {
if(err) { return handleError(res, err); }
return res.json(201, contact);
});
};
// Updates an existing contact in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Contact.findById(req.params.id, function (err, contact) {
if (err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
var updated = _.merge(contact, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, contact);
});
});
};
// delete an existing contact in datastore.
exports.delete = function(req, res) {
Contact.findById(req.params.id, function (err, contact) {
if(err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
contact.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(201);
});
});
};
function handleError(res, err) {
return res.send(500, err);
};
张量形状logits
和(None, n_class)
形状y_target
的张量包含(None, )
到int
的{{1}}个值。0
将是批量大小。 我希望我的输出是形状n_class-1
的张量,具有相应None
的倒数等级。
首先,我需要在(None, )
中对元素进行排名,然后在索引y_target
中获取元素的等级,然后获得其倒数(或x + 1的倒数,取决于排名程序)。
一个简单的例子(单次观察):
如果我的logits
和y_target
,
那么排名是y_target=1
倒数为logits=[0.5, -2.0, 1.1, 3.5]
。
这里的挑战是在轴上应用函数,因为等级是未知的(在图级别)。
我设法使用logits_rank=[3, 4, 2, 1]
获得了一些结果,但仅限于1.0 / logits_rank[y_target] = 0.25
。
非常感谢任何帮助!
答案 0 :(得分:3)
解决!
def tf_get_rank_order(input, reciprocal):
"""
Returns a tensor of the rank of the input tensor's elements.
rank(highest element) = 1.
"""
assert isinstance(reciprocal, bool), 'reciprocal has to be bool'
size = tf.size(input)
indices_of_ranks = tf.nn.top_k(-input, k=size)[1]
indices_of_ranks = size - tf.nn.top_k(-indices_of_ranks, k=size)[1]
if reciprocal:
indices_of_ranks = tf.cast(indices_of_ranks, tf.float32)
indices_of_ranks = tf.map_fn(
lambda x: tf.reciprocal(x), indices_of_ranks,
dtype=tf.float32)
return indices_of_ranks
else:
return indices_of_ranks
def get_reciprocal_rank(logits, targets, reciprocal=True):
"""
Returns a tensor containing the (reciprocal) ranks
of the logits tensor (wrt the targets tensor).
The targets tensor should be a 'one hot' vector
(otherwise apply one_hot on targets, such that index_mask is a one_hot).
"""
function_to_map = lambda x: tf_get_rank_order(x, reciprocal=reciprocal)
ordered_array_dtype = tf.float32 if reciprocal is not None else tf.int32
ordered_array = tf.map_fn(function_to_map, logits,
dtype=ordered_array_dtype)
size = int(logits.shape[1])
index_mask = tf.reshape(
targets, [-1,size])
if reciprocal:
index_mask = tf.cast(index_mask, tf.float32)
return tf.reduce_sum(ordered_array * index_mask,1)
# use:
recip_rank = tf.reduce_mean(
get_reciprocal_rank(logits[-1],
y_,
True)
答案 1 :(得分:0)
您可以了解如何在tensorflow_ranking软件包https://github.com/tensorflow/ranking/blob/master/tensorflow_ranking/python/metrics.py
中实现MRR。他们深入研究包装器,实际上在tensorflow.python.ops.gen_nn_ops.top_kv2
中调用了排序功能,该功能是从C ++代码生成的,以使处理速度更快。
您当然可以编写一些O(n)
算法而无需通过计算每个实例的较小索引数来进行排序。通过它可能不如C ++代码快。您可以取出logits
并使用以下代码进行计算。
def rev_rank(id: int, logit: list):
return 1.0 / sum([logit[id] <= i for i in logit])
rev_rank_sum = sum(map(rev_rank, y_target, logits))