📄 svm.cpp
字号:
if(nonzero[sj+k])
model->sv_coef[i][q++] = f[p].alpha[ci+k];
++p;
}
free(label);
free(probA);
free(probB);
free(count);
free(perm);
free(start);
free(x);
free(weighted_C);
free(nonzero);
for(i=0;i<nr_class*(nr_class-1)/2;i++)
free(f[i].alpha);
free(f);
free(nz_count);
free(nz_start);
}
return model;
}
// Stratified cross validation
void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, int nr_fold, double *target)
{
int i;
int *fold_start = Malloc(int,nr_fold+1);
int l = prob->l;
int *perm = Malloc(int,l);
int nr_class;
// stratified cv may not give leave-one-out rate
// Each class to l folds -> some folds may have zero elements
if((param->svm_type == C_SVC ||
param->svm_type == NU_SVC) && nr_fold < l)
{
int *start = NULL;
int *label = NULL;
int *count = NULL;
svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
// random shuffle and then data grouped by fold using the array perm
int *fold_count = Malloc(int,nr_fold);
int c;
int *index = Malloc(int,l);
for(i=0;i<l;i++)
index[i]=perm[i];
for (c=0; c<nr_class; c++)
for(i=0;i<count[c];i++)
{
int j = i+rand()%(count[c]-i);
swap(index[start[c]+j],index[start[c]+i]);
}
for(i=0;i<nr_fold;i++)
{
fold_count[i] = 0;
for (c=0; c<nr_class;c++)
fold_count[i]+=(i+1)*count[c]/nr_fold-i*count[c]/nr_fold;
}
fold_start[0]=0;
for (i=1;i<=nr_fold;i++)
fold_start[i] = fold_start[i-1]+fold_count[i-1];
for (c=0; c<nr_class;c++)
for(i=0;i<nr_fold;i++)
{
int begin = start[c]+i*count[c]/nr_fold;
int end = start[c]+(i+1)*count[c]/nr_fold;
for(int j=begin;j<end;j++)
{
perm[fold_start[i]] = index[j];
fold_start[i]++;
}
}
fold_start[0]=0;
for (i=1;i<=nr_fold;i++)
fold_start[i] = fold_start[i-1]+fold_count[i-1];
free(start);
free(label);
free(count);
free(index);
free(fold_count);
}
else
{
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 svm_problem subprob;
subprob.l = l-(end-begin);
subprob.x = Malloc(struct svm_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 svm_model *submodel = svm_train(&subprob,param);
if(param->probability &&
(param->svm_type == C_SVC || param->svm_type == NU_SVC))
{
double *prob_estimates=Malloc(double,svm_get_nr_class(submodel));
for(j=begin;j<end;j++)
target[perm[j]] = svm_predict_probability(submodel,prob->x[perm[j]],prob_estimates);
free(prob_estimates);
}
else
for(j=begin;j<end;j++)
target[perm[j]] = svm_predict(submodel,prob->x[perm[j]]);
svm_destroy_model(submodel);
free(subprob.x);
free(subprob.y);
}
free(fold_start);
free(perm);
}
int svm_get_svm_type(const svm_model *model)
{
return model->param.svm_type;
}
int svm_get_nr_class(const svm_model *model)
{
return model->nr_class;
}
void svm_get_labels(const svm_model *model, int* label)
{
if (model->label != NULL)
for(int i=0;i<model->nr_class;i++)
label[i] = model->label[i];
}
double svm_get_svr_probability(const svm_model *model)
{
if ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) &&
model->probA!=NULL)
return model->probA[0];
else
{
info("Model doesn't contain information for SVR probability inference\n");
return 0;
}
}
void svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values)
{
if(model->param.svm_type == ONE_CLASS ||
model->param.svm_type == EPSILON_SVR ||
model->param.svm_type == NU_SVR)
{
double *sv_coef = model->sv_coef[0];
double sum = 0;
for(int i=0;i<model->l;i++)
sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
sum -= model->rho[0];
*dec_values = sum;
}
else
{
int i;
int nr_class = model->nr_class;
int l = model->l;
double *kvalue = Malloc(double,l);
for(i=0;i<l;i++)
kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
int *start = Malloc(int,nr_class);
start[0] = 0;
for(i=1;i<nr_class;i++)
start[i] = start[i-1]+model->nSV[i-1];
int p=0;
int pos=0;
for(i=0;i<nr_class;i++)
for(int j=i+1;j<nr_class;j++)
{
double sum = 0;
int si = start[i];
int sj = start[j];
int ci = model->nSV[i];
int cj = model->nSV[j];
int k;
double *coef1 = model->sv_coef[j-1];
double *coef2 = model->sv_coef[i];
for(k=0;k<ci;k++)
sum += coef1[si+k] * kvalue[si+k];
for(k=0;k<cj;k++)
sum += coef2[sj+k] * kvalue[sj+k];
sum -= model->rho[p++];
dec_values[pos++] = sum;
}
free(kvalue);
free(start);
}
}
double svm_predict(const svm_model *model, const svm_node *x)
{
if(model->param.svm_type == ONE_CLASS ||
model->param.svm_type == EPSILON_SVR ||
model->param.svm_type == NU_SVR)
{
double res;
svm_predict_values(model, x, &res);
if(model->param.svm_type == ONE_CLASS)
return (res>0)?1:-1;
else
return res;
}
else
{
int i;
int nr_class = model->nr_class;
double *dec_values = Malloc(double, nr_class*(nr_class-1)/2);
svm_predict_values(model, x, dec_values);
int *vote = Malloc(int,nr_class);
for(i=0;i<nr_class;i++)
vote[i] = 0;
int pos=0;
for(i=0;i<nr_class;i++)
for(int j=i+1;j<nr_class;j++)
{
if(dec_values[pos++] > 0)
++vote[i];
else
++vote[j];
}
int vote_max_idx = 0;
for(i=1;i<nr_class;i++)
if(vote[i] > vote[vote_max_idx])
vote_max_idx = i;
free(vote);
free(dec_values);
return model->label[vote_max_idx];
}
}
double svm_predict_probability(
const svm_model *model, const svm_node *x, double *prob_estimates)
{
if ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&
model->probA!=NULL && model->probB!=NULL)
{
int i;
int nr_class = model->nr_class;
double *dec_values = Malloc(double, nr_class*(nr_class-1)/2);
svm_predict_values(model, x, dec_values);
double min_prob=1e-7;
double **pairwise_prob=Malloc(double *,nr_class);
for(i=0;i<nr_class;i++)
pairwise_prob[i]=Malloc(double,nr_class);
int k=0;
for(i=0;i<nr_class;i++)
for(int j=i+1;j<nr_class;j++)
{
pairwise_prob[i][j]=min(max(sigmoid_predict(dec_values[k],model->probA[k],model->probB[k]),min_prob),1-min_prob);
pairwise_prob[j][i]=1-pairwise_prob[i][j];
k++;
}
multiclass_probability(nr_class,pairwise_prob,prob_estimates);
int prob_max_idx = 0;
for(i=1;i<nr_class;i++)
if(prob_estimates[i] > prob_estimates[prob_max_idx])
prob_max_idx = i;
for(i=0;i<nr_class;i++)
free(pairwise_prob[i]);
free(dec_values);
free(pairwise_prob);
return model->label[prob_max_idx];
}
else
return svm_predict(model, x);
}
const char *svm_type_table[] =
{
"c_svc","nu_svc","one_class","epsilon_svr","nu_svr",NULL
};
const char *kernel_type_table[]=
{
"linear","polynomial","rbf","sigmoid",NULL
};
int svm_save_model(const char *model_file_name, const svm_model *model)
{
FILE *fp = fopen(model_file_name,"w");
if(fp==NULL) return -1;
const svm_parameter& param = model->param;
fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]);
fprintf(fp,"kernel_type %s\n", kernel_type_table[param.kernel_type]);
if(param.kernel_type == POLY)
fprintf(fp,"degree %g\n", param.degree);
if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID)
fprintf(fp,"gamma %g\n", param.gamma);
if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
fprintf(fp,"coef0 %g\n", param.coef0);
int nr_class = model->nr_class;
int l = model->l;
fprintf(fp, "nr_class %d\n", nr_class);
fprintf(fp, "total_sv %d\n",l);
{
fprintf(fp, "rho");
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
fprintf(fp," %g",model->rho[i]);
fprintf(fp, "\n");
}
if(model->label)
{
fprintf(fp, "label");
for(int i=0;i<nr_class;i++)
fprintf(fp," %d",model->label[i]);
fprintf(fp, "\n");
}
if(model->probA) // regression has probA only
{
fprintf(fp, "probA");
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
fprintf(fp," %g",model->probA[i]);
fprintf(fp, "\n");
}
if(model->probB)
{
fprintf(fp, "probB");
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
fprintf(fp," %g",model->probB[i]);
fprintf(fp, "\n");
}
if(model->nSV)
{
fprintf(fp, "nr_sv");
for(int i=0;i<nr_class;i++)
fprintf(fp," %d",model->nSV[i]);
fprintf(fp, "\n");
}
fprintf(fp, "SV\n");
const double * const *sv_coef = model->sv_coef;
const svm_node * const *SV = model->SV;
for(int i=0;i<l;i++)
{
for(int j=0;j<nr_class-1;j++)
fprintf(fp, "%.16g ",sv_coef[j][i]);
const svm_node *p = SV[i];
while(p->index != -1)
{
fprintf(fp,"%d:%.8g ",p->index,p->value);
p++;
}
fprintf(fp, "\n");
}
fclose(fp);
return 0;
}
svm_model *svm_load_model(const char *model_file_name)
{
FILE *fp = fopen(model_file_name,"rb");
if(fp==NULL) return NULL;
// read parameters
svm_model *model = Malloc(svm_model,1);
svm_parameter& param = model->param;
model->rho = NULL;
model->probA = NULL;
model->probB = NULL;
model->label = NULL;
model->nSV = NULL;
char cmd[81];
while(1)
{
fscanf(fp,"%80s",cmd);
if(strcmp(cmd,"svm_type")==0)
{
fscanf(fp,"%80s",cmd);
int i;
for(i=0;svm_type_table[i];i++)
{
if(strcmp(svm_type_table[i],cmd)==0)
{
param.svm_type=i;
break;
}
}
if(svm_type_table[i] == NULL)
{
fprintf(stderr,"unknown svm type.\n");
free(model->rho);
free(model->label);
free(model->nSV);
free(model);
return NULL;
}
}
else if(strcmp(cmd,"kernel_type")==0)
{
fscanf(fp,"%80s",cmd);
int i;
for(i=0;kernel_type_table[i];i++)
{
if(strcmp(kernel_type_table[i],cmd)==0)
{
param.kernel_type=i;
break;
}
}
if(kernel_type_table[i] == NULL)
{
fprintf(stderr,"unknown kernel function.\n");
free(model->rho);
free(model->label);
free(model->nSV);
free(model);
return NULL;
}
}
else if(strcmp(cmd,"degree")==0)
fscanf(fp,"%lf",¶m.degree);
else if(strcmp(cmd,"gamma")==0)
fscanf(fp,"%lf",¶m.gamma);
else if(strcmp(cmd,"coef0")==0)
fscanf(fp,"%lf",¶m.coef0);
else if(strcmp(cmd,"nr_class")==0)
fscanf(fp,"%d",&model->nr_class);
else if(strcmp(cmd,"total_sv")==0)
fscanf(fp,"%d",&model->l);
else if(strcmp(cmd,"rho")==0)
{
int n = model->nr_class * (model->nr_class-1)/2;
model->rho = Malloc(double,n);
for(int i=0;i<n;i++)
fscanf(fp,"%lf",&model->rho[i]);
}
else if(strcmp(cmd,"label")==0)
{
int n = model->nr_class;
model->label = Malloc(int,n);
for(int i=0;i<n;i++)
fscanf(fp,"%d",&model->label[i]);
}
else if(strcmp(cmd,"probA")==0)
{
int n = model->nr_class * (model->nr_class-1)/2;
model->probA = Malloc(double,n);
for(int i=0;i<n;i++)
fscanf(fp,"%lf",&model->probA[i]);
}
else if(strcmp(cmd,"probB")==0)
{
int n = model->nr_class * (model->nr_class-1)/2;
model->probB = Malloc(double,n);
for(int i=0;i<n;i++)
fscanf(fp,"%lf",&model->probB[i]);
}
else if(strcmp(cmd,"nr_sv")==0)
{
int n = model->nr_class;
model->nSV = Malloc(int,n);
for(int i=0;i<n;i++)
fscanf(fp,"%d",&model->nSV[i]);
}
else if(strcmp(cmd,"SV")==0)
{
while(1)
{
int c = getc(fp);
if(c==EOF || c=='\n') break;
}
break;
}
else
{
fprintf(stderr,"unknown text in model file\n");
free(model->rho);
free(model->label);
free(model->nSV);
free(model);
return NULL;
}
}
// read sv_coef and SV
int elements = 0;
long pos = ftell(fp);
while(1)
{
int c = fgetc(fp);
switch(c)
{
case '\n':
// count the '-1' element
case ':':
++elements;
break;
case EOF:
goto out;
default:
;
}
}
out:
fseek(fp,pos,SEEK_SET);
int m = model->nr_class - 1;
int l = model->l;
model->sv_coef = Malloc(double *,m);
int i;
for(i=0;i<m;i++)
model->sv_coef[i] = Malloc(double,l);
model->SV = Malloc(svm_node*,l);
svm_node *x_space=NULL;
if(l>0) x_space = Malloc(svm_node,elements);
int j=0;
for(i=0;i<l;i++)
{
model->SV[i] = &x_space[j];
for(int k=0;k<m;k++)
fscanf(fp,"%lf",&model->sv_coef[k][i]);
while(1)
{
int c;
do {
c = getc(fp);
if(c=='\n') goto out2;
} while(isspace(c));
ungetc(c,fp);
fscanf(fp,"%d:%lf",&(x_space[j].index),&(x_space[j].value));
++j;
}
out2:
x_space[j++].index = -1;
}
fclose(fp);
model->free_sv = 1; // XXX
return model;
}
void svm_destroy_model(svm_model* model)
{
if(model->free_sv && model->l > 0)
free((void *)(model->SV[0]));
for(int i=0;i<model->nr_class-1;i++)
free(model->sv_coef[i]);
free(model->SV);
free(model->sv_coef);
fr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -