double DCGCalculator::CalDCGAtK(data_size_t k, const label_t* label, const double* score, data_size_t num_data) { // get sorted indices by score std::vector<data_size_t> sorted_idx(num_data); for (data_size_t i = 0; i < num_data; ++i) { sorted_idx[i] = i; } std::sort(sorted_idx.begin(), sorted_idx.end(), [score](data_size_t a, data_size_t b) {return score[a] > score[b]; }); if (k > num_data) { k = num_data; } double dcg = 0.0f; // calculate dcg for (data_size_t i = 0; i < k; ++i) { data_size_t idx = sorted_idx[i]; dcg += label_gain_[static_cast<int>(label[idx])] * discount_[i]; } return dcg; }
void DCGCalculator::CalDCG(const std::vector<data_size_t>& ks, const label_t* label, const double * score, data_size_t num_data, std::vector<double>* out) { // get sorted indices by score std::vector<data_size_t> sorted_idx(num_data); for (data_size_t i = 0; i < num_data; ++i) { sorted_idx[i] = i; } std::sort(sorted_idx.begin(), sorted_idx.end(), [score](data_size_t a, data_size_t b) {return score[a] > score[b]; }); double cur_result = 0.0f; data_size_t cur_left = 0; // calculate multi dcg by one pass for (size_t i = 0; i < ks.size(); ++i) { data_size_t cur_k = ks[i]; if (cur_k > num_data) { cur_k = num_data; } for (data_size_t j = cur_left; j < cur_k; ++j) { data_size_t idx = sorted_idx[j]; cur_result += label_gain_[static_cast<int>(label[idx])] * discount_[j]; } (*out)[i] = cur_result; cur_left = cur_k; } }
// // Get ranks and index of scores // // [[Rcpp::export]] Rcpp::List get_score_ranks(const Rcpp::NumericVector& scores, const bool& na_last, const std::string& ties_method) { // Variables Rcpp::List ret_val; std::string errmsg = ""; std::vector<int> ranks(scores.size()); std::vector<int> rank_idx(scores.size()); // Update NAs std::vector<double> svals(scores.size()); std::vector<int> sorted_idx(scores.size()); for (int i = 0; i < scores.size(); ++i) { if (Rcpp::NumericVector::is_na(scores[i])) { if (na_last) { svals[i] = DBL_MIN; } else { svals[i] = DBL_MAX; } } else { svals[i] = scores[i]; } sorted_idx[i] = i; } // Sort scores CompDVec fcomp(svals); if (ties_method == "first") { std::stable_sort(sorted_idx.begin(), sorted_idx.end(), fcomp); } else { std::sort(sorted_idx.begin(), sorted_idx.end(), fcomp); } // Set ranks for (unsigned i = 0; i < sorted_idx.size(); ++i) { ranks[sorted_idx[i]] = i + 1; rank_idx[i] = sorted_idx[i]; } // Update ties if (ties_method == "equiv" || ties_method == "random") { std::vector<int> tied_idx; double prev_val = svals[rank_idx[0]]; bool tied = false; for (unsigned i = 1; i < rank_idx.size(); ++i) { if (tied) { if (prev_val != svals[rank_idx[i]]) { update_ties(ranks, rank_idx, tied_idx, ties_method); tied_idx.clear(); tied = false; } else { tied_idx.push_back(rank_idx[i]); } } else if (prev_val == svals[rank_idx[i]]) { tied_idx.push_back(rank_idx[i - 1]); tied_idx.push_back(rank_idx[i]); tied = true; } prev_val = svals[rank_idx[i]]; } if (tied) { update_ties(ranks, rank_idx, tied_idx, ties_method); } } // Add 1 to rank_idx for (unsigned i = 0; i < rank_idx.size(); ++i) { rank_idx[i] = rank_idx[i] + 1; } // Return result ret_val["ranks"] = ranks; ret_val["rank_idx"] = rank_idx; ret_val["errmsg"] = errmsg; return ret_val; }