mulan.dimensionalityReduction.BinaryRelevanceAttributeEvaluator.java Source code

Java tutorial

Introduction

Here is the source code for mulan.dimensionalityReduction.BinaryRelevanceAttributeEvaluator.java

Source

/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 *    BinaryRelevanceAttributeEvaluator.java
 *    Copyright (C) 2009-2010 Aristotle University of Thessaloniki, Thessaloniki, Greece
 */
package mulan.dimensionalityReduction;

import mulan.data.MultiLabelInstances;
import mulan.transformations.BinaryRelevanceTransformation;
import weka.attributeSelection.ASEvaluation;
import weka.attributeSelection.AttributeEvaluator;
import weka.core.Instances;

/**
 * @author George Traianos
 * @author Grigorios Tsoumakas
 */
public class BinaryRelevanceAttributeEvaluator extends ASEvaluation implements AttributeEvaluator {

    /** final scores for all attributes */
    private double[] scores;
    /** The number of labels */
    int numLabels;
    /**combination approach mode*/
    private String CombApprMode;
    /**normalization mode*/
    private String NormMode;
    /**attribute scoring based either on evaluation scores or ranking*/
    private String ScoreMode;

    /**
     * a wrapper class for score-based attribute ranking
     */
    public class Rank implements Comparable {

        /**score of the attribute*/
        private double score;
        /**index of the attribute*/
        private int index;

        /**
         * constructor
         * @param score the score to be given
         * @param index the index to  be given
         */
        public Rank(double score, int index) {
            this.score = score;
            this.index = index;
        }

        public double getScore() {
            return score;
        }

        public int getIndex() {
            return index;
        }

        public int compareTo(Object o) {
            if (score > ((Rank) o).score) {
                return 1;
            } else if (score < ((Rank) o).score) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    /**
     * @param ase 
     * @param mlData 
     * @param combapp combination approach mode ("max", "avg", "min")
     * @param norm normalization mode ("dl", "dm", "none")
     * @param mode scoring mode ("eval", "rank")
     */
    public BinaryRelevanceAttributeEvaluator(ASEvaluation ase, MultiLabelInstances mlData, String combapp,
            String norm, String mode) {
        CombApprMode = combapp;
        NormMode = norm;
        ScoreMode = mode;

        numLabels = mlData.getNumLabels();
        int[] labelIndices = mlData.getLabelIndices();
        try {
            int numAttributes = mlData.getFeatureIndices().length;
            double[][] evaluations = new double[numLabels][numAttributes];
            for (int i = 0; i < numLabels; i++) {
                // create dataset
                Instances labelInstances = BinaryRelevanceTransformation.transformInstances(mlData.getDataSet(),
                        labelIndices, labelIndices[i]);

                // build evaluator
                ase.buildEvaluator(labelInstances);

                // evaluate features
                for (int j = 0; j < numAttributes; j++) {
                    evaluations[i][j] = ((AttributeEvaluator) ase).evaluateAttribute(j);
                }
            }

            //scoring of features
            scores = featureSelection(evaluations);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * returns a ranking of attributes (where each attribute is represented by its index)
     * @param scores the attributes' scorelist
     * @return an ascending ranking of the attributes, based on their scores
     */
    public int[] rankAsc(double scores[]) {
        /*create a table to hold each attribute's score and index*/
        Rank r[] = new Rank[scores.length];

        for (int i = 0; i < r.length; i++) {
            r[i] = new Rank(scores[i], i);
        }

        /*sort the table, thus resulting in ascending, score-based ranking*/
        java.util.Arrays.sort(r);

        /*create a ranking table containing only the attributes' indices*/
        int ranking[] = new int[r.length];

        for (int i = 0; i < r.length; i++) {
            ranking[i] = r[i].getIndex();
        }

        return ranking;
    }

    /**
     * returns a ranking of attributes (where each attribute is represented by its index)
     * @param scores the attributes' scorelist
     * @return a descending ranking of the attributes, based on their scores
     */
    public int[] rankDesc(double scores[]) {
        int ranking[] = rankAsc(scores);
        int decr[] = new int[ranking.length];

        /*receive the indices in reverse order, thus resulting in descending ranking*/
        for (int i = 0; i < decr.length; i++) {
            decr[i] = ranking[(ranking.length - 1) - i];
        }

        return decr;
    }

    /**
     * orders the ranking scores according to their attributes' original indices
     * @param ranking a rank table
     * @return the order of the ranking scores
     */
    public int[] order(int ranking[]) {
        int order[] = new int[ranking.length];

        for (int i = 0; i < ranking.length; i++) {
            order[ranking[i]] = i + 1;
        }

        return order;
    }

    /**
     * highest score combination approach
     * @param scoreList all attributes' score lists
     * @param index the index of a specific attribute's score
     * @return the highest score achieved in any of the the input score lists
     */
    public double highest(double scoreList[][], int index) {
        double highest = scoreList[0][index];

        for (int i = 1; i < scoreList.length; i++) {
            highest = (scoreList[i][index] > highest ? scoreList[i][index] : highest);
        }

        return highest;
    }

    /**
     * lowest score combination approach
     * @param scoreList all attributes' score lists
     * @param index the index of a specific attribute's score
     * @return the lowest score achieved in all of the input score lists
     */
    public double lowest(double scoreList[][], int index) {
        double lowest = scoreList[0][index];

        for (int i = 1; i < scoreList.length; i++) {
            lowest = (scoreList[i][index] < lowest ? scoreList[i][index] : lowest);
        }

        return lowest;
    }

    /**
     * average score combination approach
     * @param scoreList all attributes' score lists
     * @param index the index of a specific attribute's score
     * @return the average score achieved in all the score lists
     */
    public double average(double scoreList[][], int index) {
        double sum = 0;

        for (int i = 0; i < scoreList.length; i++) {
            sum += scoreList[i][index];
        }

        return sum / scoreList.length;
    }

    /**
     * performs attribute selection
     * @param evaluations evaluation scores
     * @return an array of scores for all attributes
     * @throws Exception
     */
    private double[] featureSelection(double evaluations[][]) throws Exception {
        //perform dm or dl
        if (!NormMode.equalsIgnoreCase("none")) {
            if (NormMode.equalsIgnoreCase("dm")) {
                for (int i = 0; i < evaluations.length; i++) {
                    evaluations[i] = dm(evaluations[i]);
                }
            } else if (NormMode.equalsIgnoreCase("dl")) {
                for (int i = 0; i < evaluations.length; i++) {
                    evaluations[i] = dl(evaluations[i]);
                }
            }
        }

        //to hold attributes' scores
        double tempScores[][] = new double[numLabels][];

        //rank based scoring of attributes
        if (ScoreMode.equalsIgnoreCase("rank")) {
            //perform ranking
            int ranks[][] = new int[numLabels][];

            for (int i = 0; i < evaluations.length; i++) {
                ranks[i] = rankDesc(evaluations[i]);
                order(ranks[i]);
            }

            //transform ranking into a score
            for (int i = 0; i < ranks.length; i++) {
                tempScores[i] = new double[ranks[i].length];

                for (int j = 0; j < ranks[i].length; j++) {
                    tempScores[i][j] = (ranks[i].length - 1) + ranks[i][j];
                }
            }
        } //evaluation score based scoring of attributes
        else if (ScoreMode.equalsIgnoreCase("eval")) {
            //simply copy the evaluation scores
            for (int i = 0; i < evaluations.length; i++) {
                tempScores[i] = java.util.Arrays.copyOf(evaluations[i], evaluations[i].length);
            }
        }

        //employ a combination approach method
        double combAppr[] = new double[tempScores[0].length];

        if (CombApprMode.equalsIgnoreCase("max")) //highest
        {
            for (int i = 0; i < combAppr.length; i++) {
                combAppr[i] = highest(tempScores, i);
            }
        } else if (CombApprMode.equalsIgnoreCase("min")) //lowest
        {
            for (int i = 0; i < combAppr.length; i++) {
                combAppr[i] = lowest(tempScores, i);
            }
        } else if (CombApprMode.equalsIgnoreCase("avg")) //average
        {
            for (int i = 0; i < combAppr.length; i++) {
                combAppr[i] = average(tempScores, i);
            }
        }

        //return the scores for all attributes
        return combAppr;
    }

    /**
     * calculates the norm of a vector
     * @param vector a numeric array (as a vector)
     * @return the norm of the given vector
     */
    public static double norm(double vector[]) {
        double sumsq = 0;

        for (int i = 0; i < vector.length; i++) {
            sumsq += Math.pow(vector[i], 2);
        }

        return Math.sqrt(sumsq);
    }

    /**
     * normalizes an array (in the range of [0,1])
     * @param array a numeric array
     */
    public static void normalize(double array[]) {
        /*find the largest element*/
        double max = array[0];

        for (int i = 1; i < array.length; i++) {
            max = (array[i] > max ? array[i] : max);
        }

        /*normalize all elements*/
        for (int j = 0; j < array.length; j++) {
            array[j] /= max;
        }
    }

    /**
     * divide by length (dl) normalization
     * @param array a numeric array
     * @return a dl normalized copy of array
     */
    public static double[] dl(double array[]) {
        /*a copy of the original array*/
        double copy[] = new double[array.length];
        copy = java.util.Arrays.copyOf(array, array.length);

        /*calculate the norm*/
        double norm = norm(copy);

        /*divide each element by the norm*/
        for (int i = 0; i < copy.length; i++) {
            copy[i] /= norm;
        }

        return copy;
    }

    /**
     * divide by maximum (dm) normalization
     * @param array a numeric array
     * @return a dm normalized copy of array
     */
    public static double[] dm(double array[]) {
        /*a copy of the original array*/
        double copy[] = new double[array.length];
        copy = java.util.Arrays.copyOf(array, array.length);

        /*normalize the copy*/
        normalize(copy);

        return copy;
    }

    @Override
    public double evaluateAttribute(int attribute) throws Exception {
        return scores[attribute];
    }

    @Override
    public void buildEvaluator(Instances data) throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}