| 1235 | |
| 1236 | |
| 1237 | std::vector<std::vector<double>> DatasetLoader::GetForcedBins(std::string forced_bins_path, int num_total_features, |
| 1238 | const std::unordered_set<int>& categorical_features) { |
| 1239 | std::vector<std::vector<double>> forced_bins(num_total_features, std::vector<double>()); |
| 1240 | if (forced_bins_path != "") { |
| 1241 | std::ifstream forced_bins_stream(forced_bins_path.c_str()); |
| 1242 | if (forced_bins_stream.fail()) { |
| 1243 | Log::Warning("Could not open %s. Will ignore.", forced_bins_path.c_str()); |
| 1244 | } else { |
| 1245 | std::stringstream buffer; |
| 1246 | buffer << forced_bins_stream.rdbuf(); |
| 1247 | std::string err; |
| 1248 | Json forced_bins_json = Json::parse(buffer.str(), err); |
| 1249 | CHECK(forced_bins_json.is_array()); |
| 1250 | std::vector<Json> forced_bins_arr = forced_bins_json.array_items(); |
| 1251 | for (size_t i = 0; i < forced_bins_arr.size(); ++i) { |
| 1252 | int feature_num = forced_bins_arr[i]["feature"].int_value(); |
| 1253 | CHECK(feature_num < num_total_features); |
| 1254 | if (categorical_features.count(feature_num)) { |
| 1255 | Log::Warning("Feature %d is categorical. Will ignore forced bins for this feature.", feature_num); |
| 1256 | } else { |
| 1257 | std::vector<Json> bounds_arr = forced_bins_arr[i]["bin_upper_bound"].array_items(); |
| 1258 | for (size_t j = 0; j < bounds_arr.size(); ++j) { |
| 1259 | forced_bins[feature_num].push_back(bounds_arr[j].number_value()); |
| 1260 | } |
| 1261 | } |
| 1262 | } |
| 1263 | // remove duplicates |
| 1264 | for (int i = 0; i < num_total_features; ++i) { |
| 1265 | auto new_end = std::unique(forced_bins[i].begin(), forced_bins[i].end()); |
| 1266 | forced_bins[i].erase(new_end, forced_bins[i].end()); |
| 1267 | } |
| 1268 | } |
| 1269 | } |
| 1270 | return forced_bins; |
| 1271 | } |
| 1272 | |
| 1273 | } // namespace LightGBM |