Algorithm-LibLinear
view release on metacpan or search on metacpan
src/liblinear/linear.cpp view on Meta::CPAN
inner_iter++;
}
if(inner_iter > 0) // update w
{
alpha[ind1] = z;
alpha[ind2] = C-z;
sparse_operator::axpy(sign*(z-alpha_old)*yi, xi, w);
}
}
iter++;
if(iter % 10 == 0)
info(".");
if(Gmax < eps)
break;
if(newton_iter <= l/10)
innereps = max(innereps_min, 0.1*innereps);
}
info("\noptimization finished, #iter = %d\n",iter);
// calculate objective value
double v = 0;
for(i=0; i<w_size; i++)
v += w[i] * w[i];
v *= 0.5;
for(i=0; i<l; i++)
v += alpha[2*i] * log(alpha[2*i]) + alpha[2*i+1] * log(alpha[2*i+1])
- upper_bound[GETI(i)] * log(upper_bound[GETI(i)]);
info("Objective value = %lf\n", v);
delete [] xTx;
delete [] alpha;
delete [] y;
delete [] index;
return iter;
}
// A coordinate descent algorithm for
// L1-regularized L2-loss support vector classification
//
// min_w \sum |wj| + C \sum max(0, 1-yi w^T xi)^2,
//
// Given:
// x, y, Cp, Cn
// eps is the stopping tolerance
//
// solution will be put in w
//
// this function returns the number of iterations
//
// See Yuan et al. (2010) and appendix of LIBLINEAR paper, Fan et al. (2008)
//
// To not regularize the bias (i.e., regularize_bias = 0), a constant feature = 1
// must have been added to the original data. (see -B and -R option)
#undef GETI
#define GETI(i) (y[i]+1)
// To support weights for instances, use GETI(i) (i)
static int solve_l1r_l2_svc(const problem *prob_col, const parameter* param, double *w, double Cp, double Cn, double eps)
{
int l = prob_col->l;
int w_size = prob_col->n;
int regularize_bias = param->regularize_bias;
int j, s, iter = 0;
int max_iter = 1000;
int active_size = w_size;
int max_num_linesearch = 20;
double sigma = 0.01;
double d, G_loss, G, H;
double Gmax_old = INF;
double Gmax_new, Gnorm1_new;
double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
double d_old, d_diff;
double loss_old = 0, loss_new;
double appxcond, cond;
int *index = new int[w_size];
schar *y = new schar[l];
double *b = new double[l]; // b = 1-ywTx
double *xj_sq = new double[w_size];
feature_node *x;
double C[3] = {Cn,0,Cp};
// Initial w can be set here.
for(j=0; j<w_size; j++)
w[j] = 0;
for(j=0; j<l; j++)
{
b[j] = 1;
if(prob_col->y[j] > 0)
y[j] = 1;
else
y[j] = -1;
}
for(j=0; j<w_size; j++)
{
index[j] = j;
xj_sq[j] = 0;
x = prob_col->x[j];
while(x->index != -1)
{
int ind = x->index-1;
x->value *= y[ind]; // x->value stores yi*xij
double val = x->value;
b[ind] -= w[j]*val;
xj_sq[j] += C[GETI(ind)]*val*val;
x++;
}
}
src/liblinear/linear.cpp view on Meta::CPAN
}
Gmax_old = Gmax_new;
}
info("\noptimization finished, #iter = %d\n", iter);
if(iter >= max_iter)
info("\nWARNING: reaching max number of iterations\n");
// calculate objective value
double v = 0;
int nnz = 0;
for(j=0; j<w_size; j++)
{
x = prob_col->x[j];
while(x->index != -1)
{
x->value *= prob_col->y[x->index-1]; // restore x->value
x++;
}
if(w[j] != 0)
{
v += fabs(w[j]);
nnz++;
}
}
if (regularize_bias == 0)
v -= fabs(w[w_size-1]);
for(j=0; j<l; j++)
if(b[j] > 0)
v += C[GETI(j)]*b[j]*b[j];
info("Objective value = %lf\n", v);
info("#nonzeros/#features = %d/%d\n", nnz, w_size);
delete [] index;
delete [] y;
delete [] b;
delete [] xj_sq;
return iter;
}
// A coordinate descent algorithm for
// L1-regularized logistic regression problems
//
// min_w \sum |wj| + C \sum log(1+exp(-yi w^T xi)),
//
// Given:
// x, y, Cp, Cn
// eps is the stopping tolerance
//
// solution will be put in w
//
// this function returns the number of iterations
//
// See Yuan et al. (2011) and appendix of LIBLINEAR paper, Fan et al. (2008)
//
// To not regularize the bias (i.e., regularize_bias = 0), a constant feature = 1
// must have been added to the original data. (see -B and -R option)
#undef GETI
#define GETI(i) (y[i]+1)
// To support weights for instances, use GETI(i) (i)
static int solve_l1r_lr(const problem *prob_col, const parameter *param, double *w, double Cp, double Cn, double eps)
{
int l = prob_col->l;
int w_size = prob_col->n;
int regularize_bias = param->regularize_bias;
int j, s, newton_iter=0, iter=0;
int max_newton_iter = 100;
int max_iter = 1000;
int max_num_linesearch = 20;
int active_size;
int QP_active_size;
double nu = 1e-12;
double inner_eps = 1;
double sigma = 0.01;
double w_norm, w_norm_new;
double z, G, H;
double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
double Gmax_old = INF;
double Gmax_new, Gnorm1_new;
double QP_Gmax_old = INF;
double QP_Gmax_new, QP_Gnorm1_new;
double delta, negsum_xTd, cond;
int *index = new int[w_size];
schar *y = new schar[l];
double *Hdiag = new double[w_size];
double *Grad = new double[w_size];
double *wpd = new double[w_size];
double *xjneg_sum = new double[w_size];
double *xTd = new double[l];
double *exp_wTx = new double[l];
double *exp_wTx_new = new double[l];
double *tau = new double[l];
double *D = new double[l];
feature_node *x;
double C[3] = {Cn,0,Cp};
// Initial w can be set here.
for(j=0; j<w_size; j++)
w[j] = 0;
for(j=0; j<l; j++)
{
if(prob_col->y[j] > 0)
y[j] = 1;
else
y[j] = -1;
exp_wTx[j] = 0;
}
w_norm = 0;
for(j=0; j<w_size; j++)
src/liblinear/linear.cpp view on Meta::CPAN
return iter;
}
// transpose matrix X from row format to column format
static void transpose(const problem *prob, feature_node **x_space_ret, problem *prob_col)
{
int i;
int l = prob->l;
int n = prob->n;
size_t nnz = 0;
size_t *col_ptr = new size_t [n+1];
feature_node *x_space;
prob_col->l = l;
prob_col->n = n;
prob_col->y = new double[l];
prob_col->x = new feature_node*[n];
for(i=0; i<l; i++)
prob_col->y[i] = prob->y[i];
for(i=0; i<n+1; i++)
col_ptr[i] = 0;
for(i=0; i<l; i++)
{
feature_node *x = prob->x[i];
while(x->index != -1)
{
nnz++;
col_ptr[x->index]++;
x++;
}
}
for(i=1; i<n+1; i++)
col_ptr[i] += col_ptr[i-1] + 1;
x_space = new feature_node[nnz+n];
for(i=0; i<n; i++)
prob_col->x[i] = &x_space[col_ptr[i]];
for(i=0; i<l; i++)
{
feature_node *x = prob->x[i];
while(x->index != -1)
{
int ind = x->index-1;
x_space[col_ptr[ind]].index = i+1; // starts from 1
x_space[col_ptr[ind]].value = x->value;
col_ptr[ind]++;
x++;
}
}
for(i=0; i<n; i++)
x_space[col_ptr[i]].index = -1;
*x_space_ret = x_space;
delete [] col_ptr;
}
// label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data
// perm, length l, must be allocated before calling this subroutine
static void group_classes(const problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm)
{
int l = prob->l;
int max_nr_class = 16;
int nr_class = 0;
int *label = Malloc(int,max_nr_class);
int *count = Malloc(int,max_nr_class);
int *data_label = Malloc(int,l);
int i;
for(i=0;i<l;i++)
{
int this_label = (int)prob->y[i];
int j;
for(j=0;j<nr_class;j++)
{
if(this_label == label[j])
{
++count[j];
break;
}
}
data_label[i] = j;
if(j == nr_class)
{
if(nr_class == max_nr_class)
{
max_nr_class *= 2;
label = (int *)realloc(label,max_nr_class*sizeof(int));
count = (int *)realloc(count,max_nr_class*sizeof(int));
}
label[nr_class] = this_label;
count[nr_class] = 1;
++nr_class;
}
}
//
// Labels are ordered by their first occurrence in the training set.
// However, for two-class sets with -1/+1 labels and -1 appears first,
// we swap labels to ensure that internally the binary SVM has positive data corresponding to the +1 instances.
//
if (nr_class == 2 && label[0] == -1 && label[1] == 1)
{
swap(label[0],label[1]);
swap(count[0],count[1]);
for(i=0;i<l;i++)
{
if(data_label[i] == 0)
data_label[i] = 1;
else
data_label[i] = 0;
}
}
int *start = Malloc(int,nr_class);
start[0] = 0;
for(i=1;i<nr_class;i++)
start[i] = start[i-1]+count[i-1];
( run in 0.734 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )