| 28 | } |
| 29 | |
| 30 | vector<float_type> SvmModel::cross_validation(DataSet dataset, SvmParam param, int n_fold) { |
| 31 | dataset.group_classes(this->param.svm_type == SvmParam::C_SVC);//group classes only for classification |
| 32 | |
| 33 | vector<float_type> y_predict_all(dataset.n_instances()); |
| 34 | |
| 35 | for (int k = 0; k < n_fold; ++k) { |
| 36 | LOG(INFO) << n_fold << " fold cross-validation (" << k + 1 << "/" << n_fold << ")"; |
| 37 | DataSet::node2d x_train, x_test; |
| 38 | vector<float_type> y_train, y_test; |
| 39 | vector<int> test_idx; |
| 40 | for (int i = 0; i < dataset.n_classes(); ++i) { |
| 41 | int fold_test_count = dataset.count()[i] / n_fold; |
| 42 | vector<int> class_idx = dataset.original_index(i); |
| 43 | auto idx_begin = class_idx.begin() + fold_test_count * k; |
| 44 | auto idx_end = idx_begin; |
| 45 | if (k == n_fold - 1) { |
| 46 | idx_end = class_idx.end(); |
| 47 | } else { |
| 48 | while (idx_end != class_idx.end() && idx_end - idx_begin < fold_test_count) idx_end++; |
| 49 | } |
| 50 | for (int j: vector<int>(idx_begin, idx_end)) { |
| 51 | x_test.push_back(dataset.instances()[j]); |
| 52 | y_test.push_back(dataset.y()[j]); |
| 53 | test_idx.push_back(j); |
| 54 | } |
| 55 | class_idx.erase(idx_begin, idx_end); |
| 56 | for (int j:class_idx) { |
| 57 | x_train.push_back(dataset.instances()[j]); |
| 58 | y_train.push_back(dataset.y()[j]); |
| 59 | } |
| 60 | } |
| 61 | DataSet train_dataset(x_train, dataset.n_features(), y_train); |
| 62 | this->train(train_dataset, param); |
| 63 | vector<float_type> y_predict = this->predict(x_test, 1000); |
| 64 | CHECK_EQ(y_predict.size(), test_idx.size()); |
| 65 | for (int i = 0; i < y_predict.size(); ++i) { |
| 66 | y_predict_all[test_idx[i]] = y_predict[i]; |
| 67 | } |
| 68 | } |
| 69 | return y_predict_all; |
| 70 | } |
| 71 | |
| 72 | |
| 73 | void |