Skip to content

Commit 600784f

Browse files
committed
Minor changes SVM
1 parent ea67b9c commit 600784f

File tree

4 files changed

+29
-24
lines changed

4 files changed

+29
-24
lines changed

example/src/mnist/run_svm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ int main(int argc, char** argv) {
2020
pca_args.keep_percent = 0.8; // Keep at least 80% of information
2121
pca_args.scale_factor = 1E2; // More accurate but slower PCA
2222

23-
run_classifier(mnist_path, pca_args, ml::svm<svm_kernel_t, label_t>(C, ker, 2, 0.1));
23+
run_classifier(mnist_path, pca_args, ml::svm<svm_kernel_t, label_t>(C, ker, 2, 0.1, 0.1));
2424

2525
return 0;
2626
}

include/ml/classifiers/classifier.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ class classifier {
5151
* @param[in] expected
5252
* @param nb_obs
5353
*/
54-
void print_score(const LabelT* predicted, const LabelT* expected, unsigned nb_obs) {
55-
auto nb_labels = get_nb_labels();
54+
static void print_score(const LabelT* predicted, const LabelT* expected, unsigned nb_obs, unsigned nb_labels,
55+
const std::unordered_map<LabelT, unsigned>& label_user_to_label_idx) {
5656
std::vector<unsigned> cm(nb_labels * nb_labels, 0);
5757
for (unsigned i = 0; i < nb_obs; ++i)
58-
cm[_label_user_to_label_idx[expected[i]] * nb_labels + _label_user_to_label_idx[predicted[i]]] += 1;
58+
cm[label_user_to_label_idx.at(expected[i]) * nb_labels + label_user_to_label_idx.at(predicted[i])] += 1;
5959

6060
double success_rate = 0;
6161
double precision = 0;
@@ -100,6 +100,10 @@ class classifier {
100100
std::cout.fill(prev_fill);
101101
}
102102

103+
inline void print_score(const LabelT* predicted, const LabelT* expected, unsigned nb_obs) {
104+
classifier<DataT, LabelT>::print_score(predicted, expected, nb_obs, get_nb_labels(), _label_user_to_label_idx);
105+
}
106+
103107
virtual void load_from_disk(queue&) { assert(false); }
104108
virtual void save_to_disk(queue&) { assert(false); }
105109

include/ml/classifiers/svm/smo.hpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -284,15 +284,15 @@ struct smo_out {
284284
* @param[in] x data of size mxn where m is the number of observation
285285
* @param[in] y labels must be a vector of size pow2(m) with -1 or 1 the first m elements and 0 after
286286
* @param c parameter for C-SVM
287-
* @param tol criteria for stopping condition, should be greater than eps
288-
* @param eps threshold above which alpha needs to be to be used as a weight of a support vector
287+
* @param tol criteria for stopping condition
288+
* @param alpha_eps threshold above which alpha needs to be to be used as a weight of a support vector
289289
* @param max_nb_iter maximum number of iterations
290290
* @param kernel_cache
291291
* @return smo_out containing the support vectors svs, the alphas (multiplied by their respective labels) and
292292
* the offset rho
293293
*/
294294
template <class KernelCacheT, class T>
295-
smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T eps, SYCLIndexT max_nb_iter,
295+
smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T alpha_eps, SYCLIndexT max_nb_iter,
296296
KernelCacheT kernel_cache) {
297297
auto m = access_ker_dim(x, 0);
298298
assert_eq(y.kernel_range.get_global_linear_range(), to_pow2(m));
@@ -309,8 +309,8 @@ smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T eps, SYCL
309309
vector_t<T> vec_cond_greater(y.data_range, y.kernel_range);
310310
vector_t<T> vec_cond_less(y.data_range, y.kernel_range);
311311

312-
auto cond_greater = [c, eps](T y, T a) { return T((y > 0 && a < c) || (y < 0 && a > eps)); };
313-
auto cond_less = [c, eps](T y, T a) { return T((y > 0 && a > eps) || (y < 0 && a < c)); };
312+
auto cond_greater = [c, alpha_eps](T y, T a) { return T((y > 0 && a < c) || (y < 0 && a > alpha_eps)); };
313+
auto cond_less = [c, alpha_eps](T y, T a) { return T((y > 0 && a > alpha_eps) || (y < 0 && a < c)); };
314314

315315
// Compute initial cond
316316
vec_unary_op(q, y, vec_cond_greater, ml::functors::positive<T>());
@@ -325,6 +325,7 @@ smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T eps, SYCL
325325
SYCLIndexT j;
326326
T diff;
327327
SYCLIndexT nb_iter = 0;
328+
T eps = 1E-8;
328329
while (nb_iter < max_nb_iter) {
329330
if (!detail::select_wss(q, y, gradient, vec_cond_greater, vec_cond_less, tol, eps, start_search_indices,
330331
start_search_rng, find_size_threshold_host, kernel_cache, i, j, diff)) {
@@ -360,19 +361,17 @@ smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T eps, SYCL
360361
// Update gradient
361362
T delta_ai = yi * (ai - old_ai);
362363
T delta_aj = yj * (aj - old_aj);
364+
363365
// Shouldn't happen in theory but can because of precision issue
364-
if (std::abs(delta_ai) < eps && std::abs(delta_aj) < eps) {
365-
std::cerr << "SVM cannot converge, try setting a smaller eps or a bigger tol." << std::endl;
366-
break;
367-
}
368-
else {
369-
detail::update_gradient(q, delta_ai, delta_aj, ker_i_t, ker_j_t, gradient);
370-
vec_cond_greater.write_from_host(i, cond_greater(yi, ai));
371-
vec_cond_greater.write_from_host(j, cond_greater(yj, aj));
372-
vec_cond_less.write_from_host(i, cond_less(yi, ai));
373-
vec_cond_less.write_from_host(j, cond_less(yj, aj));
374-
++nb_iter;
375-
}
366+
assert(std::abs(delta_ai) >= eps);
367+
assert(std::abs(delta_aj) >= eps);
368+
369+
detail::update_gradient(q, delta_ai, delta_aj, ker_i_t, ker_j_t, gradient);
370+
vec_cond_greater.write_from_host(i, cond_greater(yi, ai));
371+
vec_cond_greater.write_from_host(j, cond_greater(yj, aj));
372+
vec_cond_less.write_from_host(i, cond_less(yi, ai));
373+
vec_cond_less.write_from_host(j, cond_less(yj, aj));
374+
++nb_iter;
376375
}
377376

378377
if (nb_iter == max_nb_iter)
@@ -382,7 +381,7 @@ smo_out<T> smo(queue& q, matrix_t<T>& x, vector_t<T>& y, T c, T tol, T eps, SYCL
382381
auto host_alphas = alphas.template get_access<access::mode::read>();
383382
std::vector<uint32_t> host_sv_indices;
384383
for (unsigned k = 0; k < m; ++k) {
385-
if (host_alphas[k] > eps)
384+
if (host_alphas[k] > alpha_eps)
386385
host_sv_indices.push_back(k);
387386
}
388387
auto nb_sv = host_sv_indices.size();

include/ml/classifiers/svm/svm.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class svm : public classifier<typename KernelType::DataType, LabelType> {
5151
* @param max_nb_iter
5252
*/
5353
explicit svm(DataType c, KernelType ker = KernelType(), SYCLIndexT nb_cache_line = 2,
54-
DataType tol = 1E-2, DataType eps = 1E-8, SYCLIndexT max_nb_iter = 0) :
54+
DataType tol = 1E-2, DataType eps = 1E-2, SYCLIndexT max_nb_iter = 0) :
5555
_c(c), _ker(ker), _tol(tol), _eps(eps), _nb_cache_line(nb_cache_line), _max_nb_iter(max_nb_iter),
5656
_data_dim(0), _data_dim_pow2(0), _nb_labels(0), _smo_outs()
5757
{
@@ -196,7 +196,9 @@ class svm : public classifier<typename KernelType::DataType, LabelType> {
196196
std::cout << "Training (" << i << ", " << j << ") ..." << std::endl;
197197
// The padded nb_obs of act_data don't need to be initialized
198198
push_back_smo(q, act_data, act_internal_labels);
199-
std::cout << "Number support vectors: " << _smo_outs.back().alphas.data_range[0] << "\n" << std::endl;
199+
auto back = _smo_outs.back();
200+
std::cout << "Nb iter: " << back.nb_iter << "\n";
201+
std::cout << "Number support vectors: " << back.alphas.data_range[0] << "\n" << std::endl;
200202
}
201203
}
202204
}

0 commit comments

Comments
 (0)