在未知等级的Tensor上应用函数(平均倒数等级)

时间:2017-04-05 16:54:24

标签: python python-3.x tensorflow

我想为我的模型创建一个新的评估指标(平均倒数排名) 假设我有:

  • '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的倒数,取决于排名程序)。

一个简单的例子(单次观察):
如果我的logitsy_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

非常感谢任何帮助!

2 个答案:

答案 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))