! * \brief predicting on data, then saving result to disk * \param data_filename Filename of data * \param result_filename Filename of output result */
| 131 | * \param result_filename Filename of output result |
| 132 | */ |
| 133 | void Predict(const char* data_filename, const char* result_filename, bool header) { |
| 134 | auto writer = VirtualFileWriter::Make(result_filename); |
| 135 | if (!writer->Init()) { |
| 136 | Log::Fatal("Prediction results file %s cannot be found", result_filename); |
| 137 | } |
| 138 | auto parser = std::unique_ptr<Parser>(Parser::CreateParser(data_filename, header, boosting_->MaxFeatureIdx() + 1, boosting_->LabelIdx())); |
| 139 | |
| 140 | if (parser == nullptr) { |
| 141 | Log::Fatal("Could not recognize the data format of data file %s", data_filename); |
| 142 | } |
| 143 | if (parser->NumFeatures() != boosting_->MaxFeatureIdx() + 1) { |
| 144 | Log::Fatal("The number of features in data (%d) is not the same as it was in training data (%d).", parser->NumFeatures(), boosting_->MaxFeatureIdx() + 1); |
| 145 | } |
| 146 | TextReader<data_size_t> predict_data_reader(data_filename, header); |
| 147 | std::unordered_map<int, int> feature_names_map_; |
| 148 | bool need_adjust = false; |
| 149 | if (header) { |
| 150 | std::string first_line = predict_data_reader.first_line(); |
| 151 | std::vector<std::string> header_words = Common::Split(first_line.c_str(), "\t,"); |
| 152 | header_words.erase(header_words.begin() + boosting_->LabelIdx()); |
| 153 | for (int i = 0; i < static_cast<int>(header_words.size()); ++i) { |
| 154 | for (int j = 0; j < static_cast<int>(boosting_->FeatureNames().size()); ++j) { |
| 155 | if (header_words[i] == boosting_->FeatureNames()[j]) { |
| 156 | feature_names_map_[i] = j; |
| 157 | break; |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | for (auto s : feature_names_map_) { |
| 162 | if (s.first != s.second) { |
| 163 | need_adjust = true; |
| 164 | break; |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | // function for parse data |
| 169 | std::function<void(const char*, std::vector<std::pair<int, double>>*)> parser_fun; |
| 170 | double tmp_label; |
| 171 | parser_fun = [&] |
| 172 | (const char* buffer, std::vector<std::pair<int, double>>* feature) { |
| 173 | parser->ParseOneLine(buffer, feature, &tmp_label); |
| 174 | if (need_adjust) { |
| 175 | int i = 0, j = static_cast<int>(feature->size()); |
| 176 | while (i < j) { |
| 177 | if (feature_names_map_.find((*feature)[i].first) != feature_names_map_.end()) { |
| 178 | (*feature)[i].first = feature_names_map_[(*feature)[i].first]; |
| 179 | ++i; |
| 180 | } else { |
| 181 | // move the non-used features to the end of the feature vector |
| 182 | std::swap((*feature)[i], (*feature)[--j]); |
| 183 | } |
| 184 | } |
| 185 | feature->resize(i); |
| 186 | } |
| 187 | }; |
| 188 | |
| 189 | std::function<void(data_size_t, const std::vector<std::string>&)> process_fun = [&] |
| 190 | (data_size_t, const std::vector<std::string>& lines) { |
no test coverage detected