⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svm_trans.c

📁 机器学习作者tom mitchell的书上代码
💻 C
字号:
/* Copyright (C) 1999 Greg Schohn - gcs@jprc.com *//* ********************* svm_trans.c ********************** * Code for transductive SVM's */ #include <bow/svm.h>/* anything > 1 will be verbose... *///#define DEBUG 1int transduce_svm(bow_wv **docs, int *yvect, int *trans_yvect_store, 		  double *weights, double *tvals, double *a_b, 		  double **W, int ndocs, int ntrans, int *up_nsv) {  double   cs_pos, cs_neg;  float   *cvect;  int      nlabeled;  int      nsolns;  int      nswitches;  int      nsv;  int     *old_yvect;  double   tb;  double   thresh;  double  *tmpdv;  float   *trans_cvect;  bow_wv **trans_docs;   int      trans_npos;   /* the # of docs that will get a + label */  double  *trans_scores; /* copy of the scores after the first run */  int     *trans_yvect;  struct svm_smo_model smo_model; /* needed if smo is used... */  int i,j,k;#ifdef DEBUG    double *oldw;#endif#if DEBUG>2  int foo;#endif  nsv = *up_nsv;  nlabeled = ndocs-ntrans;  trans_docs = &(docs[nlabeled]);  trans_yvect = &(yvect[nlabeled]);  /* don't want to crush existing labels? - so copy them */  old_yvect = (int *) malloc(sizeof(int)*ntrans);  for (i=0; i<ntrans; i++) {    old_yvect[i] = trans_yvect[i];  }  cvect = (float *) malloc(sizeof(float)*ndocs);  trans_cvect = &(cvect[nlabeled]);  for (i=0; i<nlabeled; i++) {    cvect[i] = (float) svm_C;  }  /* this is sortof necessary.  Because of the transduction algorithm,    * previous weights won't help since the bounds are iteratively    * increased at each step (ie. the inflow will be totally different   * than the outflow).  */  nsv = 0;  /* get the values for the unlabeled docs later */  for (i=0; i<nlabeled; i++) {    weights[i] = 0.0;    tvals[i] = 0.0;  }  /* this is done to simplify some of the higher level fns. */  if (*W) {    free(*W);  }  *W = NULL;  /* create the initial model */  solve_svm(docs, yvect, weights, &tb, W, nlabeled, tvals, cvect, &nsv);  tmpdv = (double *) malloc(sizeof(double)*ntrans);  trans_scores = (double *) malloc(sizeof(double)*ntrans);  trans_npos = 0;  /* classify all of the unlabeled docs */  for (i=0; i<ntrans; i++) {    if (svm_kernel_type == 0) {      tmpdv[i] = evaluate_model_hyperplane(*W, tb, trans_docs[i]);    } else {      tmpdv[i] = evaluate_model_cache(docs, weights, yvect, tb, trans_docs[i], nsv);    }    trans_scores[i] = tmpdv[i];    if (svm_trans_nobias) {      trans_yvect[i] = (tmpdv[i] > 0.0) ? 1 : -1;      if (tmpdv[i] > 0.0) {	trans_npos ++;      }    }  }  if (!svm_trans_nobias) {    qsort(tmpdv, ntrans, sizeof(double), d_cmp);    if (svm_trans_npos) {      /* sort happens in ascending order */      thresh = tmpdv[ntrans-svm_trans_npos];      trans_npos = svm_trans_npos;    } else {      /* k = npos in training set */      for (i=k=0; i<nlabeled; i++) {	if (yvect[i] > 0) {	  k++;	}      }      trans_npos = (int) ((k*ntrans)/nlabeled);      thresh = tmpdv[ntrans-trans_npos];    }  } else {    thresh = 0.0;  }#define EPSILON_CSTAR 1e-2  cs_neg = EPSILON_CSTAR;  cs_pos = EPSILON_CSTAR * (ntrans - trans_npos + 1)/trans_npos;  for (i=k=0; i<ntrans; i++) {    if (trans_scores[i] >= thresh && k < trans_npos) {      trans_yvect[i] = 1;      cvect[i+nlabeled] = cs_pos;      k++;    } else {      trans_yvect[i] = -1;      cvect[i+nlabeled] = cs_neg;    }  }  free(trans_scores);#if DEBUG > 1  printf("trans_yvect: %d: ", foo++);  for (i=0; i<ndocs-nlabeled; i++) {    printf("%d ", trans_yvect[i]);  }  printf("\n");  printf("trans cycle %d: ", foo++);  for (i=0; i<ndocs; i++) {    printf("%f ",weights[i]);  }  printf("\n");#endif  /* initialize what the tvect should look like for the unlabeled docs */  if (svm_use_smo) {    /* nothing needs to be done to the tvals since they are only valid for sv's */    for (i=nlabeled; i<ndocs; i++) {      weights[i] = 0.0;    }        /* setup model for future use */    /* only smo_evaluate_error uses this so only that info needs to be setup */    smo_model.docs = docs;    smo_model.yvect = yvect;    smo_model.ndocs = ndocs;    smo_model.weights = weights;  } else {    for (i=nlabeled; i<ndocs; i++) {      tvals[i] = 0.0;      for (j=k=0; j<nsv; k++) {	if (weights[k] > 0.0) {	  tvals[i] += weights[k]*yvect[k]*svm_kernel_cache(docs[k],docs[i]);	  j++;	}      }    }  }  nsolns = 1;  nswitches = 0;  /* this will need to be done more intelligently since this fn can be in   * an inner loop (active learning) */  while ((cs_pos < svm_trans_cstar) || (cs_neg < svm_trans_cstar)) {    int maxp=0, maxn=0;    double maxpv, maxnv;    /* switch loop */    do {      if (!svm_trans_smart_vals) {	nsv = 0;	/* get the values for the unlabeled docs later */	for (i=0; i<ndocs; i++) {	  weights[i] = 0.0;	  tvals[i] = 0.0;	}	free(*W);	*W = NULL;      } else {	/* if we don't need this - get rid of it */	if (svm_kernel_type == 0 && 	    (!svm_use_smo || !(nsolns % svm_trans_hyp_refresh))) {	  free(*W);	  *W = NULL;	}      }      nsolns ++;      solve_svm(docs, yvect, weights, &tb, W, ndocs, tvals, cvect, &nsv);      /* this block should be replaced by fns to convert tmp values       * into error values */      for (i=0; i<ntrans; i++) {	if (svm_kernel_type == 0) {	  tmpdv[i] = evaluate_model_hyperplane(*W, tb, trans_docs[i]);	} else {	  tmpdv[i] = evaluate_model_cache(docs, weights, yvect, tb, trans_docs[i], nsv);	}	if (trans_yvect[i] == 1 && tmpdv[i] < 1.0) {	  tmpdv[i] = 1.0 - tmpdv[i];	} else if (trans_yvect[i] == -1 && tmpdv[i] > -1.0) {	  tmpdv[i] = tmpdv[i] + 1.0;	} else {	  tmpdv[i] = 0.0;	}      }      for (i=0, maxnv=maxpv=0.0; i<ntrans; i++) {	if (trans_yvect[i] > 0) {	  if (tmpdv[i] > maxpv) {	    maxpv = tmpdv[i];	    maxp = i;	  }	} else {	  if (tmpdv[i] > maxnv) {	    maxnv = tmpdv[i];	    maxn = i;	  }	}      }      /* switch the largest 2 */      if (maxpv > 0.0 && maxnv > 0.0 && maxpv + maxnv > 2.0) {	nswitches++;	//printf("switching %d & %d\n",maxp,maxn);	if (bow_verbosity_level > 2) {	  fprintf(stderr,"  switching %d & %d\n",maxp,maxn);	} else {	  fprintf(stderr,"\r\t\t\t\t\t\t\t\t\t\t\t\t\t\tswitch #%d",nswitches);	}	trans_yvect[maxp] *= -1;	trans_yvect[maxn] *= -1;	/* need to also fix the hyperplane */	if (svm_kernel_type == 0 && (nsolns % svm_trans_hyp_refresh)) {	  for (j=maxp,k=0; k<2; j=maxn,k++) {	    for (i=0; i<trans_docs[j]->num_entries; i++) {	      (*W)[trans_docs[j]->entry[i].wi] += 		2 * trans_yvect[j] * weights[j+nlabeled] * trans_docs[j]->entry[i].weight;	    }	  }	}	if (svm_trans_smart_vals) {	  if (svm_use_smo) {	    double wi, wj;	    int yi, yj;	    yi = trans_yvect[maxn];	    yj = trans_yvect[maxp];	    wi = weights[nlabeled+maxn];	    wj = weights[nlabeled+maxp];	    /* set tmp vals */	    for (k=0; k<ndocs; k++) {	      if ((weights[k] < cvect[k] - svm_epsilon_a) && (weights[k] > svm_epsilon_a)) {		tvals[k] += 2*(wi*yi*svm_kernel_cache(docs[k],trans_docs[maxn]) + 			       wj*yj*svm_kernel_cache(docs[k],trans_docs[maxp]));	      }	    }#ifdef DEBUG	    /* sanity check */	    smo_model.W = *W;	    for (i=0; i<ndocs; i++) {	      if ((weights[i] < cvect[i] - svm_epsilon_a) && (weights[i] > svm_epsilon_a)) {		int tmp = tvals[i] - smo_evaluate_error(&smo_model, i);		if (tmp < 0) tmp *= -1;		if (tmp > 0.1) {		  double herror, verror;		  herror = smo_evaluate_error(&smo_model, i);		  svm_kernel_type = 1;		  verror = smo_evaluate_error(&smo_model, i);		  fprintf(stderr, "bad temporary (i=%d, tv[i]=%f, actual_H=%f, actual_V=%f)\n",i,tvals[i],			  herror, verror);		  svm_kernel_type = 0;		  fflush(stderr);		  kill(getpid(),SIGSTOP);		}	      }	    }#endif	  } else {	    double wn, wp;	    wn = weights[maxn+nlabeled] * trans_yvect[maxn];	    wp = weights[maxp+nlabeled] * trans_yvect[maxp];	  	    for (k=0; k<ndocs; k++) {	      tvals[k] += 2*(wn*svm_kernel_cache(docs[k],trans_docs[maxn]) + 			     wp*svm_kernel_cache(docs[k],trans_docs[maxp]));	    }	  }	}      } else {	break;      }    } while (1);#if DEBUG > 1    printf("trans cycle %d: ", foo++);    for (i=0; i<ndocs; i++) {      printf("%f ",weights[i]);    }    printf("\n");#endif        /* set the proper tvals for the unlabeled docs      * (since they will no longer be bound) */    if (svm_use_smo) {      smo_model.W = *W;      for (i=nlabeled; i<ndocs; i++) {	if ((weights[i] > cvect[i] - svm_epsilon_a) && 	    (weights[i] < svm_trans_cstar)) {	  tvals[i] = smo_evaluate_error(&smo_model, i);	}      }    }    cs_pos = MIN(cs_pos*1.5,svm_trans_cstar);    cs_neg = MIN(cs_neg*1.5,svm_trans_cstar);    fprintf(stderr,"\r\t\t\t\b\b\bc=(%f,%f)    ",cs_pos,cs_neg);        for (i=0; i<ntrans; i++) {      if (trans_yvect[i] == 1) 	trans_cvect[i] = cs_pos;      else	trans_cvect[i] = cs_neg;    }  }#ifdef DEBUG  /* debugging - sensitivity check */  oldw = *W;  *W = (double *) malloc(sizeof(double) * bow_num_words());  for (i=0; i<bow_num_words(); i++) {    (*W)[i] = 0;  }  for (i=0; i<ndocs; i++) {    for (j=0; j<docs[i]->num_entries; j++) {      (*W)[docs[i]->entry[j].wi] += yvect[i] * weights[i] * docs[i]->entry[j].weight;    }  }  for (i=0; i<bow_num_words(); i++) {    oldw[i] -= (*W)[i];    if (oldw[i] > 0 ) oldw[i] *= -1;    if (oldw[i] > 0.01) {      fprintf(stderr, "bad hyperplane (j=%d)\n",j);      fflush(stderr);      kill(getpid(),SIGSTOP);    }  }#endif  free(cvect);  free(tmpdv);#if DEBUG > 1  fprintf(stderr, "trans_yvect1 ");  for (i=0; i<ndocs;i++) {    fprintf(stderr," %d",yvect[i]);  }  fprintf(stderr,"\n");#endif  if (trans_yvect_store) {    for (i=0; i<ntrans; i++) {      trans_yvect_store[i] = trans_yvect[i];    }  }#if DEBUG > 1  fprintf(stderr, "trans_yvect2 ");  for (i=0; i<ntrans;i++) {    fprintf(stderr," %d",trans_yvect_store[i]);  }  fprintf(stderr,"\n");#endif  for (i=0; i<ntrans; i++) {    trans_yvect[i] = old_yvect[i];  }  free(old_yvect);  *up_nsv = nsv;  /* ?bug?  Need to add code to signal whether or not the weights have changed   * its hard to believe that the weights don't change at least a    * little bit - right */  return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -