| 146 | } |
| 147 | |
| 148 | std::vector<std::vector<int>> FastFeatureBundling(const std::vector<std::unique_ptr<BinMapper>>& bin_mappers, |
| 149 | int** sample_indices, |
| 150 | const int* num_per_col, |
| 151 | int num_sample_col, |
| 152 | size_t total_sample_cnt, |
| 153 | const std::vector<int>& used_features, |
| 154 | double max_conflict_rate, |
| 155 | data_size_t num_data, |
| 156 | data_size_t min_data, |
| 157 | double sparse_threshold, |
| 158 | bool is_enable_sparse, |
| 159 | bool is_use_gpu) { |
| 160 | // filter is based on sampling data, so decrease its range |
| 161 | const data_size_t filter_cnt = static_cast<data_size_t>(static_cast<double>(0.95 * min_data) / num_data * total_sample_cnt); |
| 162 | const data_size_t max_error_cnt = static_cast<data_size_t>(total_sample_cnt * max_conflict_rate); |
| 163 | std::vector<size_t> feature_non_zero_cnt; |
| 164 | feature_non_zero_cnt.reserve(used_features.size()); |
| 165 | // put dense feature first |
| 166 | for (auto fidx : used_features) { |
| 167 | if (fidx < num_sample_col) { |
| 168 | feature_non_zero_cnt.emplace_back(num_per_col[fidx]); |
| 169 | } else { |
| 170 | feature_non_zero_cnt.emplace_back(0); |
| 171 | } |
| 172 | } |
| 173 | // sort by non zero cnt |
| 174 | std::vector<int> sorted_idx; |
| 175 | sorted_idx.reserve(used_features.size()); |
| 176 | for (int i = 0; i < static_cast<int>(used_features.size()); ++i) { |
| 177 | sorted_idx.emplace_back(i); |
| 178 | } |
| 179 | // sort by non zero cnt, bigger first |
| 180 | std::stable_sort(sorted_idx.begin(), sorted_idx.end(), |
| 181 | [&feature_non_zero_cnt](int a, int b) { |
| 182 | return feature_non_zero_cnt[a] > feature_non_zero_cnt[b]; |
| 183 | }); |
| 184 | |
| 185 | std::vector<int> feature_order_by_cnt; |
| 186 | feature_order_by_cnt.reserve(sorted_idx.size()); |
| 187 | for (auto sidx : sorted_idx) { |
| 188 | feature_order_by_cnt.push_back(used_features[sidx]); |
| 189 | } |
| 190 | auto features_in_group = FindGroups(bin_mappers, used_features, sample_indices, num_per_col, num_sample_col, total_sample_cnt, max_error_cnt, filter_cnt, num_data, is_use_gpu); |
| 191 | auto group2 = FindGroups(bin_mappers, feature_order_by_cnt, sample_indices, num_per_col, num_sample_col, total_sample_cnt, max_error_cnt, filter_cnt, num_data, is_use_gpu); |
| 192 | if (features_in_group.size() > group2.size()) { |
| 193 | features_in_group = group2; |
| 194 | } |
| 195 | std::vector<std::vector<int>> ret; |
| 196 | for (size_t i = 0; i < features_in_group.size(); ++i) { |
| 197 | if (features_in_group[i].size() <= 1 || features_in_group[i].size() >= 5) { |
| 198 | ret.push_back(features_in_group[i]); |
| 199 | } else { |
| 200 | int cnt_non_zero = 0; |
| 201 | for (size_t j = 0; j < features_in_group[i].size(); ++j) { |
| 202 | const int fidx = features_in_group[i][j]; |
| 203 | cnt_non_zero += static_cast<int>(num_data * (1.0f - bin_mappers[fidx]->sparse_rate())); |
| 204 | } |
| 205 | double sparse_rate = 1.0f - static_cast<double>(cnt_non_zero) / (num_data); |
no test coverage detected