tensorflow可以很方便的添加用户自定义的operator(如果不添加也可以采用sklearn的auc计算函数或者自己写一个
但是会在python执行,这里希望在graph中也就是c++端执行这个计算)

这里根据工作需要添加一个计算auc的operator,只给出最简单实现,后续高级功能还是参考官方wiki

https://www.tensorflow.org/versions/r0.7/how_tos/adding_an_op/index.html

注意tensorflow现在和最初的官方wiki有变化,原wiki貌似是需要重新bazel编译整个tensorflow,然后使用比如tf.user_op.auc这样。

目前wiki给出的方式>=0.6.0版本,采用plug-in的方式,更加灵活可以直接用g++编译一个so载入,解耦合,省去了编译tensorflow过程,即插即用。

 
 

首先auc的operator计算的文件

 
 

tensorflow/core/user_ops/auc.cc

 
 

/* Copyright 2015 Google Inc. All Rights Reserved.

 
 

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

 
 

http://www.apache.org/licenses/LICENSE-2.0

 
 

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

==============================================================================*/

 
 

// An auc Op.

 
 

#include
"tensorflow/core/framework/op.h"

#include
"tensorflow/core/framework/op_kernel.h"

 
 

using
namespace tensorflow;

using
std::vector;

//@TODO add weight as optional input

REGISTER_OP("Auc")

.Input("predicts: T1")

.Input("labels: T2")

.Output("z: float")

.Attr("T1: {float, double}")

.Attr("T2: {float, double}")

//.Attr("T1: {float, double}")

//.Attr("T2: {int32, int64}")

.SetIsCommutative()

.Doc(R"doc(

Given preidicts and labels output it's auc

)doc");

 
 

class
AucOp : public OpKernel {

public:

explicit
AucOp(OpKernelConstruction* context) : OpKernel(context) {}

 
 

template<typename
ValueVec>

void
index_sort(const
ValueVec& valueVec, vector<int>& indexVec)

{

indexVec.resize(valueVec.size());

for (size_t
i = 0; i < indexVec.size(); i++)

{

indexVec[i] = i;

}

std::sort(indexVec.begin(), indexVec.end(),

[&valueVec](const
int
l, const
int
r) { return
valueVec(l) > valueVec(r); });

}

 
 

void
Compute(OpKernelContext* context) override {

// Grab the input tensor

const Tensor& predicts_tensor = context->input(0);

const Tensor& labels_tensor = context->input(1);

auto
predicts = predicts_tensor.flat<float>(); //输入能接受float double那么这里如何都处理?

auto
labels = labels_tensor.flat<float>();

 
 

vector<int> indexes;

index_sort(predicts, indexes);

typedef
float
Float;

 
 

Float
oldFalsePos = 0;

Float
oldTruePos = 0;

Float
falsePos = 0;

Float
truePos = 0;

Float
oldOut = std::numeric_limits<Float>::infinity();

Float
result = 0;

 
 

for (size_t
i = 0; i < indexes.size(); i++)

{

int
index = indexes[i];

Float
label = labels(index);

Float
prediction = predicts(index);

Float
weight = 1.0;

//Pval3(label, output, weight);

if (prediction != oldOut) //存在相同值得情况是特殊处理的

{

result += 0.5 * (oldTruePos + truePos) * (falsePos - oldFalsePos);

oldOut = prediction;

oldFalsePos = falsePos;

oldTruePos = truePos;

}

if (label > 0)

truePos += weight;

else

falsePos += weight;

}

result += 0.5 * (oldTruePos + truePos) * (falsePos - oldFalsePos);

Float
AUC = result / (truePos * falsePos);

 
 

// Create an output tensor

Tensor* output_tensor = NULL;

TensorShape output_shape;

 
 

OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output_tensor));

output_tensor->scalar<float>()() = AUC;

}

};

 
 

REGISTER_KERNEL_BUILDER(Name("Auc").Device(DEVICE_CPU), AucOp);

 
 

 
 

编译:

$cat gen-so.sh

 
 

TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())')

TF_LIB=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_lib())')

i=$1

o=${i/.cc/.so}

g++ -std=c++11 -shared $i -o $o -I $TF_INC -l tensorflow_framework -L $TF_LIB -fPIC -Wl,-rpath $TF_LIB

 
 

$sh gen-so.sh auc.cc

会生成auc.so

 
 

使用的时候

auc_module = tf.load_op_library('auc.so')

#auc = tf.user_ops.auc #0.6.0之前的tensorflow 自定义op方式

auc = auc_module.auc

 
 

evaluate_op = auc(py_x, Y) #py_x is predicts, Y is labels

 
 

 
 

 
 

 
 

 
 

 
 

tensorflow添加自定义的auc计算operator的更多相关文章

  1. AUC计算 - 进阶操作

    首先AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前 ...

  2. ROC 曲线,以及AUC计算方式

    ROC曲线: roc曲线:接收者操作特征(receiveroperating characteristic),roc曲线上每个点反映着对同一信号刺激的感受性. ROC曲线的横轴: 负正类率(false ...

  3. AUC计算 - 手把手步进操作

    2017-07-10 14:38:24 理论参考: 评估分类器性能的度量,像混淆矩阵.ROC.AUC等 http://www.cnblogs.com/suanec/p/5941630.html ROC ...

  4. 110、TensorFlow张量值的计算

    import tensorflow as tf #placeholders在没有提供具体值的时候不能使用eval方法来计算它的值 # 另外的建模方法可能会使得模型变得复杂 # TensorFlow 不 ...

  5. TensorFlow两种方式计算Cross Entropy

    sparse_softmax_cross_entropy_with_logits与softmax_cross_entropy_with_logits import tensorflow as tf y ...

  6. 学习笔记TF067:TensorFlow Serving、Flod、计算加速,机器学习评测体系,公开数据集

    TensorFlow Serving https://tensorflow.github.io/serving/ . 生产环境灵活.高性能机器学习模型服务系统.适合基于实际数据大规模运行,产生多个模型 ...

  7. tensorflow入门教程和底层机制简单解说——本质就是图计算,自动寻找依赖,想想spark机制就明白了

    简介 本章的目的是让你了解和运行 TensorFlow! 在开始之前, 让我们先看一段使用 Python API 撰写的 TensorFlow 示例代码, 让你对将要学习的内容有初步的印象. 这段很短 ...

  8. 机器学习的敲门砖:手把手教你TensorFlow初级入门

    摘要: 在开始使用机器学习算法之前,我们应该首先熟悉如何使用它们. 而本文就是通过对TensorFlow的一些基本特点的介绍,让你了解它是机器学习类库中的一个不错的选择. 本文由北邮@爱可可-爱生活  ...

  9. TensorFlow基础笔记(6) 图像风格化实验

    参考 http://blog.csdn.net/wspba/article/details/53994649 https://www.ctolib.com/AdaIN-style.html Ackno ...

随机推荐

  1. C#稳固基础:传统遍历与迭代器

    Hello,Coders.我们除了天天的码 if…else…之外,还会不断的码出foreach.我今天要说的是:传统遍历需实现的接口及我们还有一种更简洁优雅的方式实现多种迭代器. 传统遍历 传统的遍历 ...

  2. hdu3415 单调队列

    Max Sum of Max-K-sub-sequence Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  3. 在php中验证复选框

    PHP接收多个同名复选框信息不像ASP那样自动转换成为数组,这给使用带来了一定不便.但是还是有解决办法的,就是利用javascript做一下预处理.多个同名复选框在javascript中还是以数组的形 ...

  4. .NET 微信Token验证和消息接收和回复

    public class wxXmlModel { public string ToUserName { get; set; } public string FromUserName { get; s ...

  5. 前后台获取上下文context

    1.web server端获取上下文:Context ctx = WafContext.getInstance().getContext();上下文中包含当前登录组织.当前登录用户.语种.数据库.客户 ...

  6. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  7. 5 构建Mysql+heartbeat+DRBD+LVS集群应用系统系列之生产环境下drbd裂脑处理

    preface 公司的业务变更,导致服务器要搬迁,所以需要关闭服务器,然后到新地在开启服务器. 关机前确定drbd+heartbeat+mysql是正常使用的,没有异常,Heartbeat和drbd都 ...

  8. [转]eclipse重新编译

    Eclipse打开时并不重新生成class文件,这就造成了eclipse找不到需要的class文件从而不能正常编译工程中的其他代码.此时就需要重新编译工程. 单击Project菜单,选择Clean菜单 ...

  9. BZOJ3489: A simple rmq problem

    设$i$的前驱为$p_i$,后继为$q_i$,把询问看成点$(L,R)$,有贡献的$i$满足$L\in(p_i,i]$且$R\in[i,q_i)$,询问的就是覆盖这个点的矩形的最大值.那么可以用可持久 ...

  10. PHP 文件管理

    主页面: <?php session_start(); $filename=""; if(!empty($_SESSION["lujing"])) { $ ...