Algorithm-LibLinear
view release on metacpan or search on metacpan
src/liblinear/linear.cpp view on Meta::CPAN
}
delete[] C;
}
// Calculate the initial C for parameter selection
static double calc_start_C(const problem *prob, const parameter *param)
{
int i;
double xTx, max_xTx;
max_xTx = 0;
for(i=0; i<prob->l; i++)
{
xTx = 0;
feature_node *xi=prob->x[i];
while(xi->index != -1)
{
double val = xi->value;
xTx += val*val;
xi++;
}
if(xTx > max_xTx)
max_xTx = xTx;
}
double min_C = 1.0;
if(param->solver_type == L2R_LR)
min_C = 1.0 / (prob->l * max_xTx);
else if(param->solver_type == L2R_L2LOSS_SVC)
min_C = 1.0 / (2 * prob->l * max_xTx);
else if(param->solver_type == L2R_L2LOSS_SVR)
{
double sum_y, loss, y_abs;
double delta2 = 0.1;
sum_y = 0, loss = 0;
for(i=0; i<prob->l; i++)
{
y_abs = fabs(prob->y[i]);
sum_y += y_abs;
loss += max(y_abs - param->p, 0.0) * max(y_abs - param->p, 0.0);
}
if(loss > 0)
min_C = delta2 * delta2 * loss / (8 * sum_y * sum_y * max_xTx);
else
min_C = INF;
}
return pow( 2, floor(log(min_C) / log(2.0)) );
}
static double calc_max_p(const problem *prob)
{
int i;
double max_p = 0.0;
for(i = 0; i < prob->l; i++)
max_p = max(max_p, fabs(prob->y[i]));
return max_p;
}
static void find_parameter_C(const problem *prob, parameter *param_tmp, double start_C, double max_C, double *best_C, double *best_score, const int *fold_start, const int *perm, const problem *subprob, int nr_fold)
{
// variables for CV
int i;
double *target = Malloc(double, prob->l);
// variables for warm start
double ratio = 2;
double **prev_w = Malloc(double*, nr_fold);
for(i = 0; i < nr_fold; i++)
prev_w[i] = NULL;
int num_unchanged_w = 0;
void (*default_print_string) (const char *) = liblinear_print_string;
if(param_tmp->solver_type == L2R_LR || param_tmp->solver_type == L2R_L2LOSS_SVC)
*best_score = 0.0;
else if(param_tmp->solver_type == L2R_L2LOSS_SVR)
*best_score = INF;
*best_C = start_C;
param_tmp->C = start_C;
while(param_tmp->C <= max_C)
{
//Output disabled for running CV at a particular C
set_print_string_function(&print_null);
for(i=0; i<nr_fold; i++)
{
int j;
int begin = fold_start[i];
int end = fold_start[i+1];
param_tmp->init_sol = prev_w[i];
struct model *submodel = train(&subprob[i],param_tmp);
int total_w_size;
if(submodel->nr_class == 2)
total_w_size = subprob[i].n;
else
total_w_size = subprob[i].n * submodel->nr_class;
if(prev_w[i] == NULL)
{
prev_w[i] = Malloc(double, total_w_size);
for(j=0; j<total_w_size; j++)
prev_w[i][j] = submodel->w[j];
}
else if(num_unchanged_w >= 0)
{
double norm_w_diff = 0;
for(j=0; j<total_w_size; j++)
{
norm_w_diff += (submodel->w[j] - prev_w[i][j])*(submodel->w[j] - prev_w[i][j]);
prev_w[i][j] = submodel->w[j];
}
norm_w_diff = sqrt(norm_w_diff);
if(norm_w_diff > 1e-15)
num_unchanged_w = -1;
}
else
{
for(j=0; j<total_w_size; j++)
prev_w[i][j] = submodel->w[j];
}
for(j=begin; j<end; j++)
target[perm[j]] = predict(submodel,prob->x[perm[j]]);
free_and_destroy_model(&submodel);
}
set_print_string_function(default_print_string);
if(param_tmp->solver_type == L2R_LR || param_tmp->solver_type == L2R_L2LOSS_SVC)
{
int total_correct = 0;
for(i=0; i<prob->l; i++)
if(target[i] == prob->y[i])
++total_correct;
double current_rate = (double)total_correct/prob->l;
if(current_rate > *best_score)
{
*best_C = param_tmp->C;
*best_score = current_rate;
}
info("log2c=%7.2f\trate=%g\n",log(param_tmp->C)/log(2.0),100.0*current_rate);
}
else if(param_tmp->solver_type == L2R_L2LOSS_SVR)
{
double total_error = 0.0;
for(i=0; i<prob->l; i++)
{
double y = prob->y[i];
double v = target[i];
total_error += (v-y)*(v-y);
}
double current_error = total_error/prob->l;
if(current_error < *best_score)
{
*best_C = param_tmp->C;
*best_score = current_error;
}
info("log2c=%7.2f\tp=%7.2f\tMean squared error=%g\n",log(param_tmp->C)/log(2.0),param_tmp->p,current_error);
}
num_unchanged_w++;
if(num_unchanged_w == 5)
break;
param_tmp->C = param_tmp->C*ratio;
}
if(param_tmp->C > max_C)
info("WARNING: maximum C reached.\n");
free(target);
for(i=0; i<nr_fold; i++)
free(prev_w[i]);
free(prev_w);
}
//
// Interface functions
//
model* train(const problem *prob, const parameter *param)
{
int i,j;
int l = prob->l;
int n = prob->n;
int w_size = prob->n;
model *model_ = Malloc(model,1);
if(prob->bias>=0)
model_->nr_feature=n-1;
else
model_->nr_feature=n;
model_->param = *param;
model_->bias = prob->bias;
if(check_regression_model(model_))
{
model_->w = Malloc(double, w_size);
if(param->init_sol != NULL)
for(i=0;i<w_size;i++)
model_->w[i] = param->init_sol[i];
else
for(i=0;i<w_size;i++)
model_->w[i] = 0;
model_->nr_class = 2;
model_->label = NULL;
train_one(prob, param, model_->w, 0, 0);
}
else if(check_oneclass_model(model_))
{
model_->w = Malloc(double, w_size);
model_->nr_class = 2;
model_->label = NULL;
solve_oneclass_svm(prob, param, model_->w, &(model_->rho));
}
src/liblinear/linear.cpp view on Meta::CPAN
void cross_validation(const problem *prob, const parameter *param, int nr_fold, double *target)
{
int i;
int *fold_start;
int l = prob->l;
int *perm = Malloc(int,l);
if (nr_fold > l)
{
nr_fold = l;
fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
}
fold_start = Malloc(int,nr_fold+1);
for(i=0;i<l;i++) perm[i]=i;
for(i=0;i<l;i++)
{
int j = i+rand()%(l-i);
swap(perm[i],perm[j]);
}
for(i=0;i<=nr_fold;i++)
fold_start[i]=i*l/nr_fold;
for(i=0;i<nr_fold;i++)
{
int begin = fold_start[i];
int end = fold_start[i+1];
int j,k;
struct problem subprob;
subprob.bias = prob->bias;
subprob.n = prob->n;
subprob.l = l-(end-begin);
subprob.x = Malloc(struct feature_node*,subprob.l);
subprob.y = Malloc(double,subprob.l);
k=0;
for(j=0;j<begin;j++)
{
subprob.x[k] = prob->x[perm[j]];
subprob.y[k] = prob->y[perm[j]];
++k;
}
for(j=end;j<l;j++)
{
subprob.x[k] = prob->x[perm[j]];
subprob.y[k] = prob->y[perm[j]];
++k;
}
struct model *submodel = train(&subprob,param);
for(j=begin;j<end;j++)
target[perm[j]] = predict(submodel,prob->x[perm[j]]);
free_and_destroy_model(&submodel);
free(subprob.x);
free(subprob.y);
}
free(fold_start);
free(perm);
}
void find_parameters(const problem *prob, const parameter *param, int nr_fold, double start_C, double start_p, double *best_C, double *best_p, double *best_score)
{
// prepare CV folds
int i;
int *fold_start;
int l = prob->l;
int *perm = Malloc(int, l);
struct problem *subprob = Malloc(problem,nr_fold);
if (nr_fold > l)
{
nr_fold = l;
fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
}
fold_start = Malloc(int,nr_fold+1);
for(i=0;i<l;i++) perm[i]=i;
for(i=0;i<l;i++)
{
int j = i+rand()%(l-i);
swap(perm[i],perm[j]);
}
for(i=0;i<=nr_fold;i++)
fold_start[i]=i*l/nr_fold;
for(i=0;i<nr_fold;i++)
{
int begin = fold_start[i];
int end = fold_start[i+1];
int j,k;
subprob[i].bias = prob->bias;
subprob[i].n = prob->n;
subprob[i].l = l-(end-begin);
subprob[i].x = Malloc(struct feature_node*,subprob[i].l);
subprob[i].y = Malloc(double,subprob[i].l);
k=0;
for(j=0;j<begin;j++)
{
subprob[i].x[k] = prob->x[perm[j]];
subprob[i].y[k] = prob->y[perm[j]];
++k;
}
for(j=end;j<l;j++)
{
subprob[i].x[k] = prob->x[perm[j]];
subprob[i].y[k] = prob->y[perm[j]];
++k;
}
}
struct parameter param_tmp = *param;
*best_p = -1;
if(param->solver_type == L2R_LR || param->solver_type == L2R_L2LOSS_SVC)
{
if(start_C <= 0)
start_C = calc_start_C(prob, ¶m_tmp);
double max_C = 1024;
start_C = min(start_C, max_C);
double best_C_tmp, best_score_tmp;
find_parameter_C(prob, ¶m_tmp, start_C, max_C, &best_C_tmp, &best_score_tmp, fold_start, perm, subprob, nr_fold);
*best_C = best_C_tmp;
*best_score = best_score_tmp;
}
else if(param->solver_type == L2R_L2LOSS_SVR)
{
double max_p = calc_max_p(prob);
int num_p_steps = 20;
double max_C = 1048576;
*best_score = INF;
i = num_p_steps-1;
if(start_p > 0)
i = min((int)(start_p/(max_p/num_p_steps)), i);
for(; i >= 0; i--)
{
param_tmp.p = i*max_p/num_p_steps;
double start_C_tmp;
if(start_C <= 0)
start_C_tmp = calc_start_C(prob, ¶m_tmp);
else
start_C_tmp = start_C;
start_C_tmp = min(start_C_tmp, max_C);
double best_C_tmp, best_score_tmp;
find_parameter_C(prob, ¶m_tmp, start_C_tmp, max_C, &best_C_tmp, &best_score_tmp, fold_start, perm, subprob, nr_fold);
if(best_score_tmp < *best_score)
{
*best_p = param_tmp.p;
*best_C = best_C_tmp;
*best_score = best_score_tmp;
}
}
}
free(fold_start);
free(perm);
for(i=0; i<nr_fold; i++)
{
free(subprob[i].x);
free(subprob[i].y);
}
free(subprob);
}
double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values)
{
int idx;
int n;
if(model_->bias>=0)
n=model_->nr_feature+1;
else
n=model_->nr_feature;
double *w=model_->w;
int nr_class=model_->nr_class;
int i;
int nr_w;
if(nr_class==2 && model_->param.solver_type != MCSVM_CS)
nr_w = 1;
else
nr_w = nr_class;
const feature_node *lx=x;
for(i=0;i<nr_w;i++)
dec_values[i] = 0;
for(; (idx=lx->index)!=-1; lx++)
{
// the dimension of testing data may exceed that of training
if(idx<=n)
for(i=0;i<nr_w;i++)
dec_values[i] += w[(idx-1)*nr_w+i]*lx->value;
}
if(check_oneclass_model(model_))
dec_values[0] -= model_->rho;
if(nr_class==2)
{
if(check_regression_model(model_))
return dec_values[0];
else if(check_oneclass_model(model_))
return (dec_values[0]>0)?1:-1;
else
return (dec_values[0]>0)?model_->label[0]:model_->label[1];
}
else
{
int dec_max_idx = 0;
for(i=1;i<nr_class;i++)
{
if(dec_values[i] > dec_values[dec_max_idx])
dec_max_idx = i;
( run in 0.738 second using v1.01-cache-2.11-cpan-39bf76dae61 )