1. 程式人生 > 其它 >auc計算方法

auc計算方法

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; }
};

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.4));
  std::cout << auc(res) << std::endl; // 0.6
  return 0;
} 

3.首先按照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個. 這樣遍歷一次就得到結果.