@Override public double[] probs(double[] feature) { double[] probs = new double[classCount]; for (int i = 0; i < boosters.length; i++) { if (roundIndicator[i]) { for (int j = 0; j < boosters[i].length; j++) probs[j] += LEARNING_RATE * boosters[i][j].boostPredict(feature); } } IntStream.range(0, classCount).forEach(i -> probs[i] = Math.exp(probs[i])); ArraySumUtil.normalize(probs); return probs; }
@Override public void train() { for (int i = 0; i < boosters.length; i++) { long t1 = System.currentTimeMillis(); final int ROUND = i; service = Executors.newFixedThreadPool(MAX_THREADS); countDownLatch = new CountDownLatch(classCount); IntStream.range(0, classCount) .forEach( j -> service.submit( () -> { long tic = System.currentTimeMillis(); try { boosters[ROUND][j].boostInitialize(roundData[j], roundIndices); boosters[ROUND][j].boost(); } catch (Throwable t) { log.error(t.getMessage(), t); } long toc = System.currentTimeMillis(); log.debug( "round {}, task: {}/{} finished, elapsed {} ms", ROUND, j, classCount, toc - tic); countDownLatch.countDown(); })); try { TimeUnit.SECONDS.sleep(10); countDownLatch.await(); } catch (Throwable t) { log.error(t.getMessage(), t); } service.shutdown(); roundIndicator[ROUND] = true; long t2 = System.currentTimeMillis(); float[] probs = new float[classCount]; for (int j = 0; j < trainData.getInstanceLength(); j++) { double[] x = trainData.getInstance(j); double y = trainData.getLabel(j); float[] ys = new float[classCount]; ys[(int) y] = 1; for (int k = 0; k < classCount; k++) { scoreCache[j][k] += LEARNING_RATE * boosters[ROUND][k].boostPredict(x); probs[k] = (float) Math.exp(scoreCache[j][k]); } ArraySumUtil.normalize(probs); roundKL[ROUND] += (float) ArrayUtil.KLDivergence(ys, probs); for (int k = 0; k < classCount; k++) tempLabels[k][j] = ys[k] - probs[k]; } roundKL[ROUND] /= trainData.getInstanceLength(); for (int j = 0; j < classCount; j++) roundData[j] = new DataSet(trainData.getFeatureMatrix(), new Label(tempLabels[j], null)); indices.shuffle(new Random()); for (int j = 0; j < roundIndices.length; j++) roundIndices[j] = indices.get(j); long t3 = System.currentTimeMillis(); if (NEED_REPORT) { statisticReport(ROUND); } long t4 = System.currentTimeMillis(); log.info("round {}, KL {}", ROUND, roundKL[ROUND]); log.info( "boost {} |update gradient {} |report {}| total {}", t2 - t1, t3 - t2, t4 - t3, t4 - t1); } log.info("GradientBoostClassification training finished ..."); if (NEED_REPORT) { printRoundReport(); } }