@Override public String toJavaString() { double[] ary = expand(); if (ary == null || ary.length == 0) return "\"null\""; SB sb = new SB().p('{'); for (int i = 0; i < ary.length - 1; ++i) sb.p(ary[i]).p(','); return sb.p('}').toString(); }
@Override protected void toJavaUnifyPreds(SB bodySb) { if (isClassifier()) { bodySb.i().p("float sum = 0;").nl(); bodySb.i().p("for(int i=1; i<preds.length; i++) sum += preds[i];").nl(); bodySb.i().p("if (sum>0) for(int i=1; i<preds.length; i++) preds[i] /= sum;").nl(); } else bodySb.i().p("preds[1] = preds[1]/NTREES;").nl(); }
@Override protected SB toJavaInit(SB sb, SB fileContextSB) { sb = super.toJavaInit(sb, fileContextSB); sb.ip("public boolean isSupervised() { return " + isSupervised() + "; }").nl(); sb.ip("public int nfeatures() { return " + _output.nfeatures() + "; }").nl(); sb.ip("public int nclasses() { return " + _parms._k + "; }").nl(); if (_output._nnums > 0) { JCodeGen.toStaticVar( sb, "NORMMUL", _output._normMul, "Standardization/Normalization scaling factor for numerical variables."); JCodeGen.toStaticVar( sb, "NORMSUB", _output._normSub, "Standardization/Normalization offset for numerical variables."); } JCodeGen.toStaticVar(sb, "CATOFFS", _output._catOffsets, "Categorical column offsets."); JCodeGen.toStaticVar(sb, "PERMUTE", _output._permutation, "Permutation index vector."); JCodeGen.toStaticVar(sb, "EIGVECS", _output._eigenvectors_raw, "Eigenvector matrix."); return sb; }
@Override public String str() { SB sb = new SB().p('['); for (int i = 0; i < _bases.length; i++) { sb.p(_bases[i]); if (_cnts[i] != 1) { sb.p(':').p(_bases[i] + _cnts[i] * _strides[i]); if (_strides[i] != 1 || ((long) _bases[i]) != _bases[i]) sb.p(':').p(_strides[i]); } if (i < _bases.length - 1) sb.p(','); } return sb.p(']').toString(); }
@Override protected void toJavaUnifyPreds(SB bodyCtxSB) { if (isClassifier()) { bodyCtxSB .i() .p( "// Compute Probabilities for classifier (scale via http://www.hongliangjie.com/2011/01/07/logsum/)") .nl(); bodyCtxSB.i().p("float dsum = 0, maxval = Float.NEGATIVE_INFINITY;").nl(); if (nclasses() == 2) { bodyCtxSB.i().p("preds[2] = -preds[1];").nl(); } bodyCtxSB .i() .p("for(int i=1; i<preds.length; i++) maxval = Math.max(maxval, preds[i]);") .nl(); bodyCtxSB .i() .p( "for(int i=1; i<preds.length; i++) dsum += (preds[i]=(float) Math.exp(preds[i] - maxval));") .nl(); bodyCtxSB.i().p("for(int i=1; i<preds.length; i++) preds[i] = preds[i] / dsum;").nl(); } }
@Override public String str() { SB sb = new SB().p('('); for (AST ast : _asts) sb.p(ast.toString()).p(' '); return sb.p(')').toString(); }
@Override protected void toJavaPredictBody(final SB bodySb, final SB classCtxSb, final SB fileCtxSb) { SB model = new SB(); bodySb.i().p("java.util.Arrays.fill(preds,0);").nl(); final int cats = _output._ncats; final int nums = _output._nnums; bodySb.i().p("final int nstart = CATOFFS[CATOFFS.length-1];").nl(); bodySb.i().p("for(int i = 0; i < ").p(_parms._k).p("; i++) {").nl(); // Categorical columns bodySb.i(1).p("for(int j = 0; j < ").p(cats).p("; j++) {").nl(); bodySb.i(2).p("double d = data[PERMUTE[j]];").nl(); bodySb.i(2).p("if(Double.isNaN(d)) continue;").nl(); bodySb.i(2).p("int last = CATOFFS[j+1]-CATOFFS[j]-1;").nl(); bodySb.i(2).p("int c = (int)d").p(_parms._use_all_factor_levels ? ";" : "-1;").nl(); bodySb.i(2).p("if(c < 0 || c > last) continue;").nl(); bodySb.i(2).p("preds[i] += EIGVECS[CATOFFS[j]+c][i];").nl(); bodySb.i(1).p("}").nl(); // Numeric columns bodySb.i(1).p("for(int j = 0; j < ").p(nums).p("; j++) {").nl(); bodySb .i(2) .p( "preds[i] += (data[PERMUTE[j" + (cats > 0 ? "+" + cats : "") + "]]-NORMSUB[j])*NORMMUL[j]*EIGVECS[j" + (cats > 0 ? "+ nstart" : "") + "][i];") .nl(); bodySb.i(1).p("}").nl(); bodySb.i().p("}").nl(); fileCtxSb.p(model); }
// Note: POJO scoring code doesn't support per-row offsets (the scoring API would need to be // changed to pass in offsets) @Override protected void toJavaUnifyPreds(SB body, SB file) { // Preds are filled in from the trees, but need to be adjusted according to // the loss function. if (_parms._distribution == Distributions.Family.bernoulli) { body.ip("preds[2] = preds[1] + ").p(_output._init_f).p(";").nl(); body.ip("preds[2] = " + _parms._distribution.linkInvString("preds[2]") + ";").nl(); body.ip("preds[1] = 1.0-preds[2];").nl(); if (_parms._balance_classes) body.ip( "hex.genmodel.GenModel.correctProbabilities(preds, PRIOR_CLASS_DISTRIB, MODEL_CLASS_DISTRIB);") .nl(); body.ip( "preds[0] = hex.genmodel.GenModel.getPrediction(preds, data, " + defaultThreshold() + ");") .nl(); return; } if (_output.nclasses() == 1) { // Regression body.ip("preds[0] += ").p(_output._init_f).p(";").nl(); body.ip("preds[0] = " + _parms._distribution.linkInvString("preds[0]") + ";").nl(); return; } if (_output.nclasses() == 2) { // Kept the initial prediction for binomial body.ip("preds[1] += ").p(_output._init_f).p(";").nl(); body.ip("preds[2] = - preds[1];").nl(); } body.ip("hex.genmodel.GenModel.GBM_rescale(preds);").nl(); if (_parms._balance_classes) body.ip( "hex.genmodel.GenModel.correctProbabilities(preds, PRIOR_CLASS_DISTRIB, MODEL_CLASS_DISTRIB);") .nl(); body.ip( "preds[0] = hex.genmodel.GenModel.getPrediction(preds, data, " + defaultThreshold() + ");") .nl(); }