/** * Compute Variable Importance, based on GEDEON: DATA MINING OF INPUTS: ANALYSING MAGNITUDE AND * FUNCTIONAL MEASURES * * @return variable importances for input features */ public float[] computeVariableImportances() { float[] vi = new float[units[0]]; Arrays.fill(vi, 0f); float[][] Qik = new float[units[0]][units[2]]; // importance of input i on output k float[] sum_wj = new float[units[1]]; // sum of incoming weights into first hidden layer float[] sum_wk = new float[units[2]]; // sum of incoming weights into output layer (or second hidden layer) for (float[] Qi : Qik) Arrays.fill(Qi, 0f); Arrays.fill(sum_wj, 0f); Arrays.fill(sum_wk, 0f); // compute sum of absolute incoming weights for (int j = 0; j < units[1]; j++) { for (int i = 0; i < units[0]; i++) { float wij = get_weights(0).get(j, i); sum_wj[j] += Math.abs(wij); } } for (int k = 0; k < units[2]; k++) { for (int j = 0; j < units[1]; j++) { float wjk = get_weights(1).get(k, j); sum_wk[k] += Math.abs(wjk); } } // compute importance of input i on output k as product of connecting weights going through j for (int i = 0; i < units[0]; i++) { for (int k = 0; k < units[2]; k++) { for (int j = 0; j < units[1]; j++) { float wij = get_weights(0).get(j, i); float wjk = get_weights(1).get(k, j); // Qik[i][k] += Math.abs(wij)/sum_wj[j] * wjk; //Wong,Gedeon,Taggart '95 Qik[i][k] += Math.abs(wij) / sum_wj[j] * Math.abs(wjk) / sum_wk[k]; // Gedeon '97 } } } // normalize Qik over all outputs k for (int k = 0; k < units[2]; k++) { float sumQk = 0; for (int i = 0; i < units[0]; i++) sumQk += Qik[i][k]; for (int i = 0; i < units[0]; i++) Qik[i][k] /= sumQk; } // importance for feature i is the sum over k of i->k importances for (int i = 0; i < units[0]; i++) vi[i] = ArrayUtils.sum(Qik[i]); // normalize importances such that max(vi) = 1 ArrayUtils.div(vi, ArrayUtils.maxValue(vi)); // zero out missing categorical variables if they were never seen if (_saw_missing_cats != null) { for (int i = 0; i < _saw_missing_cats.length; ++i) { assert (data_info._catMissing[i] == 1); // have a missing bucket for each categorical if (!_saw_missing_cats[i]) vi[data_info._catOffsets[i + 1] - 1] = 0; } } return vi; }
/** Unique identifier for this model's state, based on raw numbers */ protected long checksum_impl() { long cs = parameters._seed; cs ^= size() * get_processed_total(); cs ^= (long) (2234.3424 * ArrayUtils.sum(mean_bias)); cs *= (long) (9234.1343 * ArrayUtils.sum(rms_bias)); cs ^= (long) (9723.9734 * ArrayUtils.sum(mean_weight)); cs *= (long) (9234.1783 * ArrayUtils.sum(rms_weight)); cs ^= (long) (4273.2344 * (Math.E + ArrayUtils.sum(mean_rate))); cs *= (long) (3378.1999 * (Math.PI + ArrayUtils.sum(rms_rate))); return cs; }
long cnt() { return water.util.ArrayUtils.sum(_cnts); }
@Ignore @Test public void matrixVecTest() { int rows = 2048; int cols = 8192; int loops = 5; int warmup_loops = 5; long seed = 0x533D; float nnz_ratio_vec = 0.01f; // fraction of non-zeroes for vector float nnz_ratio_mat = 0.1f; // fraction of non-zeroes for matrix float[] a = new float[rows * cols]; float[] x = new float[cols]; float[] y = new float[rows]; float[] res = new float[rows]; byte[] bits = new byte[rows]; for (int row = 0; row < rows; ++row) { y[row] = 0; res[row] = 0; bits[row] = (byte) ("abcdefghijklmnopqrstuvwxyz".toCharArray()[row % 26]); } Random rng = new Random(seed); for (int col = 0; col < cols; ++col) if (rng.nextFloat() < nnz_ratio_vec) x[col] = ((float) col) / cols; for (int row = 0; row < rows; ++row) { int off = row * cols; for (int col = 0; col < cols; ++col) { if (rng.nextFloat() < nnz_ratio_mat) a[off + col] = ((float) (row + col)) / cols; } } Storage.DenseRowMatrix dra = new Storage.DenseRowMatrix(a, rows, cols); Storage.DenseColMatrix dca = new Storage.DenseColMatrix(dra, rows, cols); Storage.SparseRowMatrix sra = new Storage.SparseRowMatrix(dra, rows, cols); Storage.SparseColMatrix sca = new Storage.SparseColMatrix(dca, rows, cols); Storage.DenseVector dx = new Storage.DenseVector(x); Storage.DenseVector dy = new Storage.DenseVector(y); Storage.DenseVector dres = new Storage.DenseVector(res); Storage.SparseVector sx = new Storage.SparseVector(x); /** warmup */ System.out.println("warming up."); float sum = 0; for (int l = 0; l < warmup_loops; ++l) { gemv_naive(res, a, x, y, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv_naive(dres, dra, dx, dy, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv_row_optimized(res, a, x, y, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv(dres, dca, dx, dy, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv(dres, dra, sx, dy, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv(dres, dca, sx, dy, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv(dres, sra, sx, dy, bits); sum += res[rows / 2]; } for (int l = 0; l < warmup_loops; ++l) { gemv(dres, sca, sx, dy, bits); sum += res[rows / 2]; } /** naive version */ System.out.println("\nstarting naive."); sum = 0; long start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv_naive(res, a, x, y, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "naive time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting dense row * dense."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv_naive(dres, dra, dx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "dense row * dense time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting optimized dense row * dense."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv_row_optimized(res, a, x, y, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "optimized dense row * dense time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting dense col * dense."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv(dres, dca, dx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "dense col * dense time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting dense row * sparse."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv(dres, dra, sx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "dense row * sparse time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting dense col * sparse."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv(dres, dca, sx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "dense col * sparse time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting sparse row * sparse."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv(dres, sra, sx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "sparse row * sparse time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); System.out.println("\nstarting sparse col * sparse."); sum = 0; start = System.currentTimeMillis(); for (int l = 0; l < loops; ++l) { gemv(dres, sca, sx, dy, bits); sum += res[rows / 2]; // do something useful } System.out.println("result: " + sum + " and " + ArrayUtils.sum(res)); System.out.println( "sparse col * sparse time: " + PrettyPrint.msecs(System.currentTimeMillis() - start, true)); }