读取svm_model

实现将存在一个文件中的svm_model读入内存。

char* readline(FILE *input)
{
int len;

if(fgets(line,max_line_len,input) == NULL)//从input中读取max_line_len个字符到line中,成功就返回指针line
return NULL;
//在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
//返回位置,如果没有找到返回空指针
while(strrchr(line,'\n') == NULL)
{
max_line_len *= 2;
line = (char *) realloc(line,max_line_len);
len = (int) strlen(line);
if(fgets(line+len,max_line_len-len,input) == NULL)
break;
}
return line;
}

#define FSCANF(_stream, _format, _var) do{ if (fscanf(_stream, _format, _var) != 1) return false; }while(0)
bool read_model_header(FILE *fp, struct svm_model* model)//格式化的读入模型
{
//svm_parameter& param = model->param;
//这个是C++中的引用,在C++中又省去了struct,param是个实在的变量,引用就是一个别名
// parameters for training only won't be assigned, but arrays are assigned as NULL for safety
//仅用于训练的参数将不会被分配,但为了安全起见,将数组分配为NULL
model->param.nr_weight = 0;
model->param.weight_label = NULL;
model->param.weight = NULL;

char cmd[81];
while(1)
{
FSCANF(fp,"%80s",cmd);//从fp读取格式化输入,最大读取80个字符的字符串到cmd
//s这将读取连续字符,直到遇到一个空格字符
//如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

if(strcmp(cmd,"svm_type")==0)//比较cmd中的字符串与"svm_type"大小,应该是按ascii比较,如果相等返回零
{
FSCANF(fp,"%80s",cmd);
int i;
for(i=0;svm_type_table[i];i++)
{
if(strcmp(svm_type_table[i],cmd)==0)
{
model->param.svm_type=i;
break;
}
}
if(svm_type_table[i] == NULL)
{
fprintf(stderr,"unknown svm type.\n");
return false;
}
}
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)
{
model->param.kernel_type=i;
break;
}
}
if(kernel_type_table[i] == NULL)
{
fprintf(stderr,"unknown kernel function.\n");
return false;
}
}
else if(strcmp(cmd,"gamma")==0)//有
FSCANF(fp,"%lf",&model->param.gamma);

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;//nr_class为4,n为6
model->rho = Malloc(double,n);
int i;
for(i=0;i<n;i++)
FSCANF(fp,"%lf",&model->rho[i]);
}
else if(strcmp(cmd,"label")==0)//有
{
int i;
int n = model->nr_class;
model->label = Malloc(int,n);
for(i=0;i<n;i++)
FSCANF(fp,"%d",&model->label[i]);
}

else if(strcmp(cmd,"nr_sv")==0)//有
{
int i;
int n = model->nr_class;
model->nSV = Malloc(int,n);
for(i=0;i<n;i++)
FSCANF(fp,"%d",&model->nSV[i]);
}
else if(strcmp(cmd,"SV")==0)//有
{
while(1)
{
//从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
//该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。
int c = getc(fp);
if(c==EOF || c=='\n') break;
}
break;
}
else
{
fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
return false;
}
}

return true;

}

struct svm_model *svm_load_model(const char *model_file_name)
{
FILE *fp = fopen(model_file_name,"rb");//打开文件
if(fp==NULL) return NULL;//如果打开失败,返回空指针

char *old_locale = setlocale(LC_ALL, NULL);//设置或读取地域化信息。
if (old_locale) {
old_locale = strdup(old_locale);
}
setlocale(LC_ALL, "C");

// read parameters

struct svm_model *model = Malloc(struct svm_model,1);//宏定义分配内存
model->rho = NULL;//先初始化为空,
model->probA = NULL;
model->probB = NULL;
model->sv_indices = NULL;
model->label = NULL;
model->nSV = NULL;

// read header
if (!read_model_header(fp, model))
{
fprintf(stderr, "ERROR: fscanf failed to read model\n");
setlocale(LC_ALL, old_locale);
free(old_locale);
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);//返回给定流 stream 的当前文件位置。

max_line_len = 1024;
line = Malloc(char,max_line_len);//分配内存,
char *p,*endptr,*idx,*val;

while(readline(fp)!=NULL)
{
//获取第一个字符串
p = strtok(line,":");//分解字符串 str 为一组字符串,delim 为分隔符。
while(1)
{
//获取其他字符串
p = strtok(NULL,":");
if(p == NULL)
break;
++elements;
}
}
elements += model->l;

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(struct svm_node*,l);
struct svm_node *x_space = NULL;
if(l>0) x_space = Malloc(struct svm_node,elements);

int j=0;
for(i=0;i<l;i++)
{
int k;
readline(fp);
model->SV[i] = &x_space[j];

p = strtok(line, " \t");
model->sv_coef[0][i] = strtod(p,&endptr);
for(k=1;k<m;k++)
{
p = strtok(NULL, " \t");
model->sv_coef[k][i] = strtod(p,&endptr);
}

while(1)
{
idx = strtok(NULL, ":");
val = strtok(NULL, " \t");

if(val == NULL)
break;
x_space[j].index = (int) strtol(idx,&endptr,10);
x_space[j].value = strtod(val,&endptr);

++j;
}
x_space[j++].index = -1;
}
free(line);

setlocale(LC_ALL, old_locale);
free(old_locale);

if (ferror(fp) != 0 || fclose(fp) != 0)
return NULL;

model->free_sv = 1; // XXX
return model;
}

转载于:https://www.cnblogs.com/keda/p/8973473.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值