Rev 6464 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** The four routines for anova splitting*/#include "rpart.h"#include "rpartproto.h"static double *mean, *sums;static double *wts;static int *countn;static int *tsplit;intanovainit(int n, double *y[], int maxcat, char **error,double *parm, int *size, int who, double *wt){if (who == 1 && maxcat > 0) {graycode_init0(maxcat);countn = (int *) ALLOC(2 * maxcat, sizeof(int));tsplit = countn + maxcat;mean = (double *) ALLOC(3 * maxcat, sizeof(double));wts = mean + maxcat;sums = wts + maxcat;}*size = 1;return 0;}/** The anova evaluation function. Return the mean and the ss.*/voidanovass(int n, double *y[], double *value, double *risk, double *wt){int i;double temp = 0., twt = 0.; /* sum of the weights */double mean, ss;for (i = 0; i < n; i++) {temp += *y[i] * wt[i];twt += wt[i];}mean = temp / twt;ss = 0;for (i = 0; i < n; i++) {temp = *y[i] - mean;ss += temp * temp * wt[i];}*value = mean;*risk = ss;}/** The anova splitting function. Find that split point in x such that* the sum of squares of y within the two groups is decreased as much* as possible. It is not necessary to actually calculate the SS, the* improvement involves only means in the two groups.*/voidanova(int n, double *y[], double *x, int nclass,int edge, double *improve, double *split, int *csplit,double myrisk, double *wt){int i, j;double temp;double left_sum, right_sum;double left_wt, right_wt;int left_n, right_n;double grandmean, best;int direction = LEFT;int where = 0;/** The improvement of a node is SS - (SS_L + SS_R), where* SS = sum of squares in a node = \sum w_i (x_i - \bar x)^2, where* of course \bar x is a weighted mean \sum w_i x_i / \sum w_i* Using the identity* \sum w_i(x_ - \bar x)^2 = \sum w_i (x_i-c)^2 - (\sum w_i)(c-\bar x)^2* the improvement = w_l*(left mean - grand mean)^2* +w_r*(right mean- grand mean)^2* where w_l is the sum of weights in the left node, w_r similarly.*/right_wt = 0;right_n = n;right_sum = 0;for (i = 0; i < n; i++) {right_sum += *y[i] * wt[i];right_wt += wt[i];}grandmean = right_sum / right_wt;if (nclass == 0) { /* continuous predictor */left_sum = 0; /* No data in left branch, to start */left_wt = 0;left_n = 0;right_sum = 0; /* after subracting grand mean, it's zero */best = 0;for (i = 0; right_n > edge; i++) {left_wt += wt[i];right_wt -= wt[i];left_n++;right_n--;temp = (*y[i] - grandmean) * wt[i];left_sum += temp;right_sum -= temp;if (x[i + 1] != x[i] && left_n >= edge) {temp = left_sum * left_sum / left_wt +right_sum * right_sum / right_wt;if (temp > best) {best = temp;where = i;if (left_sum < right_sum)direction = LEFT;elsedirection = RIGHT;}}}*improve = best / myrisk;if (best > 0) { /* found something */csplit[0] = direction;*split = (x[where] + x[where + 1]) / 2;}}/** Categorical predictor*/else {for (i = 0; i < nclass; i++) {sums[i] = 0;countn[i] = 0;wts[i] = 0;}/* rank the classes by their mean y value */for (i = 0; i < n; i++) {j = (int) x[i] - 1;countn[j]++;wts[j] += wt[i];sums[j] += (*y[i] - grandmean) * wt[i];}for (i = 0; i < nclass; i++) {if (countn[i] > 0) {tsplit[i] = RIGHT;mean[i] = sums[i] / wts[i];} elsetsplit[i] = 0;}graycode_init2(nclass, countn, mean);/** Now find the split that we want*/left_wt = 0;left_sum = 0;right_sum = 0;left_n = 0;best = 0;where = 0;while ((j = graycode()) < nclass) {tsplit[j] = LEFT;left_n += countn[j];right_n -= countn[j];left_wt += wts[j];right_wt -= wts[j];left_sum += sums[j];right_sum -= sums[j];if (left_n >= edge && right_n >= edge) {temp = left_sum * left_sum / left_wt +right_sum * right_sum / right_wt;if (temp > best) {best = temp;if ((left_sum / left_wt) > (right_sum / right_wt))for (i = 0; i < nclass; i++) csplit[i] = -tsplit[i];elsefor (i = 0; i < nclass; i++) csplit[i] = tsplit[i];}}}*improve = best / myrisk; /* % improvement */}}