SVECTOR *psi(PATTERNX x, LABEL y, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm) { /* Returns a feature vector describing the match between pattern x and label y. The feature vector is returned as an SVECTOR (i.e. pairs <featurenumber:featurevalue>), where the last pair has featurenumber 0 as a terminator. Featurenumbers start with 1 and end with sizePsi. This feature vector determines the linear evaluation function that is used to score labels. There will be one weight in sm.w for each feature. Note that psi has to match find_most_violated_constraint_???(x, y, sm) and vice versa. In particular, find_most_violated_constraint_???(x, y, sm) finds that ybar!=y that maximizes psi(x,ybar,sm)*sm.w (where * is the inner vector product) and the appropriate function of the loss. */ SVECTOR *fvec; if (sparm->loss_function == 2) { /* specific psi for bilinear SVM optimization */ fvec = smult_s(x.doc->fvec, y.classlabel==2 ? 0.5 : -0.5); fvec->words[0].weight = 0.0; /* nullify 'theta' */ } else { /* shift the feature numbers to the position of weight vector of class y */ fvec = shift_s(x.doc->fvec, (y.classlabel-1)*sparm->num_features); } /* The following makes sure that the weight vectors for each class are treated separately when kernels are used . */ fvec->kernel_id = y.classlabel; return(fvec); }
SVECTOR* add_list_ss(SVECTOR *a) /* computes the linear combination of the SVECTOR list weighted by the factor of each SVECTOR */ { SVECTOR *scaled,*oldsum,*sum,*f; WORD empty[2]; if(a){ sum=smult_s(a,a->factor); for(f=a->next;f;f=f->next) { scaled=smult_s(f,f->factor); oldsum=sum; sum=add_ss(sum,scaled); free_svector(oldsum); free_svector(scaled); } sum->factor=1.0; } else { empty[0].wnum=0; sum=create_svector(empty,"",1.0); } return(sum); }
SVECTOR* add_list_ss_r(SVECTOR *a, double min_non_zero) /* computes the linear combination of the SVECTOR list weighted by the factor of each SVECTOR */ { SVECTOR *oldsum,*sum,*f; WORD empty[2]; if(!a) { empty[0].wnum=0; sum=create_svector(empty,NULL,1.0); } else if(a && (!a->next)) { sum=smult_s(a,a->factor); } else { sum=multadd_ss_r(a,a->next,a->factor,a->next->factor,min_non_zero); for(f=a->next->next;f;f=f->next) { oldsum=sum; sum=multadd_ss_r(oldsum,f,1.0,f->factor,min_non_zero); free_svector(oldsum); } } return(sum); }
SVECTOR *psi(PATTERN x, LABEL y, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm) { /* Creates the feature vector \Psi(x,y) and return a pointer to sparse vector SVECTOR in SVM^light format. The dimension of the feature vector returned has to agree with the dimension in sm->sizePsi. */ SVECTOR *fvec=NULL; SVECTOR *psi1=NULL; SVECTOR *psi2=NULL; SVECTOR *temp_psi=NULL; SVECTOR *temp_sub=NULL; WORD *words = NULL; words = (WORD *) malloc(sizeof(WORD)); if(!words) die("Memory error."); words[0].wnum = 0; words[0].weight = 0; fvec = create_svector(words,"",1); psi1 = create_svector(words,"",1); psi2 = create_svector(words,"",1); free(words); int i,j = 0; for (i = 0; i < (x.n_pos+x.n_neg); i++){ if(y.labels[i] == 1){ temp_psi = add_ss(psi1, x.x_is[i].phi1phi2_pos); } else{ temp_psi = add_ss(psi1, x.x_is[i].phi1phi2_neg); } free_svector(psi1); psi1 = temp_psi; for (j=(i+1); j < (x.n_pos+x.n_neg); j++){ if(x.neighbors[i][j]){ if(y.labels[i] != y.labels[j]){ temp_sub = sub_ss_sq(x.x_is[i].phi1phi2_pos, x.x_is[j].phi1phi2_pos); temp_psi = add_ss(psi2, temp_sub); free_svector(temp_sub); free_svector(psi2); psi2 = temp_psi; } } } } // scale w1 by 1/n temp_psi = smult_s(psi1, (float)1/(float)(x.n_pos+x.n_neg)); free_svector(psi1); psi1 = temp_psi; // scale w2 by 1/n^2 if (x.n_neighbors){ temp_psi = smult_s(psi2, (float)1/(float)x.n_neighbors); free_svector(psi2); psi2 = temp_psi; } // concatenate psi1, psi2 temp_psi = create_svector_with_index(psi2->words, "", 1, (sparm->phi1_size+sparm->phi2_size)*2); free_svector(psi2); fvec = add_ss(psi1, temp_psi); free_svector(temp_psi); free_svector(psi1); return(fvec); }