auc计算方法

1.auc概念:

①随机挑选一对正负样本,正样本打分值大于负样本的概率

②roc曲线面积

注意:按照定义①,这里有个问题,打分相同怎么取舍。这个问题可以根据roc曲线绘制方法可知,如果打分值相同的话,roc会有斜线产生,那么计算面积的时候就是梯形面积,等价于打分值相同的时候,取一半的正样本算作打分值大于负样本

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个. 这样遍历一次就得到结果.

====================================2022.09.02补充===========================

4.predict值相同的时候,计算对数的时候,取一半的值. 例如:有5个样本打分相同,其中3个正样本,2个负样本,这时候正样本大于负样本的对数取 3*2 /2 = 3.

--------------2022.10.08补充-----------

5.使用概念②计算auc

6.weighted auc计算方法

7.gauc计算方法

8.分布式auc计算方法

posted @ 2021-10-29 14:17  灰太狼锅锅  阅读(937)  评论(0编辑  收藏  举报