package com.yahoo.labs.samoa.learners.classifiers.rules.common; /* * #%L * SAMOA * %% * Copyright (C) 2013 - 2014 Yahoo! Inc. * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.io.Serializable; import com.yahoo.labs.samoa.moa.classifiers.core.conditionaltests.InstanceConditionalTest; import com.yahoo.labs.samoa.moa.classifiers.core.conditionaltests.NumericAttributeBinaryTest; import com.yahoo.labs.samoa.moa.classifiers.rules.core.attributeclassobservers.FIMTDDNumericAttributeClassLimitObserver; import com.yahoo.labs.samoa.moa.classifiers.rules.core.conditionaltests.NumericAttributeBinaryRulePredicate; /** * ActiveRule is a LearningRule that actively update its LearningNode * with incoming instances. * * @author Anh Thu Vu * */ public class ActiveRule extends LearningRule { private static final long serialVersionUID = 1L; private double[] statisticsOtherBranchSplit; private Builder builder; private RuleActiveRegressionNode learningNode; private RuleSplitNode lastUpdatedRuleSplitNode; /* * Constructor with Builder */ public ActiveRule() { super(); this.builder = null; this.learningNode = null; this.ruleNumberID = 0; } public ActiveRule(Builder builder) { super(); this.setBuilder(builder); this.learningNode = newRuleActiveLearningNode(builder); //JD - use builder ID to set ruleNumberID this.ruleNumberID=builder.id; } private RuleActiveRegressionNode newRuleActiveLearningNode(Builder builder) { return new RuleActiveRegressionNode(builder); } /* * Setters & getters */ public Builder getBuilder() { return builder; } public void setBuilder(Builder builder) { this.builder = builder; } @Override public RuleRegressionNode getLearningNode() { return this.learningNode; } @Override public void setLearningNode(RuleRegressionNode learningNode) { this.learningNode = (RuleActiveRegressionNode) learningNode; } public double[] statisticsOtherBranchSplit() { return this.statisticsOtherBranchSplit; } public RuleSplitNode getLastUpdatedRuleSplitNode() { return this.lastUpdatedRuleSplitNode; } /* * Builder */ public static class Builder implements Serializable { private static final long serialVersionUID = 1712887264918475622L; protected boolean changeDetection; protected boolean usePerceptron; protected double threshold; protected double alpha; protected int predictionFunction; protected boolean constantLearningRatioDecay; protected double learningRatio; protected double[] statistics; protected FIMTDDNumericAttributeClassLimitObserver numericObserver; protected double lastTargetMean; public int id; public Builder() { } public Builder changeDetection(boolean changeDetection) { this.changeDetection = changeDetection; return this; } public Builder threshold(double threshold) { this.threshold = threshold; return this; } public Builder alpha(double alpha) { this.alpha = alpha; return this; } public Builder predictionFunction(int predictionFunction) { this.predictionFunction = predictionFunction; return this; } public Builder statistics(double[] statistics) { this.statistics = statistics; return this; } public Builder constantLearningRatioDecay(boolean constantLearningRatioDecay) { this.constantLearningRatioDecay = constantLearningRatioDecay; return this; } public Builder learningRatio(double learningRatio) { this.learningRatio = learningRatio; return this; } public Builder numericObserver(FIMTDDNumericAttributeClassLimitObserver numericObserver) { this.numericObserver = numericObserver; return this; } public Builder id(int id) { this.id = id; return this; } public ActiveRule build() { return new ActiveRule(this); } } /** * Try to Expand method. * @param splitConfidence * @param tieThreshold * @return */ public boolean tryToExpand(double splitConfidence, double tieThreshold) { boolean shouldSplit= this.learningNode.tryToExpand(splitConfidence, tieThreshold); return shouldSplit; } //JD: Only call after tryToExpand returning true public void split() { //this.statisticsOtherBranchSplit = this.learningNode.getStatisticsOtherBranchSplit(); //create a split node, int splitIndex = this.learningNode.getSplitIndex(); InstanceConditionalTest st=this.learningNode.getBestSuggestion().splitTest; if(st instanceof NumericAttributeBinaryTest) { NumericAttributeBinaryTest splitTest = (NumericAttributeBinaryTest) st; NumericAttributeBinaryRulePredicate predicate = new NumericAttributeBinaryRulePredicate( splitTest.getAttsTestDependsOn()[0], splitTest.getSplitValue(), splitIndex + 1); lastUpdatedRuleSplitNode = new RuleSplitNode(predicate, this.learningNode.getStatisticsBranchSplit() ); if (this.nodeListAdd(lastUpdatedRuleSplitNode)) { // create a new learning node RuleActiveRegressionNode newLearningNode = newRuleActiveLearningNode(this.getBuilder().statistics(this.learningNode.getStatisticsNewRuleActiveLearningNode())); newLearningNode.initialize(this.learningNode); this.learningNode = newLearningNode; } } else throw new UnsupportedOperationException("AMRules (currently) only supports numerical attributes."); } // protected void debug(String string, int level) { // if (this.amRules.VerbosityOption.getValue()>=level) { // System.out.println(string); // } //} /** * MOA GUI output */ @Override public void getDescription(StringBuilder sb, int indent) { } }