tensorflow添加自定义的auc计算operator

本文介绍如何在 TensorFlow 中添加自定义的 AUC 计算 Operator,通过 C++ 编写并编译为插件形式,直接在计算图中执行以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tensorflow添加自定义的auc计算operator

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

这里根据工作需要添加一个计算aucoperator,只给出最简单实现,后续高级功能还是参考官方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过程,即插即用。

  

首先aucoperator计算的文件

  

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"

  

usingnamespace tensorflow;

usingstd::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");

  

classAucOp : public OpKernel {

public:

explicitAucOp(OpKernelConstruction* context) : OpKernel(context) {}

  

template<typenameValueVec>

voidindex_sort(constValueVec& valueVec, vector<int>& indexVec)

{

indexVec.resize(valueVec.size());

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

{

indexVec[i] = i;

}

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

[&valueVec](constintl, constintr) { returnvalueVec(l) > valueVec(r); });

}

  

voidCompute(OpKernelContext* context) override {

// Grab the input tensor

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

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

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

autolabels = labels_tensor.flat<float>();

  

vector<int> indexes;

index_sort(predicts, indexes);

typedeffloatFloat;

  

FloatoldFalsePos = 0;

FloatoldTruePos = 0;

FloatfalsePos = 0;

FloattruePos = 0;

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

Floatresult = 0;

  

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

{

intindex = indexes[i];

Floatlabel = labels(index);

Floatprediction = predicts(index);

Floatweight = 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);

FloatAUC = 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
AUC(Area Under the Curve)是用于评估分类模型性能的重要指标,尤其在二分类问题中广泛应用。它衡量的是ROC曲线下的面积,反映了模型对正类和负类样本的区分能力。计算AUC的方法主要包括以下步骤: 1. **生成预测得分**:模型输出每个样本属于正类的概率或得分。 2. **构建ROC曲线**:通过改变分类阈值,计算不同阈值下的真正例率(TPR)和假正例率(FPR),并绘制ROC曲线。 3. **计算曲线下面积**:通过积分方法计算ROC曲线下的面积,即AUC值。 AUC值的范围通常在0.5到1之间,其中: - AUC = 1 表示模型完美区分正负样本; - AUC = 0.5 表示模型的预测结果与随机猜测无异; - AUC > 0.5 表示模型具有一定的判别能力。 ### Python实现 可以使用`scikit-learn`库中的`roc_auc_score`函数来计算AUC指标[^2]。以下是具体的代码示例: ```python import numpy as np from sklearn.metrics import roc_auc_score # 示例1 y_true_1 = np.array([1, 1, 0, 0, 1, 1, 0]) y_scores_1 = np.array([0.8, 0.7, 0.5, 0.5, 0.5, 0.5, 0.3]) auc_1 = roc_auc_score(y_true_1, y_scores_1) print(f"y_true is {y_true_1}") print(f"y_scores is {y_scores_1}") print(f"AUC is {auc_1}") # 示例2 y_true_2 = np.array([0, 0, 1, 1]) y_scores_2 = np.array([0.1, 0.4, 0.35, 0.8]) auc_2 = roc_auc_score(y_true_2, y_scores_2) print(f"y_true is {y_true_2}") print(f"y_scores is {y_scores_2}") print(f"AUC is {auc_2}") ``` 上述代码展示了如何利用真实标签和模型输出的预测概率来计算AUC值。需要注意的是,输入的预测得分必须为连续值,而不是离散的类别标签。 此外,如果需要手动实现AUC计算,可以通过以下步骤完成: 1. 按照预测得分从高到低排序所有样本。 2. 遍历排序后的样本,统计真正例和假正例的数量。 3. 计算每一步的TPR和FPR,并通过梯形法计算面积。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值