http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWIN.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWIN.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWIN.java index b05a302..efacc93 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWIN.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWIN.java @@ -23,582 +23,573 @@ package com.yahoo.labs.samoa.moa.classifiers.core.driftdetection; import com.yahoo.labs.samoa.moa.AbstractMOAObject; /** - * ADaptive sliding WINdow method. This method is a change detector and estimator. - * It keeps a variable-length window of recently seen - * items, with the property that the window has the maximal length statistically - * consistent with the hypothesis "there has been no change in the average value - * inside the window". - * - * + * ADaptive sliding WINdow method. This method is a change detector and + * estimator. It keeps a variable-length window of recently seen items, with the + * property that the window has the maximal length statistically consistent with + * the hypothesis "there has been no change in the average value inside the + * window". + * + * * @author Albert Bifet (abifet at cs dot waikato dot ac dot nz) * @version $Revision: 7 $ */ public class ADWIN extends AbstractMOAObject { - private class List extends AbstractMOAObject { + private class List extends AbstractMOAObject { - protected int count; + protected int count; - protected ListItem head; + protected ListItem head; - protected ListItem tail; - - public List() { -// post: initializes the list to be empty. - clear(); - addToHead(); - } + protected ListItem tail; - /* Interface Store Methods */ - public int size() { - // post: returns the number of elements in the list. - return this.count; - } + public List() { + // post: initializes the list to be empty. + clear(); + addToHead(); + } - public ListItem head() { - // post: returns the number of elements in the list. - return this.head; - } + /* Interface Store Methods */ + public int size() { + // post: returns the number of elements in the list. + return this.count; + } - public ListItem tail() { - // post: returns the number of elements in the list. - return this.tail; - } + public ListItem head() { + // post: returns the number of elements in the list. + return this.head; + } - public boolean isEmpty() { - // post: returns the true iff store is empty. - return (this.size() == 0); - } + public ListItem tail() { + // post: returns the number of elements in the list. + return this.tail; + } - public void clear() { - // post: clears the list so that it contains no elements. - this.head = null; - this.tail = null; - this.count = 0; - } + public boolean isEmpty() { + // post: returns the true iff store is empty. + return (this.size() == 0); + } - /* Interface List Methods */ - public void addToHead() { - // pre: anObject is non-null - // post: the object is added to the beginning of the list - this.head = new ListItem(this.head, null); - if (this.tail == null) { - this.tail = this.head; - } - this.count++; - } + public void clear() { + // post: clears the list so that it contains no elements. + this.head = null; + this.tail = null; + this.count = 0; + } - public void removeFromHead() { - // pre: list is not empty - // post: removes and returns first object from the list -// ListItem temp; -// temp = this.head; - this.head = this.head.next(); - if (this.head != null) { - this.head.setPrevious(null); - } else { - this.tail = null; - } - this.count--; - } + /* Interface List Methods */ + public void addToHead() { + // pre: anObject is non-null + // post: the object is added to the beginning of the list + this.head = new ListItem(this.head, null); + if (this.tail == null) { + this.tail = this.head; + } + this.count++; + } - public void addToTail() { -// pre: anObject is non-null -// post: the object is added at the end of the list - this.tail = new ListItem(null, this.tail); - if (this.head == null) { - this.head = this.tail; - } - this.count++; - } + public void removeFromHead() { + // pre: list is not empty + // post: removes and returns first object from the list + // ListItem temp; + // temp = this.head; + this.head = this.head.next(); + if (this.head != null) { + this.head.setPrevious(null); + } else { + this.tail = null; + } + this.count--; + } - public void removeFromTail() { -// pre: list is not empty -// post: the last object in the list is removed and returned -// ListItem temp; -// temp = this.tail; - this.tail = this.tail.previous(); - if (this.tail == null) { - this.head = null; - } else { - this.tail.setNext(null); - } - this.count--; - //temp=null; - } + public void addToTail() { + // pre: anObject is non-null + // post: the object is added at the end of the list + this.tail = new ListItem(null, this.tail); + if (this.head == null) { + this.head = this.tail; + } + this.count++; + } - @Override - public void getDescription(StringBuilder sb, int indent) { - } + public void removeFromTail() { + // pre: list is not empty + // post: the last object in the list is removed and returned + // ListItem temp; + // temp = this.tail; + this.tail = this.tail.previous(); + if (this.tail == null) { + this.head = null; + } else { + this.tail.setNext(null); + } + this.count--; + // temp=null; } - private class ListItem extends AbstractMOAObject { - protected ListItem next; + @Override + public void getDescription(StringBuilder sb, int indent) { + } + } - protected ListItem previous; + private class ListItem extends AbstractMOAObject { + protected ListItem next; - protected int bucketSizeRow = 0; + protected ListItem previous; - protected int MAXBUCKETS = ADWIN.MAXBUCKETS; + protected int bucketSizeRow = 0; - protected double bucketTotal[] = new double[MAXBUCKETS + 1]; + protected int MAXBUCKETS = ADWIN.MAXBUCKETS; - protected double bucketVariance[] = new double[MAXBUCKETS + 1]; + protected double bucketTotal[] = new double[MAXBUCKETS + 1]; - public ListItem() { -// post: initializes the node to be a tail node -// containing the given value. - this(null, null); - } + protected double bucketVariance[] = new double[MAXBUCKETS + 1]; - public void clear() { - bucketSizeRow = 0; - for (int k = 0; k <= MAXBUCKETS; k++) { - clearBucket(k); - } - } + public ListItem() { + // post: initializes the node to be a tail node + // containing the given value. + this(null, null); + } - private void clearBucket(int k) { - setTotal(0, k); - setVariance(0, k); - } + public void clear() { + bucketSizeRow = 0; + for (int k = 0; k <= MAXBUCKETS; k++) { + clearBucket(k); + } + } - public ListItem(ListItem nextNode, ListItem previousNode) { -// post: initializes the node to contain the given -// object and link to the given next node. - //this.data = element; - this.next = nextNode; - this.previous = previousNode; - if (nextNode != null) { - nextNode.previous = this; - } - if (previousNode != null) { - previousNode.next = this; - } - clear(); - } + private void clearBucket(int k) { + setTotal(0, k); + setVariance(0, k); + } - public void insertBucket(double Value, double Variance) { -// insert a Bucket at the end - int k = bucketSizeRow; - bucketSizeRow++; - //Insert new bucket - setTotal(Value, k); - setVariance(Variance, k); - } + public ListItem(ListItem nextNode, ListItem previousNode) { + // post: initializes the node to contain the given + // object and link to the given next node. + // this.data = element; + this.next = nextNode; + this.previous = previousNode; + if (nextNode != null) { + nextNode.previous = this; + } + if (previousNode != null) { + previousNode.next = this; + } + clear(); + } - public void RemoveBucket() { -// Removes the first Buvket - compressBucketsRow(1); - } + public void insertBucket(double Value, double Variance) { + // insert a Bucket at the end + int k = bucketSizeRow; + bucketSizeRow++; + // Insert new bucket + setTotal(Value, k); + setVariance(Variance, k); + } - public void compressBucketsRow(int NumberItemsDeleted) { - //Delete first elements - for (int k = NumberItemsDeleted; k <= MAXBUCKETS; k++) { - bucketTotal[k - NumberItemsDeleted] = bucketTotal[k]; - bucketVariance[k - NumberItemsDeleted] = bucketVariance[k]; - } - for (int k = 1; k <= NumberItemsDeleted; k++) { - clearBucket(MAXBUCKETS - k + 1); - } - bucketSizeRow -= NumberItemsDeleted; - //BucketNumber-=NumberItemsDeleted; - } + public void RemoveBucket() { + // Removes the first Buvket + compressBucketsRow(1); + } - public ListItem previous() { -// post: returns the previous node. - return this.previous; - } + public void compressBucketsRow(int NumberItemsDeleted) { + // Delete first elements + for (int k = NumberItemsDeleted; k <= MAXBUCKETS; k++) { + bucketTotal[k - NumberItemsDeleted] = bucketTotal[k]; + bucketVariance[k - NumberItemsDeleted] = bucketVariance[k]; + } + for (int k = 1; k <= NumberItemsDeleted; k++) { + clearBucket(MAXBUCKETS - k + 1); + } + bucketSizeRow -= NumberItemsDeleted; + // BucketNumber-=NumberItemsDeleted; + } - public void setPrevious(ListItem previous) { -// post: sets the previous node to be the given node - this.previous = previous; - } + public ListItem previous() { + // post: returns the previous node. + return this.previous; + } - public ListItem next() { -// post: returns the next node. - return this.next; - } + public void setPrevious(ListItem previous) { + // post: sets the previous node to be the given node + this.previous = previous; + } - public void setNext(ListItem next) { -// post: sets the next node to be the given node - this.next = next; - } + public ListItem next() { + // post: returns the next node. + return this.next; + } - public double Total(int k) { -// post: returns the element in this node - return bucketTotal[k]; - } + public void setNext(ListItem next) { + // post: sets the next node to be the given node + this.next = next; + } - public double Variance(int k) { -// post: returns the element in this node - return bucketVariance[k]; - } + public double Total(int k) { + // post: returns the element in this node + return bucketTotal[k]; + } - public void setTotal(double value, int k) { -// post: sets the element in this node to the given -// object. - bucketTotal[k] = value; - } + public double Variance(int k) { + // post: returns the element in this node + return bucketVariance[k]; + } - public void setVariance(double value, int k) { -// post: sets the element in this node to the given -// object. - bucketVariance[k] = value; - } - /* - public ListItem(Object element, - ListItem nextNode){ - // post: initializes the node to contain the given - // object and link to the given next node. - this.data = element; - this.next = nextNode; - } - public ListItem(Object element) { - // post: initializes the node to be a tail node - // containing the given value. - this(element, null); - } + public void setTotal(double value, int k) { + // post: sets the element in this node to the given + // object. + bucketTotal[k] = value; + } + public void setVariance(double value, int k) { + // post: sets the element in this node to the given + // object. + bucketVariance[k] = value; + } - public Object value() { - // post: returns the element in this node - return this.data; - } - public void setValue(Object anObject) { - // post: sets the element in this node to the given - // object. - this.data = anObject; - } - */ + /* + * public ListItem(Object element, ListItem nextNode){ // post: initializes + * the node to contain the given // object and link to the given next node. + * this.data = element; this.next = nextNode; } public ListItem(Object + * element) { // post: initializes the node to be a tail node // containing + * the given value. this(element, null); } + * + * + * public Object value() { // post: returns the element in this node return + * this.data; } public void setValue(Object anObject) { // post: sets the + * element in this node to the given // object. this.data = anObject; } + */ - @Override - public void getDescription(StringBuilder sb, int indent) { - } + @Override + public void getDescription(StringBuilder sb, int indent) { } + } - public static final double DELTA = .002; //.1; + public static final double DELTA = .002; // .1; - private static final int mintMinimLongitudWindow = 10; //10 + private static final int mintMinimLongitudWindow = 10; // 10 - private double mdbldelta = .002; //.1; + private double mdbldelta = .002; // .1; - private int mintTime = 0; + private int mintTime = 0; - private int mintClock = 32; + private int mintClock = 32; - private double mdblWidth = 0; // Mean of Width = mdblWidth/Number of items - //BUCKET + private double mdblWidth = 0; // Mean of Width = mdblWidth/Number of items + // BUCKET - public static final int MAXBUCKETS = 5; + public static final int MAXBUCKETS = 5; - private int lastBucketRow = 0; + private int lastBucketRow = 0; - private double TOTAL = 0; + private double TOTAL = 0; - private double VARIANCE = 0; + private double VARIANCE = 0; - private int WIDTH = 0; + private int WIDTH = 0; - private int BucketNumber = 0; + private int BucketNumber = 0; - private int Detect = 0; + private int Detect = 0; - private int numberDetections = 0; + private int numberDetections = 0; - private int DetectTwice = 0; + private int DetectTwice = 0; - private boolean blnBucketDeleted = false; + private boolean blnBucketDeleted = false; - private int BucketNumberMAX = 0; + private int BucketNumberMAX = 0; - private int mintMinWinLength = 5; + private int mintMinWinLength = 5; - private List listRowBuckets; + private List listRowBuckets; - public boolean getChange() { - return blnBucketDeleted; - } + public boolean getChange() { + return blnBucketDeleted; + } - public void resetChange() { - blnBucketDeleted = false; - } - - public int getBucketsUsed() { - return BucketNumberMAX; - } + public void resetChange() { + blnBucketDeleted = false; + } - public int getWidth() { - return WIDTH; - } + public int getBucketsUsed() { + return BucketNumberMAX; + } - public void setClock(int intClock) { - mintClock = intClock; - } + public int getWidth() { + return WIDTH; + } - public int getClock() { - return mintClock; - } + public void setClock(int intClock) { + mintClock = intClock; + } - public boolean getWarning() { - return false; - } + public int getClock() { + return mintClock; + } - public boolean getDetect() { - return (Detect == mintTime); - } + public boolean getWarning() { + return false; + } - public int getNumberDetections() { - return numberDetections; - } + public boolean getDetect() { + return (Detect == mintTime); + } - public double getTotal() { - return TOTAL; - } + public int getNumberDetections() { + return numberDetections; + } - public double getEstimation() { - return TOTAL / WIDTH; - } + public double getTotal() { + return TOTAL; + } - public double getVariance() { - return VARIANCE / WIDTH; - } + public double getEstimation() { + return TOTAL / WIDTH; + } - public double getWidthT() { - return mdblWidth; - } + public double getVariance() { + return VARIANCE / WIDTH; + } - private void initBuckets() { - //Init buckets - listRowBuckets = new List(); - lastBucketRow = 0; - TOTAL = 0; - VARIANCE = 0; - WIDTH = 0; - BucketNumber = 0; - } + public double getWidthT() { + return mdblWidth; + } - private void insertElement(double Value) { - WIDTH++; - insertElementBucket(0, Value, listRowBuckets.head()); - double incVariance = 0; - if (WIDTH > 1) { - incVariance = (WIDTH - 1) * (Value - TOTAL / (WIDTH - 1)) * (Value - TOTAL / (WIDTH - 1)) / WIDTH; - } - VARIANCE += incVariance; - TOTAL += Value; - compressBuckets(); - } + private void initBuckets() { + // Init buckets + listRowBuckets = new List(); + lastBucketRow = 0; + TOTAL = 0; + VARIANCE = 0; + WIDTH = 0; + BucketNumber = 0; + } - private void insertElementBucket(double Variance, double Value, ListItem Node) { - //Insert new bucket - Node.insertBucket(Value, Variance); - BucketNumber++; - if (BucketNumber > BucketNumberMAX) { - BucketNumberMAX = BucketNumber; - } + private void insertElement(double Value) { + WIDTH++; + insertElementBucket(0, Value, listRowBuckets.head()); + double incVariance = 0; + if (WIDTH > 1) { + incVariance = (WIDTH - 1) * (Value - TOTAL / (WIDTH - 1)) * (Value - TOTAL / (WIDTH - 1)) / WIDTH; } - - private int bucketSize(int Row) { - return (int) Math.pow(2, Row); + VARIANCE += incVariance; + TOTAL += Value; + compressBuckets(); + } + + private void insertElementBucket(double Variance, double Value, ListItem Node) { + // Insert new bucket + Node.insertBucket(Value, Variance); + BucketNumber++; + if (BucketNumber > BucketNumberMAX) { + BucketNumberMAX = BucketNumber; } - - public int deleteElement() { - //LIST - //Update statistics - ListItem Node; - Node = listRowBuckets.tail(); - int n1 = bucketSize(lastBucketRow); - WIDTH -= n1; - TOTAL -= Node.Total(0); - double u1 = Node.Total(0) / n1; - double incVariance = Node.Variance(0) + n1 * WIDTH * (u1 - TOTAL / WIDTH) * (u1 - TOTAL / WIDTH) / (n1 + WIDTH); - VARIANCE -= incVariance; - - //Delete Bucket - Node.RemoveBucket(); - BucketNumber--; - if (Node.bucketSizeRow == 0) { - listRowBuckets.removeFromTail(); - lastBucketRow--; - } - return n1; + } + + private int bucketSize(int Row) { + return (int) Math.pow(2, Row); + } + + public int deleteElement() { + // LIST + // Update statistics + ListItem Node; + Node = listRowBuckets.tail(); + int n1 = bucketSize(lastBucketRow); + WIDTH -= n1; + TOTAL -= Node.Total(0); + double u1 = Node.Total(0) / n1; + double incVariance = Node.Variance(0) + n1 * WIDTH * (u1 - TOTAL / WIDTH) * (u1 - TOTAL / WIDTH) / (n1 + WIDTH); + VARIANCE -= incVariance; + + // Delete Bucket + Node.RemoveBucket(); + BucketNumber--; + if (Node.bucketSizeRow == 0) { + listRowBuckets.removeFromTail(); + lastBucketRow--; } - - public void compressBuckets() { - //Traverse the list of buckets in increasing order - int n1, n2; - double u2, u1, incVariance; - ListItem cursor; - ListItem nextNode; - cursor = listRowBuckets.head(); - int i = 0; + return n1; + } + + public void compressBuckets() { + // Traverse the list of buckets in increasing order + int n1, n2; + double u2, u1, incVariance; + ListItem cursor; + ListItem nextNode; + cursor = listRowBuckets.head(); + int i = 0; + do { + // Find the number of buckets in a row + int k = cursor.bucketSizeRow; + // If the row is full, merge buckets + if (k == MAXBUCKETS + 1) { + nextNode = cursor.next(); + if (nextNode == null) { + listRowBuckets.addToTail(); + nextNode = cursor.next(); + lastBucketRow++; + } + n1 = bucketSize(i); + n2 = bucketSize(i); + u1 = cursor.Total(0) / n1; + u2 = cursor.Total(1) / n2; + incVariance = n1 * n2 * (u1 - u2) * (u1 - u2) / (n1 + n2); + + nextNode.insertBucket(cursor.Total(0) + cursor.Total(1), cursor.Variance(0) + cursor.Variance(1) + incVariance); + BucketNumber++; + cursor.compressBucketsRow(2); + if (nextNode.bucketSizeRow <= MAXBUCKETS) { + break; + } + } else { + break; + } + cursor = cursor.next(); + i++; + } while (cursor != null); + } + + public boolean setInput(double intEntrada) { + return setInput(intEntrada, mdbldelta); + } + + public boolean setInput(double intEntrada, double delta) { + boolean blnChange = false; + boolean blnExit; + ListItem cursor; + mintTime++; + + // 1,2)Increment window in one element + insertElement(intEntrada); + blnBucketDeleted = false; + // 3)Reduce window + if (mintTime % mintClock == 0 && getWidth() > mintMinimLongitudWindow) { + boolean blnReduceWidth = true; // Diference + + while (blnReduceWidth) // Diference + { + blnReduceWidth = false; // Diference + blnExit = false; + int n0 = 0; + int n1 = WIDTH; + double u0 = 0; + double u1 = getTotal(); + double v0 = 0; + double v1 = VARIANCE; + double n2; + double u2; + + cursor = listRowBuckets.tail(); + int i = lastBucketRow; do { - //Find the number of buckets in a row - int k = cursor.bucketSizeRow; - //If the row is full, merge buckets - if (k == MAXBUCKETS + 1) { - nextNode = cursor.next(); - if (nextNode == null) { - listRowBuckets.addToTail(); - nextNode = cursor.next(); - lastBucketRow++; - } - n1 = bucketSize(i); - n2 = bucketSize(i); - u1 = cursor.Total(0) / n1; - u2 = cursor.Total(1) / n2; - incVariance = n1 * n2 * (u1 - u2) * (u1 - u2) / (n1 + n2); - - nextNode.insertBucket(cursor.Total(0) + cursor.Total(1), cursor.Variance(0) + cursor.Variance(1) + incVariance); - BucketNumber++; - cursor.compressBucketsRow(2); - if (nextNode.bucketSizeRow <= MAXBUCKETS) { - break; - } - } else { - break; + for (int k = 0; k <= (cursor.bucketSizeRow - 1); k++) { + n2 = bucketSize(i); + u2 = cursor.Total(k); + if (n0 > 0) { + v0 += cursor.Variance(k) + (double) n0 * n2 * (u0 / n0 - u2 / n2) * (u0 / n0 - u2 / n2) / (n0 + n2); + } + if (n1 > 0) { + v1 -= cursor.Variance(k) + (double) n1 * n2 * (u1 / n1 - u2 / n2) * (u1 / n1 - u2 / n2) / (n1 + n2); } - cursor = cursor.next(); - i++; - } while (cursor != null); - } - - public boolean setInput(double intEntrada) { - return setInput(intEntrada, mdbldelta); - } - - public boolean setInput(double intEntrada, double delta) { - boolean blnChange = false; - boolean blnExit; - ListItem cursor; - mintTime++; - - //1,2)Increment window in one element - insertElement(intEntrada); - blnBucketDeleted = false; - //3)Reduce window - if (mintTime % mintClock == 0 && getWidth() > mintMinimLongitudWindow) { - boolean blnReduceWidth = true; // Diference - - while (blnReduceWidth) // Diference - { - blnReduceWidth = false; // Diference - blnExit = false; - int n0 = 0; - int n1 = WIDTH; - double u0 = 0; - double u1 = getTotal(); - double v0 = 0; - double v1 = VARIANCE; - double n2; - double u2; - - cursor = listRowBuckets.tail(); - int i = lastBucketRow; - do { - for (int k = 0; k <= (cursor.bucketSizeRow - 1); k++) { - n2 = bucketSize(i); - u2 = cursor.Total(k); - if (n0 > 0) { - v0 += cursor.Variance(k) + (double) n0 * n2 * (u0 / n0 - u2 / n2) * (u0 / n0 - u2 / n2) / (n0 + n2); - } - if (n1 > 0) { - v1 -= cursor.Variance(k) + (double) n1 * n2 * (u1 / n1 - u2 / n2) * (u1 / n1 - u2 / n2) / (n1 + n2); - } - - n0 += bucketSize(i); - n1 -= bucketSize(i); - u0 += cursor.Total(k); - u1 -= cursor.Total(k); - - if (i == 0 && k == cursor.bucketSizeRow - 1) { - blnExit = true; - break; - } - double absvalue = (u0 / n0) - (u1 / n1); //n1<WIDTH-mintMinWinLength-1 - if ((n1 > mintMinWinLength + 1 && n0 > mintMinWinLength + 1) && // Diference NEGATIVE - //if( - blnCutexpression(n0, n1, u0, u1, v0, v1, absvalue, delta)) { - blnBucketDeleted = true; - Detect = mintTime; - - if (Detect == 0) { - Detect = mintTime; - //blnFirst=true; - //blnWarning=true; - } else if (DetectTwice == 0) { - DetectTwice = mintTime; - //blnDetect=true; - } - blnReduceWidth = true; // Diference - blnChange = true; - if (getWidth() > 0) { //Reduce width of the window - //while (n0>0) // Diference NEGATIVE - n0 -= deleteElement(); - blnExit = true; - break; - } - } //End if - }//Next k - cursor = cursor.previous(); - i--; - } while (((!blnExit && cursor != null))); - }//End While // Diference - }//End if - - mdblWidth += getWidth(); - if (blnChange) { - numberDetections++; - } - return blnChange; - } - - private boolean blnCutexpression(int n0, int n1, double u0, double u1, double v0, double v1, double absvalue, double delta) { - int n = getWidth(); - double dd = Math.log(2 * Math.log(n) / delta); // -- ull perque el ln n va al numerador. - // Formula Gener 2008 - double v = getVariance(); - double m = ((double) 1 / ((n0 - mintMinWinLength + 1))) + ((double) 1 / ((n1 - mintMinWinLength + 1))); - double epsilon = Math.sqrt(2 * m * v * dd) + (double) 2 / 3 * dd * m; - - return (Math.abs(absvalue) > epsilon); - } - - public ADWIN() { - mdbldelta = DELTA; - initBuckets(); - Detect = 0; - numberDetections = 0; - DetectTwice = 0; - - } - - public ADWIN(double d) { - mdbldelta = d; - initBuckets(); - Detect = 0; - numberDetections = 0; - DetectTwice = 0; - } - - public ADWIN(int cl) { - mdbldelta = DELTA; - initBuckets(); - Detect = 0; - numberDetections = 0; - DetectTwice = 0; - mintClock = cl; - } - - public String getEstimatorInfo() { - return "ADWIN;;"; - } - public void setW(int W0) { - } + n0 += bucketSize(i); + n1 -= bucketSize(i); + u0 += cursor.Total(k); + u1 -= cursor.Total(k); - @Override - public void getDescription(StringBuilder sb, int indent) { + if (i == 0 && k == cursor.bucketSizeRow - 1) { + blnExit = true; + break; + } + double absvalue = (u0 / n0) - (u1 / n1); // n1<WIDTH-mintMinWinLength-1 + if ((n1 > mintMinWinLength + 1 && n0 > mintMinWinLength + 1) && // Diference + // NEGATIVE + // if( + blnCutexpression(n0, n1, u0, u1, v0, v1, absvalue, delta)) { + blnBucketDeleted = true; + Detect = mintTime; + + if (Detect == 0) { + Detect = mintTime; + // blnFirst=true; + // blnWarning=true; + } else if (DetectTwice == 0) { + DetectTwice = mintTime; + // blnDetect=true; + } + blnReduceWidth = true; // Diference + blnChange = true; + if (getWidth() > 0) { // Reduce width of the window + // while (n0>0) // Diference NEGATIVE + n0 -= deleteElement(); + blnExit = true; + break; + } + } // End if + }// Next k + cursor = cursor.previous(); + i--; + } while (((!blnExit && cursor != null))); + }// End While // Diference + }// End if + + mdblWidth += getWidth(); + if (blnChange) { + numberDetections++; } + return blnChange; + } + + private boolean blnCutexpression(int n0, int n1, double u0, double u1, double v0, double v1, double absvalue, + double delta) { + int n = getWidth(); + double dd = Math.log(2 * Math.log(n) / delta); // -- ull perque el ln n va + // al numerador. + // Formula Gener 2008 + double v = getVariance(); + double m = ((double) 1 / ((n0 - mintMinWinLength + 1))) + ((double) 1 / ((n1 - mintMinWinLength + 1))); + double epsilon = Math.sqrt(2 * m * v * dd) + (double) 2 / 3 * dd * m; + + return (Math.abs(absvalue) > epsilon); + } + + public ADWIN() { + mdbldelta = DELTA; + initBuckets(); + Detect = 0; + numberDetections = 0; + DetectTwice = 0; + + } + + public ADWIN(double d) { + mdbldelta = d; + initBuckets(); + Detect = 0; + numberDetections = 0; + DetectTwice = 0; + } + + public ADWIN(int cl) { + mdbldelta = DELTA; + initBuckets(); + Detect = 0; + numberDetections = 0; + DetectTwice = 0; + mintClock = cl; + } + + public String getEstimatorInfo() { + return "ADWIN;;"; + } + + public void setW(int W0) { + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + } }
http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWINChangeDetector.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWINChangeDetector.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWINChangeDetector.java index b582351..4e7b3dc 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWINChangeDetector.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ADWINChangeDetector.java @@ -1,4 +1,3 @@ - package com.yahoo.labs.samoa.moa.classifiers.core.driftdetection; /* @@ -25,49 +24,48 @@ import com.github.javacliparser.FloatOption; import com.yahoo.labs.samoa.moa.core.ObjectRepository; import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; - /** * Drift detection method based in ADWIN. ADaptive sliding WINdow is a change * detector and estimator. It keeps a variable-length window of recently seen * items, with the property that the window has the maximal length statistically * consistent with the hypothesis "there has been no change in the average value * inside the window". - * - * + * + * * @author Albert Bifet (abifet at cs dot waikato dot ac dot nz) * @version $Revision: 7 $ */ public class ADWINChangeDetector extends AbstractChangeDetector { - protected ADWIN adwin; + protected ADWIN adwin; - public FloatOption deltaAdwinOption = new FloatOption("deltaAdwin", 'a', - "Delta of Adwin change detection", 0.002, 0.0, 1.0); + public FloatOption deltaAdwinOption = new FloatOption("deltaAdwin", 'a', + "Delta of Adwin change detection", 0.002, 0.0, 1.0); - @Override - public void input(double inputValue) { - if (this.adwin == null) { - resetLearning(); - } - this.isChangeDetected = adwin.setInput(inputValue); - this.isWarningZone = false; - this.delay = 0.0; - this.estimation = adwin.getEstimation(); + @Override + public void input(double inputValue) { + if (this.adwin == null) { + resetLearning(); } + this.isChangeDetected = adwin.setInput(inputValue); + this.isWarningZone = false; + this.delay = 0.0; + this.estimation = adwin.getEstimation(); + } - @Override - public void resetLearning() { - adwin = new ADWIN(this.deltaAdwinOption.getValue()); - } + @Override + public void resetLearning() { + adwin = new ADWIN(this.deltaAdwinOption.getValue()); + } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub - } + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub - } + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/AbstractChangeDetector.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/AbstractChangeDetector.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/AbstractChangeDetector.java index ff591ab..a06707c 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/AbstractChangeDetector.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/AbstractChangeDetector.java @@ -24,120 +24,122 @@ import com.yahoo.labs.samoa.moa.options.AbstractOptionHandler; /** * Abstract Change Detector. All change detectors in MOA extend this class. - * + * * @author Albert Bifet (abifet at cs dot waikato dot ac dot nz) * @version $Revision: 7 $ */ public abstract class AbstractChangeDetector extends AbstractOptionHandler - implements ChangeDetector { - - - - /** - * Change was detected - */ - protected boolean isChangeDetected; - - /** - * Warning Zone: after a warning and before a change - */ - protected boolean isWarningZone; - - /** - * Prediction for the next value based in previous seen values - */ - protected double estimation; - - /** - * Delay in detecting change - */ - protected double delay; - - /** - * Resets this change detector. It must be similar to starting a new change - * detector from scratch. - * - */ - public void resetLearning() { - this.isChangeDetected = false; - this.isWarningZone = false; - this.estimation = 0.0; - this.delay = 0.0; - } - - /** - * Adding a numeric value to the change detector<br><br> - * - * The output of the change detector is modified after the insertion of a - * new item inside. - * - * @param inputValue the number to insert into the change detector - */ - public abstract void input(double inputValue); - - /** - * Gets whether there is change detected. - * - * @return true if there is change - */ - public boolean getChange() { - return this.isChangeDetected; - } - - /** - * Gets whether the change detector is in the warning zone, after a warning - * alert and before a change alert. - * - * @return true if the change detector is in the warning zone - */ - public boolean getWarningZone() { - return this.isWarningZone; - } - - /** - * Gets the prediction of next values. - * - * @return a prediction of the next value - */ - public double getEstimation() { - return this.estimation; - } - - /** - * Gets the length of the delay in the change detected. - * - * @return he length of the delay in the change detected - */ - public double getDelay() { - return this.delay; - } - - /** - * Gets the output state of the change detection. - * - * @return an array with the number of change detections, number of - * warnings, delay, and estimation. - */ - public double[] getOutput() { - return new double[]{this.isChangeDetected ? 1 : 0, this.isWarningZone ? 1 : 0, this.delay, this.estimation}; - } - - /** - * Returns a string representation of the model. - * - * @param sb the stringbuilder to add the description - * @param indent the number of characters to indent - */ - @Override - public abstract void getDescription(StringBuilder sb, int indent); - - /** - * Produces a copy of this change detector method - * - * @return the copy of this change detector method - */ - @Override - public ChangeDetector copy() { - return (ChangeDetector) super.copy(); - } + implements ChangeDetector { + + /** + * Change was detected + */ + protected boolean isChangeDetected; + + /** + * Warning Zone: after a warning and before a change + */ + protected boolean isWarningZone; + + /** + * Prediction for the next value based in previous seen values + */ + protected double estimation; + + /** + * Delay in detecting change + */ + protected double delay; + + /** + * Resets this change detector. It must be similar to starting a new change + * detector from scratch. + * + */ + public void resetLearning() { + this.isChangeDetected = false; + this.isWarningZone = false; + this.estimation = 0.0; + this.delay = 0.0; + } + + /** + * Adding a numeric value to the change detector<br> + * <br> + * + * The output of the change detector is modified after the insertion of a new + * item inside. + * + * @param inputValue + * the number to insert into the change detector + */ + public abstract void input(double inputValue); + + /** + * Gets whether there is change detected. + * + * @return true if there is change + */ + public boolean getChange() { + return this.isChangeDetected; + } + + /** + * Gets whether the change detector is in the warning zone, after a warning + * alert and before a change alert. + * + * @return true if the change detector is in the warning zone + */ + public boolean getWarningZone() { + return this.isWarningZone; + } + + /** + * Gets the prediction of next values. + * + * @return a prediction of the next value + */ + public double getEstimation() { + return this.estimation; + } + + /** + * Gets the length of the delay in the change detected. + * + * @return he length of the delay in the change detected + */ + public double getDelay() { + return this.delay; + } + + /** + * Gets the output state of the change detection. + * + * @return an array with the number of change detections, number of warnings, + * delay, and estimation. + */ + public double[] getOutput() { + return new double[] { this.isChangeDetected ? 1 : 0, this.isWarningZone ? 1 : 0, this.delay, this.estimation }; + } + + /** + * Returns a string representation of the model. + * + * @param sb + * the stringbuilder to add the description + * @param indent + * the number of characters to indent + */ + @Override + public abstract void getDescription(StringBuilder sb, int indent); + + /** + * Produces a copy of this change detector method + * + * @return the copy of this change detector method + */ + @Override + public ChangeDetector copy() { + return (ChangeDetector) super.copy(); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ChangeDetector.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ChangeDetector.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ChangeDetector.java index 47dc203..d2bae2b 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ChangeDetector.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/ChangeDetector.java @@ -23,80 +23,85 @@ package com.yahoo.labs.samoa.moa.classifiers.core.driftdetection; import com.yahoo.labs.samoa.moa.options.OptionHandler; /** - * Change Detector interface to implement methods that detects change. - * + * Change Detector interface to implement methods that detects change. + * * @author Albert Bifet (abifet at cs dot waikato dot ac dot nz) * @version $Revision: 7 $ */ public interface ChangeDetector extends OptionHandler { - /** - * Resets this change detector. It must be similar to starting a new change - * detector from scratch. - * - */ - public void resetLearning(); + /** + * Resets this change detector. It must be similar to starting a new change + * detector from scratch. + * + */ + public void resetLearning(); - /** - * Adding a numeric value to the change detector<br><br> - * - * The output of the change detector is modified after the insertion of a - * new item inside. - * - * @param inputValue the number to insert into the change detector - */ - public void input(double inputValue); + /** + * Adding a numeric value to the change detector<br> + * <br> + * + * The output of the change detector is modified after the insertion of a new + * item inside. + * + * @param inputValue + * the number to insert into the change detector + */ + public void input(double inputValue); - /** - * Gets whether there is change detected. - * - * @return true if there is change - */ - public boolean getChange(); + /** + * Gets whether there is change detected. + * + * @return true if there is change + */ + public boolean getChange(); - /** - * Gets whether the change detector is in the warning zone, after a warning alert and before a change alert. - * - * @return true if the change detector is in the warning zone - */ - public boolean getWarningZone(); + /** + * Gets whether the change detector is in the warning zone, after a warning + * alert and before a change alert. + * + * @return true if the change detector is in the warning zone + */ + public boolean getWarningZone(); - /** - * Gets the prediction of next values. - * - * @return a prediction of the next value - */ - public double getEstimation(); + /** + * Gets the prediction of next values. + * + * @return a prediction of the next value + */ + public double getEstimation(); - /** - * Gets the length of the delay in the change detected. - * - * @return he length of the delay in the change detected - */ - public double getDelay(); + /** + * Gets the length of the delay in the change detected. + * + * @return he length of the delay in the change detected + */ + public double getDelay(); - /** - * Gets the output state of the change detection. - * - * @return an array with the number of change detections, number of - * warnings, delay, and estimation. - */ - public double[] getOutput(); + /** + * Gets the output state of the change detection. + * + * @return an array with the number of change detections, number of warnings, + * delay, and estimation. + */ + public double[] getOutput(); - /** - * Returns a string representation of the model. - * - * @param out the stringbuilder to add the description - * @param indent the number of characters to indent - */ - @Override - public void getDescription(StringBuilder sb, int indent); + /** + * Returns a string representation of the model. + * + * @param out + * the stringbuilder to add the description + * @param indent + * the number of characters to indent + */ + @Override + public void getDescription(StringBuilder sb, int indent); - /** - * Produces a copy of this drift detection method - * - * @return the copy of this drift detection method - */ - @Override - public ChangeDetector copy(); + /** + * Produces a copy of this drift detection method + * + * @return the copy of this drift detection method + */ + @Override + public ChangeDetector copy(); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/CusumDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/CusumDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/CusumDM.java index e372ae8..88bce73 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/CusumDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/CusumDM.java @@ -27,84 +27,84 @@ import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** * Drift detection method based in Cusum - * - * + * + * * @author Manuel Baena ([email protected]) * @version $Revision: 7 $ */ public class CusumDM extends AbstractChangeDetector { - private static final long serialVersionUID = -3518369648142099719L; + private static final long serialVersionUID = -3518369648142099719L; - public IntOption minNumInstancesOption = new IntOption( - "minNumInstances", - 'n', - "The minimum number of instances before permitting detecting change.", - 30, 0, Integer.MAX_VALUE); + public IntOption minNumInstancesOption = new IntOption( + "minNumInstances", + 'n', + "The minimum number of instances before permitting detecting change.", + 30, 0, Integer.MAX_VALUE); - public FloatOption deltaOption = new FloatOption("delta", 'd', - "Delta parameter of the Cusum Test", 0.005, 0.0, 1.0); + public FloatOption deltaOption = new FloatOption("delta", 'd', + "Delta parameter of the Cusum Test", 0.005, 0.0, 1.0); - public FloatOption lambdaOption = new FloatOption("lambda", 'l', - "Threshold parameter of the Cusum Test", 50, 0.0, Float.MAX_VALUE); + public FloatOption lambdaOption = new FloatOption("lambda", 'l', + "Threshold parameter of the Cusum Test", 50, 0.0, Float.MAX_VALUE); - private int m_n; + private int m_n; - private double sum; + private double sum; - private double x_mean; + private double x_mean; - private double delta; + private double delta; - private double lambda; + private double lambda; - public CusumDM() { - resetLearning(); - } + public CusumDM() { + resetLearning(); + } - @Override - public void resetLearning() { - m_n = 1; - x_mean = 0.0; - sum = 0.0; - delta = this.deltaOption.getValue(); - lambda = this.lambdaOption.getValue(); - } + @Override + public void resetLearning() { + m_n = 1; + x_mean = 0.0; + sum = 0.0; + delta = this.deltaOption.getValue(); + lambda = this.lambdaOption.getValue(); + } - @Override - public void input(double x) { - // It monitors the error rate - if (this.isChangeDetected) { - resetLearning(); - } - - x_mean = x_mean + (x - x_mean) / (double) m_n; - sum = Math.max(0, sum + x - x_mean - this.delta); - m_n++; - - // System.out.print(prediction + " " + m_n + " " + (m_p+m_s) + " "); - this.estimation = x_mean; - this.isChangeDetected = false; - this.isWarningZone = false; - this.delay = 0; - - if (m_n < this.minNumInstancesOption.getValue()) { - return; - } - - if (sum > this.lambda) { - this.isChangeDetected = true; - } + @Override + public void input(double x) { + // It monitors the error rate + if (this.isChangeDetected) { + resetLearning(); } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub + x_mean = x_mean + (x - x_mean) / (double) m_n; + sum = Math.max(0, sum + x - x_mean - this.delta); + m_n++; + + // System.out.print(prediction + " " + m_n + " " + (m_p+m_s) + " "); + this.estimation = x_mean; + this.isChangeDetected = false; + this.isWarningZone = false; + this.delay = 0; + + if (m_n < this.minNumInstancesOption.getValue()) { + return; } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub + if (sum > this.lambda) { + this.isChangeDetected = true; } + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/DDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/DDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/DDM.java index af5dd52..1bf2cdd 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/DDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/DDM.java @@ -25,93 +25,95 @@ import com.yahoo.labs.samoa.moa.core.ObjectRepository; import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** - * Drift detection method based in DDM method of Joao Gama SBIA 2004. - * - * <p>João Gama, Pedro Medas, Gladys Castillo, Pedro Pereira Rodrigues: Learning - * with Drift Detection. SBIA 2004: 286-295 </p> - * - * @author Manuel Baena ([email protected]) - * @version $Revision: 7 $ + * Drift detection method based in DDM method of Joao Gama SBIA 2004. + * + * <p> + * João Gama, Pedro Medas, Gladys Castillo, Pedro Pereira Rodrigues: Learning + * with Drift Detection. SBIA 2004: 286-295 + * </p> + * + * @author Manuel Baena ([email protected]) + * @version $Revision: 7 $ */ public class DDM extends AbstractChangeDetector { - private static final long serialVersionUID = -3518369648142099719L; + private static final long serialVersionUID = -3518369648142099719L; - //private static final int DDM_MINNUMINST = 30; - public IntOption minNumInstancesOption = new IntOption( - "minNumInstances", - 'n', - "The minimum number of instances before permitting detecting change.", - 30, 0, Integer.MAX_VALUE); - private int m_n; + // private static final int DDM_MINNUMINST = 30; + public IntOption minNumInstancesOption = new IntOption( + "minNumInstances", + 'n', + "The minimum number of instances before permitting detecting change.", + 30, 0, Integer.MAX_VALUE); + private int m_n; - private double m_p; + private double m_p; - private double m_s; + private double m_s; - private double m_psmin; + private double m_psmin; - private double m_pmin; + private double m_pmin; - private double m_smin; + private double m_smin; - public DDM() { - resetLearning(); - } + public DDM() { + resetLearning(); + } - @Override - public void resetLearning() { - m_n = 1; - m_p = 1; - m_s = 0; - m_psmin = Double.MAX_VALUE; - m_pmin = Double.MAX_VALUE; - m_smin = Double.MAX_VALUE; - } + @Override + public void resetLearning() { + m_n = 1; + m_p = 1; + m_s = 0; + m_psmin = Double.MAX_VALUE; + m_pmin = Double.MAX_VALUE; + m_smin = Double.MAX_VALUE; + } - @Override - public void input(double prediction) { - // prediction must be 1 or 0 - // It monitors the error rate - if (this.isChangeDetected) { - resetLearning(); - } - m_p = m_p + (prediction - m_p) / (double) m_n; - m_s = Math.sqrt(m_p * (1 - m_p) / (double) m_n); - - m_n++; - - // System.out.print(prediction + " " + m_n + " " + (m_p+m_s) + " "); - this.estimation = m_p; - this.isChangeDetected = false; - this.isWarningZone = false; - this.delay = 0; - - if (m_n < this.minNumInstancesOption.getValue()) { - return; - } - - if (m_p + m_s <= m_psmin) { - m_pmin = m_p; - m_smin = m_s; - m_psmin = m_p + m_s; - } - - if (m_n > this.minNumInstancesOption.getValue() && m_p + m_s > m_pmin + 3 * m_smin) { - this.isChangeDetected = true; - //resetLearning(); - } else - this.isWarningZone = m_p + m_s > m_pmin + 2 * m_smin; + @Override + public void input(double prediction) { + // prediction must be 1 or 0 + // It monitors the error rate + if (this.isChangeDetected) { + resetLearning(); } + m_p = m_p + (prediction - m_p) / (double) m_n; + m_s = Math.sqrt(m_p * (1 - m_p) / (double) m_n); - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub + m_n++; + + // System.out.print(prediction + " " + m_n + " " + (m_p+m_s) + " "); + this.estimation = m_p; + this.isChangeDetected = false; + this.isWarningZone = false; + this.delay = 0; + + if (m_n < this.minNumInstancesOption.getValue()) { + return; } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub + if (m_p + m_s <= m_psmin) { + m_pmin = m_p; + m_smin = m_s; + m_psmin = m_p + m_s; } + + if (m_n > this.minNumInstancesOption.getValue() && m_p + m_s > m_pmin + 3 * m_smin) { + this.isChangeDetected = true; + // resetLearning(); + } else + this.isWarningZone = m_p + m_s > m_pmin + 2 * m_smin; + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EDDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EDDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EDDM.java index 2ab1022..b845120 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EDDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EDDM.java @@ -25,114 +25,116 @@ import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** * Drift detection method based in EDDM method of Manuel Baena et al. - * - * <p>Early Drift Detection Method. Manuel Baena-Garcia, Jose Del Campo-Avila, - * Raúl Fidalgo, Albert Bifet, Ricard Gavalda, Rafael Morales-Bueno. In Fourth - * International Workshop on Knowledge Discovery from Data Streams, 2006.</p> - * + * + * <p> + * Early Drift Detection Method. Manuel Baena-Garcia, Jose Del Campo-Avila, Raúl + * Fidalgo, Albert Bifet, Ricard Gavalda, Rafael Morales-Bueno. In Fourth + * International Workshop on Knowledge Discovery from Data Streams, 2006. + * </p> + * * @author Manuel Baena ([email protected]) * @version $Revision: 7 $ */ public class EDDM extends AbstractChangeDetector { - /** + /** * */ - private static final long serialVersionUID = 140980267062162000L; + private static final long serialVersionUID = 140980267062162000L; - private static final double FDDM_OUTCONTROL = 0.9; + private static final double FDDM_OUTCONTROL = 0.9; - private static final double FDDM_WARNING = 0.95; + private static final double FDDM_WARNING = 0.95; - private static final double FDDM_MINNUMINSTANCES = 30; + private static final double FDDM_MINNUMINSTANCES = 30; - private double m_numErrors; + private double m_numErrors; - private int m_minNumErrors = 30; + private int m_minNumErrors = 30; - private int m_n; + private int m_n; - private int m_d; + private int m_d; - private int m_lastd; + private int m_lastd; - private double m_mean; + private double m_mean; - private double m_stdTemp; + private double m_stdTemp; - private double m_m2smax; + private double m_m2smax; - public EDDM() { - resetLearning(); - } + public EDDM() { + resetLearning(); + } - @Override - public void resetLearning() { - m_n = 1; - m_numErrors = 0; - m_d = 0; - m_lastd = 0; - m_mean = 0.0; - m_stdTemp = 0.0; - m_m2smax = 0.0; - this.estimation = 0.0; - } + @Override + public void resetLearning() { + m_n = 1; + m_numErrors = 0; + m_d = 0; + m_lastd = 0; + m_mean = 0.0; + m_stdTemp = 0.0; + m_m2smax = 0.0; + this.estimation = 0.0; + } - @Override - public void input(double prediction) { - // prediction must be 1 or 0 - // It monitors the error rate - // System.out.print(prediction + " " + m_n + " " + probability + " "); - if (this.isChangeDetected) { - resetLearning(); + @Override + public void input(double prediction) { + // prediction must be 1 or 0 + // It monitors the error rate + // System.out.print(prediction + " " + m_n + " " + probability + " "); + if (this.isChangeDetected) { + resetLearning(); + } + this.isChangeDetected = false; + + m_n++; + if (prediction == 1.0) { + this.isWarningZone = false; + this.delay = 0; + m_numErrors += 1; + m_lastd = m_d; + m_d = m_n - 1; + int distance = m_d - m_lastd; + double oldmean = m_mean; + m_mean = m_mean + ((double) distance - m_mean) / m_numErrors; + this.estimation = m_mean; + m_stdTemp = m_stdTemp + (distance - m_mean) * (distance - oldmean); + double std = Math.sqrt(m_stdTemp / m_numErrors); + double m2s = m_mean + 2 * std; + + if (m2s > m_m2smax) { + if (m_n > FDDM_MINNUMINSTANCES) { + m_m2smax = m2s; } - this.isChangeDetected = false; - - m_n++; - if (prediction == 1.0) { - this.isWarningZone = false; - this.delay = 0; - m_numErrors += 1; - m_lastd = m_d; - m_d = m_n - 1; - int distance = m_d - m_lastd; - double oldmean = m_mean; - m_mean = m_mean + ((double) distance - m_mean) / m_numErrors; - this.estimation = m_mean; - m_stdTemp = m_stdTemp + (distance - m_mean) * (distance - oldmean); - double std = Math.sqrt(m_stdTemp / m_numErrors); - double m2s = m_mean + 2 * std; - - if (m2s > m_m2smax) { - if (m_n > FDDM_MINNUMINSTANCES) { - m_m2smax = m2s; - } - //m_lastLevel = DDM_INCONTROL_LEVEL; - // System.out.print(1 + " "); - } else { - double p = m2s / m_m2smax; - // System.out.print(p + " "); - if (m_n > FDDM_MINNUMINSTANCES && m_numErrors > m_minNumErrors - && p < FDDM_OUTCONTROL) { - //System.out.println(m_mean + ",D"); - this.isChangeDetected = true; - //resetLearning(); - } else { - this.isWarningZone = m_n > FDDM_MINNUMINSTANCES - && m_numErrors > m_minNumErrors && p < FDDM_WARNING; - } - } + // m_lastLevel = DDM_INCONTROL_LEVEL; + // System.out.print(1 + " "); + } else { + double p = m2s / m_m2smax; + // System.out.print(p + " "); + if (m_n > FDDM_MINNUMINSTANCES && m_numErrors > m_minNumErrors + && p < FDDM_OUTCONTROL) { + // System.out.println(m_mean + ",D"); + this.isChangeDetected = true; + // resetLearning(); + } else { + this.isWarningZone = m_n > FDDM_MINNUMINSTANCES + && m_numErrors > m_minNumErrors && p < FDDM_WARNING; } + } } - - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub - } - - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub - } + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EWMAChartDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EWMAChartDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EWMAChartDM.java index 7f98099..6394259 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EWMAChartDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/EWMAChartDM.java @@ -28,95 +28,96 @@ import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** * Drift detection method based in EWMA Charts of Ross, Adams, Tasoulis and Hand * 2012 - * - * + * + * * @author Manuel Baena ([email protected]) * @version $Revision: 7 $ */ public class EWMAChartDM extends AbstractChangeDetector { - private static final long serialVersionUID = -3518369648142099719L; + private static final long serialVersionUID = -3518369648142099719L; - //private static final int DDM_MIN_NUM_INST = 30; - public IntOption minNumInstancesOption = new IntOption( - "minNumInstances", - 'n', - "The minimum number of instances before permitting detecting change.", - 30, 0, Integer.MAX_VALUE); + // private static final int DDM_MIN_NUM_INST = 30; + public IntOption minNumInstancesOption = new IntOption( + "minNumInstances", + 'n', + "The minimum number of instances before permitting detecting change.", + 30, 0, Integer.MAX_VALUE); - public FloatOption lambdaOption = new FloatOption("lambda", 'l', - "Lambda parameter of the EWMA Chart Method", 0.2, 0.0, Float.MAX_VALUE); + public FloatOption lambdaOption = new FloatOption("lambda", 'l', + "Lambda parameter of the EWMA Chart Method", 0.2, 0.0, Float.MAX_VALUE); - private double m_n; + private double m_n; - private double m_sum; - - private double m_p; - - private double m_s; - - private double lambda; - - private double z_t; + private double m_sum; - public EWMAChartDM() { - resetLearning(); - } + private double m_p; - @Override - public void resetLearning() { - m_n = 1.0; - m_sum = 0.0; - m_p = 0.0; - m_s = 0.0; - z_t = 0.0; - lambda = this.lambdaOption.getValue(); - } + private double m_s; + + private double lambda; + + private double z_t; + + public EWMAChartDM() { + resetLearning(); + } - @Override - public void input(double prediction) { - // prediction must be 1 or 0 - // It monitors the error rate - if (this.isChangeDetected) { - resetLearning(); - } - - m_sum += prediction; - - m_p = m_sum/m_n; // m_p + (prediction - m_p) / (double) (m_n+1); - - m_s = Math.sqrt( m_p * (1.0 - m_p)* lambda * (1.0 - Math.pow(1.0 - lambda, 2.0 * m_n)) / (2.0 - lambda)); - - m_n++; - - z_t += lambda * (prediction - z_t); - - double L_t = 3.97 - 6.56 * m_p + 48.73 * Math.pow(m_p, 3) - 330.13 * Math.pow(m_p, 5) + 848.18 * Math.pow(m_p, 7); //%1 FP - this.estimation = m_p; - this.isChangeDetected = false; - this.isWarningZone = false; - this.delay = 0; - - if (m_n < this.minNumInstancesOption.getValue()) { - return; - } - - if (m_n > this.minNumInstancesOption.getValue() && z_t > m_p + L_t * m_s) { - this.isChangeDetected = true; - //resetLearning(); - } else { - this.isWarningZone = z_t > m_p + 0.5 * L_t * m_s; - } + @Override + public void resetLearning() { + m_n = 1.0; + m_sum = 0.0; + m_p = 0.0; + m_s = 0.0; + z_t = 0.0; + lambda = this.lambdaOption.getValue(); + } + + @Override + public void input(double prediction) { + // prediction must be 1 or 0 + // It monitors the error rate + if (this.isChangeDetected) { + resetLearning(); } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub + m_sum += prediction; + + m_p = m_sum / m_n; // m_p + (prediction - m_p) / (double) (m_n+1); + + m_s = Math.sqrt(m_p * (1.0 - m_p) * lambda * (1.0 - Math.pow(1.0 - lambda, 2.0 * m_n)) / (2.0 - lambda)); + + m_n++; + + z_t += lambda * (prediction - z_t); + + double L_t = 3.97 - 6.56 * m_p + 48.73 * Math.pow(m_p, 3) - 330.13 * Math.pow(m_p, 5) + 848.18 * Math.pow(m_p, 7); // %1 + // FP + this.estimation = m_p; + this.isChangeDetected = false; + this.isWarningZone = false; + this.delay = 0; + + if (m_n < this.minNumInstancesOption.getValue()) { + return; } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub + if (m_n > this.minNumInstancesOption.getValue() && z_t > m_p + L_t * m_s) { + this.isChangeDetected = true; + // resetLearning(); + } else { + this.isWarningZone = z_t > m_p + 0.5 * L_t * m_s; } + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/GeometricMovingAverageDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/GeometricMovingAverageDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/GeometricMovingAverageDM.java index 5ed44e5..fc4335f 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/GeometricMovingAverageDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/GeometricMovingAverageDM.java @@ -27,82 +27,82 @@ import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** * Drift detection method based in Geometric Moving Average Test - * - * + * + * * @author Manuel Baena ([email protected]) * @version $Revision: 7 $ */ public class GeometricMovingAverageDM extends AbstractChangeDetector { - private static final long serialVersionUID = -3518369648142099719L; + private static final long serialVersionUID = -3518369648142099719L; - public IntOption minNumInstancesOption = new IntOption( - "minNumInstances", - 'n', - "The minimum number of instances before permitting detecting change.", - 30, 0, Integer.MAX_VALUE); + public IntOption minNumInstancesOption = new IntOption( + "minNumInstances", + 'n', + "The minimum number of instances before permitting detecting change.", + 30, 0, Integer.MAX_VALUE); - public FloatOption lambdaOption = new FloatOption("lambda", 'l', - "Threshold parameter of the Geometric Moving Average Test", 1, 0.0, Float.MAX_VALUE); + public FloatOption lambdaOption = new FloatOption("lambda", 'l', + "Threshold parameter of the Geometric Moving Average Test", 1, 0.0, Float.MAX_VALUE); - public FloatOption alphaOption = new FloatOption("alpha", 'a', - "Alpha parameter of the Geometric Moving Average Test", .99, 0.0, 1.0); + public FloatOption alphaOption = new FloatOption("alpha", 'a', + "Alpha parameter of the Geometric Moving Average Test", .99, 0.0, 1.0); - private double m_n; + private double m_n; - private double sum; + private double sum; - private double x_mean; - - private double alpha; + private double x_mean; - private double lambda; + private double alpha; - public GeometricMovingAverageDM() { - resetLearning(); - } + private double lambda; - @Override - public void resetLearning() { - m_n = 1.0; - x_mean = 0.0; - sum = 0.0; - alpha = this.alphaOption.getValue(); - lambda = this.lambdaOption.getValue(); - } + public GeometricMovingAverageDM() { + resetLearning(); + } + + @Override + public void resetLearning() { + m_n = 1.0; + x_mean = 0.0; + sum = 0.0; + alpha = this.alphaOption.getValue(); + lambda = this.lambdaOption.getValue(); + } - @Override - public void input(double x) { - // It monitors the error rate - if (this.isChangeDetected) { - resetLearning(); - } - - x_mean = x_mean + (x - x_mean) / m_n; - sum = alpha * sum + (1.0- alpha) * (x - x_mean); - m_n++; - this.estimation = x_mean; - this.isChangeDetected = false; - this.isWarningZone = false; - this.delay = 0; - - if (m_n < this.minNumInstancesOption.getValue()) { - return; - } - - if (sum > this.lambda) { - this.isChangeDetected = true; - } + @Override + public void input(double x) { + // It monitors the error rate + if (this.isChangeDetected) { + resetLearning(); } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub + x_mean = x_mean + (x - x_mean) / m_n; + sum = alpha * sum + (1.0 - alpha) * (x - x_mean); + m_n++; + this.estimation = x_mean; + this.isChangeDetected = false; + this.isWarningZone = false; + this.delay = 0; + + if (m_n < this.minNumInstancesOption.getValue()) { + return; } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub + if (sum > this.lambda) { + this.isChangeDetected = true; } + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/PageHinkleyDM.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/PageHinkleyDM.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/PageHinkleyDM.java index 7a94a17..a01021a 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/PageHinkleyDM.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/driftdetection/PageHinkleyDM.java @@ -27,88 +27,88 @@ import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** * Drift detection method based in Page Hinkley Test. - * - * + * + * * @author Manuel Baena ([email protected]) * @version $Revision: 7 $ */ public class PageHinkleyDM extends AbstractChangeDetector { - private static final long serialVersionUID = -3518369648142099719L; + private static final long serialVersionUID = -3518369648142099719L; - public IntOption minNumInstancesOption = new IntOption( - "minNumInstances", - 'n', - "The minimum number of instances before permitting detecting change.", - 30, 0, Integer.MAX_VALUE); + public IntOption minNumInstancesOption = new IntOption( + "minNumInstances", + 'n', + "The minimum number of instances before permitting detecting change.", + 30, 0, Integer.MAX_VALUE); - public FloatOption deltaOption = new FloatOption("delta", 'd', - "Delta parameter of the Page Hinkley Test", 0.005, 0.0, 1.0); + public FloatOption deltaOption = new FloatOption("delta", 'd', + "Delta parameter of the Page Hinkley Test", 0.005, 0.0, 1.0); - public FloatOption lambdaOption = new FloatOption("lambda", 'l', - "Lambda parameter of the Page Hinkley Test", 50, 0.0, Float.MAX_VALUE); + public FloatOption lambdaOption = new FloatOption("lambda", 'l', + "Lambda parameter of the Page Hinkley Test", 50, 0.0, Float.MAX_VALUE); - public FloatOption alphaOption = new FloatOption("alpha", 'a', - "Alpha parameter of the Page Hinkley Test", 1 - 0.0001, 0.0, 1.0); + public FloatOption alphaOption = new FloatOption("alpha", 'a', + "Alpha parameter of the Page Hinkley Test", 1 - 0.0001, 0.0, 1.0); - private int m_n; + private int m_n; - private double sum; + private double sum; - private double x_mean; + private double x_mean; - private double alpha; + private double alpha; - private double delta; + private double delta; - private double lambda; + private double lambda; - public PageHinkleyDM() { - resetLearning(); - } + public PageHinkleyDM() { + resetLearning(); + } - @Override - public void resetLearning() { - m_n = 1; - x_mean = 0.0; - sum = 0.0; - delta = this.deltaOption.getValue(); - alpha = this.alphaOption.getValue(); - lambda = this.lambdaOption.getValue(); - } + @Override + public void resetLearning() { + m_n = 1; + x_mean = 0.0; + sum = 0.0; + delta = this.deltaOption.getValue(); + alpha = this.alphaOption.getValue(); + lambda = this.lambdaOption.getValue(); + } - @Override - public void input(double x) { - // It monitors the error rate - if (this.isChangeDetected) { - resetLearning(); - } - - x_mean = x_mean + (x - x_mean) / (double) m_n; - sum = this.alpha * sum + (x - x_mean - this.delta); - m_n++; - this.estimation = x_mean; - this.isChangeDetected = false; - this.isWarningZone = false; - this.delay = 0; - - if (m_n < this.minNumInstancesOption.getValue()) { - return; - } - - if (sum > this.lambda) { - this.isChangeDetected = true; - } + @Override + public void input(double x) { + // It monitors the error rate + if (this.isChangeDetected) { + resetLearning(); } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub + x_mean = x_mean + (x - x_mean) / (double) m_n; + sum = this.alpha * sum + (x - x_mean - this.delta); + m_n++; + this.estimation = x_mean; + this.isChangeDetected = false; + this.isWarningZone = false; + this.delay = 0; + + if (m_n < this.minNumInstancesOption.getValue()) { + return; } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub + if (sum > this.lambda) { + this.isChangeDetected = true; } + } + + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/23a35dbe/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/splitcriteria/GiniSplitCriterion.java ---------------------------------------------------------------------- diff --git a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/splitcriteria/GiniSplitCriterion.java b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/splitcriteria/GiniSplitCriterion.java index 185b12f..b5135ea 100644 --- a/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/splitcriteria/GiniSplitCriterion.java +++ b/samoa-api/src/main/java/com/yahoo/labs/samoa/moa/classifiers/core/splitcriteria/GiniSplitCriterion.java @@ -26,61 +26,60 @@ import com.yahoo.labs.samoa.moa.options.AbstractOptionHandler; import com.yahoo.labs.samoa.moa.tasks.TaskMonitor; /** - * Class for computing splitting criteria using Gini - * with respect to distributions of class values. - * The split criterion is used as a parameter on + * Class for computing splitting criteria using Gini with respect to + * distributions of class values. The split criterion is used as a parameter on * decision trees and decision stumps. - * + * * @author Richard Kirkby ([email protected]) * @version $Revision: 7 $ */ public class GiniSplitCriterion extends AbstractOptionHandler implements - SplitCriterion { + SplitCriterion { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public double getMeritOfSplit(double[] preSplitDist, double[][] postSplitDists) { - double totalWeight = 0.0; - double[] distWeights = new double[postSplitDists.length]; - for (int i = 0; i < postSplitDists.length; i++) { - distWeights[i] = Utils.sum(postSplitDists[i]); - totalWeight += distWeights[i]; - } - double gini = 0.0; - for (int i = 0; i < postSplitDists.length; i++) { - gini += (distWeights[i] / totalWeight) - * computeGini(postSplitDists[i], distWeights[i]); - } - return 1.0 - gini; + @Override + public double getMeritOfSplit(double[] preSplitDist, double[][] postSplitDists) { + double totalWeight = 0.0; + double[] distWeights = new double[postSplitDists.length]; + for (int i = 0; i < postSplitDists.length; i++) { + distWeights[i] = Utils.sum(postSplitDists[i]); + totalWeight += distWeights[i]; } - - @Override - public double getRangeOfMerit(double[] preSplitDist) { - return 1.0; + double gini = 0.0; + for (int i = 0; i < postSplitDists.length; i++) { + gini += (distWeights[i] / totalWeight) + * computeGini(postSplitDists[i], distWeights[i]); } + return 1.0 - gini; + } - public static double computeGini(double[] dist, double distSumOfWeights) { - double gini = 1.0; - for (double aDist : dist) { - double relFreq = aDist / distSumOfWeights; - gini -= relFreq * relFreq; - } - return gini; - } + @Override + public double getRangeOfMerit(double[] preSplitDist) { + return 1.0; + } - public static double computeGini(double[] dist) { - return computeGini(dist, Utils.sum(dist)); + public static double computeGini(double[] dist, double distSumOfWeights) { + double gini = 1.0; + for (double aDist : dist) { + double relFreq = aDist / distSumOfWeights; + gini -= relFreq * relFreq; } + return gini; + } - @Override - public void getDescription(StringBuilder sb, int indent) { - // TODO Auto-generated method stub - } + public static double computeGini(double[] dist) { + return computeGini(dist, Utils.sum(dist)); + } - @Override - protected void prepareForUseImpl(TaskMonitor monitor, - ObjectRepository repository) { - // TODO Auto-generated method stub - } + @Override + public void getDescription(StringBuilder sb, int indent) { + // TODO Auto-generated method stub + } + + @Override + protected void prepareForUseImpl(TaskMonitor monitor, + ObjectRepository repository) { + // TODO Auto-generated method stub + } }
