Rev 6464 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** Cross validate a model. This routine is responsible for filling in* two vectors -- xrisk = cross-validated risk estimate* xstd = std of xrisk** Basic method is to use a stratified partitioning of the data (NOT random)* into n_xval subgroups. One by one, each of these groups is left out of* the partitioning by setting 'which' to 0. After partitioning, the risk* of each left out subject is determined, under each of the unique* complexity parameters.* The x-groups are set by the calling S-routine, so they can actually be* random, non-random, or whatever, as far as this routine is concerned.** n_xval: number of cross-validation subsets* cptable: head of the complexity parameter table, were results will be* stored* x_grp(n): defines the groups. Integers from 1 to n_xval* maxcat : max # categories, in any given categorical variable* errmsg : possible error message* parms : vector of input parameters, initializers for the splitting rule* savesort: saved version of rp.sorts*/#include <math.h>#include "rpart.h"#include "node.h"#include "rpartproto.h"#ifndef DEBUG# define DEBUG 0#endif#if DEBUG > 1static int debug = 0; /*if it is odd, print out every tree *//*if >= 2, print out every risk value we see */#endifvoidxval(int n_xval, CpTable cptable_head, int *x_grp,int maxcat, char **errmsg, double *parms, int *savesort){int i, j, k, ii, jj;int last;int xgroup;double *xtemp, *xpred;int *savew;double *cp;double alphasave;pNode xtree;CpTable cplist;double temp;double old_wt, total_wt;alphasave = rp.alpha;/** Allocate a set of temporary arrays*/xtemp = (double *) CALLOC(3 * rp.num_unique_cp, sizeof(double));xpred = xtemp + rp.num_unique_cp;cp = xpred + rp.num_unique_cp;savew = (int *) CALLOC(rp.n, sizeof(int));for (i = 0; i < rp.n; i++)savew[i] = rp.which[i]; /* restore at the end *//** Make the list of CPs that I will compare against*/cp[0] = 10 * cptable_head->cp; /* close enough to infinity */for (cplist = cptable_head, i = 1; i < rp.num_unique_cp;cplist = cplist->forward, i++)cp[i] = sqrt(cplist->cp * (cplist->forward)->cp);total_wt = 0;for (i = 0; i < rp.n; i++)total_wt += rp.wt[i];old_wt = total_wt;/** do the validations*/k = 0; /* -Wall */for (xgroup = 0; xgroup < n_xval; xgroup++) {/** restore rp.sorts, with the data for this run at the top* this requires one pass per variable*/for (j = 0; j < rp.nvar; j++) {k = 0;for (i = 0; i < rp.n; i++) {ii = savesort[j * rp.n + i];if (ii < 0)ii = -(1 + ii); /* missings move too */if (x_grp[ii] != xgroup + 1) {/** this obs is left in --* copy to the front half of rp.sorts*/rp.sorts[j][k] = savesort[j * rp.n + i];k++;}}}/** Fix up the y vector, and save a list of "left out" obs * in* the tail, unused end of rp.sorts[0][i];*/last = k;k = 0;temp = 0;for (i = 0; i < rp.n; i++) {rp.which[i] = 1; /* everyone starts in group 1 */if (x_grp[i] == xgroup + 1) {rp.sorts[0][last] = i;last++;} else {rp.ytemp[k] = rp.ydata[i];rp.wtemp[k] = rp.wt[i];temp += rp.wt[i];k++;}}/* at this point k = #obs in the xval group *//* rescale the cp */for (j = 0; j < rp.num_unique_cp; j++)cp[j] *= temp / old_wt;rp.alpha *= temp / old_wt;old_wt = temp;/** partition the new tree*/xtree = (pNode) CALLOC(1, nodesize);xtree->num_obs = k;(*rp_init) (k, rp.ytemp, maxcat, errmsg, parms, &temp, 2, rp.wtemp);(*rp_eval) (k, rp.ytemp, xtree->response_est, &(xtree->risk), rp.wtemp);xtree->complexity = xtree->risk;partition(1, xtree, &temp, 0, k);fix_cp(xtree, xtree->complexity);/** run the extra data down the new tree*/for (i = k; i < rp.n; i++) {j = rp.sorts[0][i];rundown(xtree, j, cp, xpred, xtemp);#if DEBUG > 1if (debug > 1) {jj = j + 1;Rprintf("\nObs %d, y=%f \n", jj, rp.ydata[j][0]);}#endif/* add it in to the risk */cplist = cptable_head;for (jj = 0; jj < rp.num_unique_cp; jj++) {cplist->xrisk += xtemp[jj] * rp.wt[j];cplist->xstd += xtemp[jj] * xtemp[jj] * rp.wt[j];#if DEBUG > 1if (debug > 1)Rprintf(" cp=%f, pred=%f, xtemp=%f\n",cp[jj] / old_wt, xpred[jj], xtemp[jj]);#endifcplist = cplist->forward;}}free_tree(xtree, 1); // Calloc-edR_CheckUserInterrupt();}for (cplist = cptable_head; cplist; cplist = cplist->forward) {cplist->xstd = sqrt(cplist->xstd -cplist->xrisk * cplist->xrisk / total_wt);}rp.alpha = alphasave;for (i = 0; i < rp.n; i++)rp.which[i] = savew[i];Free(savew);Free(xtemp);}