1.auc概念:随机挑选一对正负样本,正样本打分值大于负样本的概率.
2.auc计算方法.
#include <iostream>
#include <vector>
#include <algorithm>
struct Record {
float label;
float predict;
Record(float l, float p) {
label = l;
predict = p;
}
bool operator<(const Record& r) const {
return predict < r.predict || (predict == r.predict && label > r.label);
}
};
double auc(std::vector<Record>& res) {
// 1. 按照打分排序
std::sort(res.begin(), res.end());
// 2. 获取总对数
size_t true_count = 0;
size_t false_count = 0;
for (auto& r : res) {
if (r.label == 1) {
true_count++;
} else {
false_count++;
}
}
size_t total_area = true_count * false_count;
if (total_area == 0) {
return -1;
}
// 3. 获取正样本打分大于负样本的个数
size_t h = 0;
size_t area = 0;
for (auto it = res.rbegin(); it != res.rend(); ++it) {
if (it->label == 1) {
h++;
} else {
area += h;
}
}
return static_cast<double>(area) / static_cast<double>(total_area);
}
int main() {
std::vector<Record> res;
res.push_back(Record(0, 0.1));
res.push_back(Record(0, 0.2));
res.push_back(Record(0, 0.3));
res.push_back(Record(0, 0.5));
res.push_back(Record(0, 0.6));
res.push_back(Record(1, 0.5));
std::cout << auc(res) << std::endl;
return 0;
}
3.首先按照predict值排序(升序,注意predict相等的情况). 按照定义,问题可转化为:在一个0,1数组中,随机选取一对0,1,求1出现在0后面的概率,即1的下标大于0下标的概率.
也就是求所有0,1对的个数,满足1的下标大于0的下标. 用这个数除以总(0,1)对数即可,总的(0,1)对数遍历一遍数组即可获取.
最简单的方法就是暴力遍历,时间复杂度0(n^2). 上述代码更巧妙一些,从后向前遍历,实时统计1的个数h,每次遇到0,那么满足条件的(0,1)对会增加h个. 这样遍历一次就得到结果.