|
13 | 13 | using LightGBM::TestUtils;
|
14 | 14 |
|
15 | 15 | void test_predict_type(int predict_type, int num_predicts) {
|
16 |
| - // Load some test data |
17 |
| - int result; |
18 |
| - |
19 |
| - DatasetHandle train_dataset; |
20 |
| - result = TestUtils::LoadDatasetFromExamples("binary_classification/binary.train", "max_bin=15", &train_dataset); |
21 |
| - EXPECT_EQ(0, result) << "LoadDatasetFromExamples train result code: " << result; |
22 |
| - |
23 |
| - BoosterHandle booster_handle; |
24 |
| - result = LGBM_BoosterCreate(train_dataset, "app=binary metric=auc num_leaves=31 verbose=0", &booster_handle); |
25 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterCreate result code: " << result; |
26 |
| - |
27 |
| - for (int i = 0; i < 51; i++) { |
28 |
| - int is_finished; |
29 |
| - result = LGBM_BoosterUpdateOneIter( |
30 |
| - booster_handle, |
31 |
| - &is_finished); |
32 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterUpdateOneIter result code: " << result; |
33 |
| - } |
34 |
| - |
35 |
| - int n_features; |
36 |
| - result = LGBM_BoosterGetNumFeature( |
37 |
| - booster_handle, |
38 |
| - &n_features); |
39 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterGetNumFeature result code: " << result; |
40 |
| - EXPECT_EQ(28, n_features) << "LGBM_BoosterGetNumFeature number of features: " << n_features; |
41 |
| - |
42 |
| - // Run a single row prediction and compare with regular Mat prediction: |
43 |
| - int64_t output_size; |
44 |
| - result = LGBM_BoosterCalcNumPredict( |
45 |
| - booster_handle, |
46 |
| - 1, |
47 |
| - predict_type, // predict_type |
48 |
| - 0, // start_iteration |
49 |
| - -1, // num_iteration |
50 |
| - &output_size); |
51 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterCalcNumPredict result code: " << result; |
52 |
| - EXPECT_EQ(num_predicts, output_size) << "LGBM_BoosterCalcNumPredict output size: " << output_size; |
53 |
| - |
54 |
| - std::ifstream test_file("examples/binary_classification/binary.test"); |
55 |
| - std::vector<double> test; |
56 |
| - double x; |
57 |
| - int test_set_size = 0; |
58 |
| - while (test_file >> x) { |
59 |
| - if (test_set_size % (n_features + 1) == 0) { |
60 |
| - // Drop the result from the dataset, we only care about checking that prediction results are equal |
61 |
| - // in both cases |
62 |
| - test_file >> x; |
63 |
| - test_set_size++; |
| 16 | + // Load some test data |
| 17 | + int result; |
| 18 | + |
| 19 | + DatasetHandle train_dataset; |
| 20 | + result = TestUtils::LoadDatasetFromExamples("binary_classification/binary.train", "max_bin=15", &train_dataset); |
| 21 | + EXPECT_EQ(0, result) << "LoadDatasetFromExamples train result code: " << result; |
| 22 | + |
| 23 | + BoosterHandle booster_handle; |
| 24 | + result = LGBM_BoosterCreate(train_dataset, "app=binary metric=auc num_leaves=31 verbose=0", &booster_handle); |
| 25 | + EXPECT_EQ(0, result) << "LGBM_BoosterCreate result code: " << result; |
| 26 | + |
| 27 | + for (int i = 0; i < 51; i++) { |
| 28 | + int is_finished; |
| 29 | + result = LGBM_BoosterUpdateOneIter( |
| 30 | + booster_handle, |
| 31 | + &is_finished); |
| 32 | + EXPECT_EQ(0, result) << "LGBM_BoosterUpdateOneIter result code: " << result; |
| 33 | + } |
| 34 | + |
| 35 | + int n_features; |
| 36 | + result = LGBM_BoosterGetNumFeature( |
| 37 | + booster_handle, |
| 38 | + &n_features); |
| 39 | + EXPECT_EQ(0, result) << "LGBM_BoosterGetNumFeature result code: " << result; |
| 40 | + EXPECT_EQ(28, n_features) << "LGBM_BoosterGetNumFeature number of features: " << n_features; |
| 41 | + |
| 42 | + // Run a single row prediction and compare with regular Mat prediction: |
| 43 | + int64_t output_size; |
| 44 | + result = LGBM_BoosterCalcNumPredict( |
| 45 | + booster_handle, |
| 46 | + 1, |
| 47 | + predict_type, // predict_type |
| 48 | + 0, // start_iteration |
| 49 | + -1, // num_iteration |
| 50 | + &output_size); |
| 51 | + EXPECT_EQ(0, result) << "LGBM_BoosterCalcNumPredict result code: " << result; |
| 52 | + EXPECT_EQ(num_predicts, output_size) << "LGBM_BoosterCalcNumPredict output size: " << output_size; |
| 53 | + |
| 54 | + std::ifstream test_file("examples/binary_classification/binary.test"); |
| 55 | + std::vector<double> test; |
| 56 | + double x; |
| 57 | + int test_set_size = 0; |
| 58 | + while (test_file >> x) { |
| 59 | + if (test_set_size % (n_features + 1) == 0) { |
| 60 | + // Drop the result from the dataset, we only care about checking that prediction results are equal |
| 61 | + // in both cases |
| 62 | + test_file >> x; |
| 63 | + test_set_size++; |
| 64 | + } |
| 65 | + test.push_back(x); |
| 66 | + test_set_size++; |
| 67 | + } |
| 68 | + EXPECT_EQ(test_set_size % (n_features + 1), 0) << "Test size mismatch with dataset size (%)"; |
| 69 | + test_set_size /= (n_features + 1); |
| 70 | + EXPECT_EQ(test_set_size, 500) << "Improperly parsed test file (test_set_size)"; |
| 71 | + EXPECT_EQ(test.size(), test_set_size * n_features) << "Improperly parsed test file (test len)"; |
| 72 | + |
| 73 | + std::vector<double> mat_output(output_size * test_set_size, -1); |
| 74 | + int64_t written; |
| 75 | + result = LGBM_BoosterPredictForMat( |
| 76 | + booster_handle, |
| 77 | + &test[0], |
| 78 | + C_API_DTYPE_FLOAT64, |
| 79 | + test_set_size, // nrow |
| 80 | + n_features, // ncol |
| 81 | + 1, // is_row_major |
| 82 | + predict_type, // predict_type |
| 83 | + 0, // start_iteration |
| 84 | + -1, // num_iteration |
| 85 | + "", |
| 86 | + &written, |
| 87 | + &mat_output[0]); |
| 88 | + EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMat result code: " << result; |
| 89 | + |
| 90 | + // Test LGBM_BoosterPredictForMat in multi-threaded mode |
| 91 | + const int kNThreads = 10; |
| 92 | + const int numIterations = 5; |
| 93 | + std::vector<std::thread> predict_for_mat_threads(kNThreads); |
| 94 | + for (int i = 0; i < kNThreads; i++) { |
| 95 | + predict_for_mat_threads[i] = std::thread( |
| 96 | + [ |
| 97 | + i, test_set_size, output_size, n_features, |
| 98 | + test = &test[0], booster_handle, predict_type, numIterations |
| 99 | + ]() { |
| 100 | + for (int j = 0; j < numIterations; j++) { |
| 101 | + int result; |
| 102 | + std::vector<double> mat_output(output_size * test_set_size, -1); |
| 103 | + int64_t written; |
| 104 | + result = LGBM_BoosterPredictForMat( |
| 105 | + booster_handle, |
| 106 | + &test[0], |
| 107 | + C_API_DTYPE_FLOAT64, |
| 108 | + test_set_size, // nrow |
| 109 | + n_features, // ncol |
| 110 | + 1, // is_row_major |
| 111 | + predict_type, // predict_type |
| 112 | + 0, // start_iteration |
| 113 | + -1, // num_iteration |
| 114 | + "", |
| 115 | + &written, |
| 116 | + &mat_output[0]); |
| 117 | + EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMat result code: " << result; |
| 118 | + } |
| 119 | + }); |
| 120 | + } |
| 121 | + for (std::thread& t : predict_for_mat_threads) { |
| 122 | + t.join(); |
64 | 123 | }
|
65 |
| - test.push_back(x); |
66 |
| - test_set_size++; |
67 |
| - } |
68 |
| - EXPECT_EQ(test_set_size % (n_features + 1), 0) << "Test size mismatch with dataset size (%)"; |
69 |
| - test_set_size /= (n_features + 1); |
70 |
| - EXPECT_EQ(test_set_size, 500) << "Improperly parsed test file (test_set_size)"; |
71 |
| - EXPECT_EQ(test.size(), test_set_size * n_features) << "Improperly parsed test file (test len)"; |
72 |
| - |
73 |
| - std::vector<double> mat_output(output_size * test_set_size, -1); |
74 |
| - int64_t written; |
75 |
| - result = LGBM_BoosterPredictForMat( |
76 |
| - booster_handle, |
77 |
| - &test[0], |
78 |
| - C_API_DTYPE_FLOAT64, |
79 |
| - test_set_size, // nrow |
80 |
| - n_features, // ncol |
81 |
| - 1, // is_row_major |
82 |
| - predict_type, // predict_type |
83 |
| - 0, // start_iteration |
84 |
| - -1, // num_iteration |
85 |
| - "", |
86 |
| - &written, |
87 |
| - &mat_output[0]); |
88 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMat result code: " << result; |
89 |
| - |
90 |
| - // Test LGBM_BoosterPredictForMat in multi-threaded mode |
91 |
| - const int kNThreads = 10; |
92 |
| - const int numIterations = 5; |
93 |
| - std::vector<std::thread> predict_for_mat_threads(kNThreads); |
94 |
| - for (int i = 0; i < kNThreads; i++) { |
95 |
| - predict_for_mat_threads[i] = std::thread( |
96 |
| - [ |
97 |
| - i, test_set_size, output_size, n_features, |
98 |
| - test = &test[0], booster_handle, predict_type, numIterations |
99 |
| - ]() { |
100 |
| - for (int j = 0; j < numIterations; j++) { |
101 |
| - int result; |
102 |
| - std::vector<double> mat_output(output_size * test_set_size, -1); |
103 |
| - int64_t written; |
104 |
| - result = LGBM_BoosterPredictForMat( |
| 124 | + |
| 125 | + // Now let's run with the single row fast prediction API: |
| 126 | + FastConfigHandle fast_configs[kNThreads]; |
| 127 | + for (int i = 0; i < kNThreads; i++) { |
| 128 | + result = LGBM_BoosterPredictForMatSingleRowFastInit( |
105 | 129 | booster_handle,
|
106 |
| - &test[0], |
107 |
| - C_API_DTYPE_FLOAT64, |
108 |
| - test_set_size, // nrow |
109 |
| - n_features, // ncol |
110 |
| - 1, // is_row_major |
111 | 130 | predict_type, // predict_type
|
112 | 131 | 0, // start_iteration
|
113 | 132 | -1, // num_iteration
|
| 133 | + C_API_DTYPE_FLOAT64, |
| 134 | + n_features, |
114 | 135 | "",
|
115 |
| - &written, |
116 |
| - &mat_output[0]); |
117 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMat result code: " << result; |
118 |
| - } |
119 |
| - }); |
120 |
| - } |
121 |
| - for (std::thread& t : predict_for_mat_threads) { |
122 |
| - t.join(); |
123 |
| - } |
124 |
| - |
125 |
| - // Now let's run with the single row fast prediction API: |
126 |
| - FastConfigHandle fast_configs[kNThreads]; |
127 |
| - for (int i = 0; i < kNThreads; i++) { |
128 |
| - result = LGBM_BoosterPredictForMatSingleRowFastInit( |
129 |
| - booster_handle, |
130 |
| - predict_type, // predict_type |
131 |
| - 0, // start_iteration |
132 |
| - -1, // num_iteration |
133 |
| - C_API_DTYPE_FLOAT64, |
134 |
| - n_features, |
135 |
| - "", |
136 |
| - &fast_configs[i]); |
137 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMatSingleRowFastInit result code: " << result; |
138 |
| - } |
139 |
| - |
140 |
| - std::vector<double> single_row_output(output_size * test_set_size, -1); |
141 |
| - std::vector<std::thread> single_row_threads(kNThreads); |
142 |
| - int batch_size = (test_set_size + kNThreads - 1) / kNThreads; // round up |
143 |
| - for (int i = 0; i < kNThreads; i++) { |
144 |
| - single_row_threads[i] = std::thread( |
145 |
| - [ |
146 |
| - i, batch_size, test_set_size, output_size, n_features, |
147 |
| - test = &test[0], fast_configs = &fast_configs[0], single_row_output = &single_row_output[0] |
148 |
| - ]() { |
149 |
| - int result; |
150 |
| - int64_t written; |
151 |
| - for (int j = i * batch_size; j < std::min((i + 1) * batch_size, test_set_size); j++) { |
152 |
| - result = LGBM_BoosterPredictForMatSingleRowFast( |
153 |
| - fast_configs[i], |
154 |
| - &test[j * n_features], |
155 |
| - &written, |
156 |
| - &single_row_output[j * output_size]); |
157 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMatSingleRowFast result code: " << result; |
158 |
| - EXPECT_EQ(written, output_size) << "LGBM_BoosterPredictForMatSingleRowFast unexpected written output size"; |
159 |
| - } |
160 |
| - }); |
161 |
| - } |
162 |
| - for (std::thread& t : single_row_threads) { |
163 |
| - t.join(); |
164 |
| - } |
| 136 | + &fast_configs[i]); |
| 137 | + EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMatSingleRowFastInit result code: " << result; |
| 138 | + } |
| 139 | + |
| 140 | + std::vector<double> single_row_output(output_size * test_set_size, -1); |
| 141 | + std::vector<std::thread> single_row_threads(kNThreads); |
| 142 | + int batch_size = (test_set_size + kNThreads - 1) / kNThreads; // round up |
| 143 | + for (int i = 0; i < kNThreads; i++) { |
| 144 | + single_row_threads[i] = std::thread( |
| 145 | + [ |
| 146 | + i, batch_size, test_set_size, output_size, n_features, |
| 147 | + test = &test[0], fast_configs = &fast_configs[0], single_row_output = &single_row_output[0] |
| 148 | + ]() { |
| 149 | + int result; |
| 150 | + int64_t written; |
| 151 | + for (int j = i * batch_size; j < std::min((i + 1) * batch_size, test_set_size); j++) { |
| 152 | + result = LGBM_BoosterPredictForMatSingleRowFast( |
| 153 | + fast_configs[i], |
| 154 | + &test[j * n_features], |
| 155 | + &written, |
| 156 | + &single_row_output[j * output_size]); |
| 157 | + EXPECT_EQ(0, result) << "LGBM_BoosterPredictForMatSingleRowFast result code: " << result; |
| 158 | + EXPECT_EQ(written, output_size) << "LGBM_BoosterPredictForMatSingleRowFast unexpected written output size"; |
| 159 | + } |
| 160 | + }); |
| 161 | + } |
| 162 | + for (std::thread& t : single_row_threads) { |
| 163 | + t.join(); |
| 164 | + } |
165 | 165 |
|
166 |
| - EXPECT_EQ(single_row_output, mat_output) << "LGBM_BoosterPredictForMatSingleRowFast output mismatch with LGBM_BoosterPredictForMat"; |
| 166 | + EXPECT_EQ(single_row_output, mat_output) << "LGBM_BoosterPredictForMatSingleRowFast output mismatch with LGBM_BoosterPredictForMat"; |
167 | 167 |
|
168 |
| - // Free all: |
169 |
| - for (int i = 0; i < kNThreads; i++) { |
170 |
| - result = LGBM_FastConfigFree(fast_configs[i]); |
171 |
| - EXPECT_EQ(0, result) << "LGBM_FastConfigFree result code: " << result; |
172 |
| - } |
| 168 | + // Free all: |
| 169 | + for (int i = 0; i < kNThreads; i++) { |
| 170 | + result = LGBM_FastConfigFree(fast_configs[i]); |
| 171 | + EXPECT_EQ(0, result) << "LGBM_FastConfigFree result code: " << result; |
| 172 | + } |
173 | 173 |
|
174 |
| - result = LGBM_BoosterFree(booster_handle); |
175 |
| - EXPECT_EQ(0, result) << "LGBM_BoosterFree result code: " << result; |
| 174 | + result = LGBM_BoosterFree(booster_handle); |
| 175 | + EXPECT_EQ(0, result) << "LGBM_BoosterFree result code: " << result; |
176 | 176 |
|
177 |
| - result = LGBM_DatasetFree(train_dataset); |
178 |
| - EXPECT_EQ(0, result) << "LGBM_DatasetFree result code: " << result; |
| 177 | + result = LGBM_DatasetFree(train_dataset); |
| 178 | + EXPECT_EQ(0, result) << "LGBM_DatasetFree result code: " << result; |
179 | 179 | }
|
180 | 180 |
|
181 | 181 | TEST(SingleRow, Normal) {
|
182 |
| - test_predict_type(C_API_PREDICT_NORMAL, 1); |
| 182 | + test_predict_type(C_API_PREDICT_NORMAL, 1); |
183 | 183 | }
|
184 | 184 |
|
185 | 185 | TEST(SingleRow, Contrib) {
|
186 |
| - test_predict_type(C_API_PREDICT_CONTRIB, 29); |
| 186 | + test_predict_type(C_API_PREDICT_CONTRIB, 29); |
187 | 187 | }
|
0 commit comments