Map.get(key) returns null after inserting key

Discussion in 'Java' started by Mize-ze, Dec 31, 2006.

  1. Mize-ze

    Mize-ze Guest

    Hello,
    I am inserting a key and a object into a Map. later in the code I try
    to retrieve the object by calling
    Map.get(key) and I get a null.
    I can't see where is my problem...

    The application is a weka classifier.
    the problem can be seen in isAcceptable(Instance) function.

    First I populate a hashtable (calculateAprior method) where the key is
    an instance and the value
    is a double.
    later I will try to fetch the double value by the key and get null (in
    isAcceptable method).
    I will eventually recieve a NullPointerException.
    Thanks



    CODE:
    /*=============================buildIB3TrainingSet===========================*/

    private Instances buildIB3TrainingSet(Instances instances) {

    /** see implementation below <==**/
    calculateAprior(instances);
    double distance
    =0,minDistance=Double.MAX_VALUE,classValue=Double.NaN;

    /*** Sucess rate*/
    successRate = new HashMap<Instance,int[]>();

    Instances res = new Instances(instances,0,1);
    this.addSuccessSuccessRate(res.firstInstance());
    //Iterate on original
    for(int i=0;i<instances.numInstances();i++)
    {
    Instance candidate = instances.instance(i);
    Instance yInstance = null;
    //Find nearest neighbor
    for(int j=0;j<res.numInstances();j++)
    {
    Instance conceptDescription = res.instance(j);

    /** see implementation below <== here is the
    problem!!!!!!!!!!!**/
    if(!isAcceptable(conceptDescription))
    continue;
    if (!conceptDescription.classIsMissing())
    {
    distance = distance(candidate, conceptDescription);
    if (distance < minDistance)
    {
    minDistance = distance;
    classValue = conceptDescription.classValue();
    yInstance = conceptDescription;
    }
    }
    }
    if (yInstance!=null)
    {
    if(candidate.classValue()!=classValue&&classValue!=Double.NaN)
    {
    res.add(candidate);
    addFailureSuccessRate(yInstance);
    }
    else
    {
    addSuccessSuccessRate(yInstance);
    }
    }

    for(int j=0;j<res.numInstances();j++)
    {
    Instance conceptDescription = res.instance(j);
    if(isRejected(conceptDescription))
    {
    res.delete(j);
    successRate.remove(conceptDescription);
    }
    }
    }
    return res;
    }

    /*=======================calculateAprior===================================*/
    /**
    * calculateAprior
    *
    * @param instances
    * @return double array of aPriory
    */
    private void calculateAprior(Instances instances) {

    this.aPriori = new
    Hashtable<Instance,Double>(instances.numInstances());

    /** count classes*/
    Map<Double,Double> classCounter = new
    HashMap<Double,Double>(m_Train.numClasses());
    for(Enumeration enumeration =
    instances.enumerateInstances();enumeration.hasMoreElements();)
    {
    Instance ins = (Instance)enumeration.nextElement();
    if (classCounter.containsKey(ins.classValue()))
    {
    classCounter.put(ins.classValue(), new
    Double(classCounter.get(ins.classValue())+ 1));
    }
    else
    {
    classCounter.put(ins.classValue(), new Double(1));
    }
    }

    /** Update instances a priori*/
    for(Enumeration enumeration =
    instances.enumerateInstances();enumeration.hasMoreElements();)
    {
    Instance ins = (Instance)enumeration.nextElement();
    aPriori.put(ins,
    (double)classCounter.get(ins.classValue())
    /instances.numInstances());
    }
    }



    /*=========================isAcceptable==================================*/
    /**
    * is the Instance acceptable
    * @param j
    * @return
    */
    private boolean isAcceptable(Instance instance) {
    int [] inf = successRate.get(instance);
    double rate = (double)inf[1]/inf[0];

    /* here is the problem!!!!!!!!!!! aPriori.get(instance)
    is null!!!!*/

    return (rate-aPriori.get(instance)>ACCEPTENCE);
    }
     
    Mize-ze, Dec 31, 2006
    #1
    1. Advertising

  2. Mize-ze

    Mize-ze Guest

    Here is the full code just in case ....
    --------------------------------------------------------
    /*
    * 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.
    */

    /*
    * IB1.java
    * Copyright (C) 1999 Stuart Inglis,Len Trigg,Eibe Frank
    *
    */

    package weka.classifiers.lazy;

    import weka.classifiers.Classifier;
    import weka.classifiers.Evaluation;
    import weka.classifiers.UpdateableClassifier;
    import java.io.*;
    import java.util.*;

    import weka.core.*;


    /**
    * IB3-type classifier.
    *
    * @author Zahy
    */
    public class IB3 extends Classifier implements UpdateableClassifier {

    /** The training instances used for classification. */
    private Instances m_Train;

    /** The minimum values for numeric attributes. */
    private double [] m_MinArray;

    /** The A Priori Statistics according to which to use the Training
    set*/
    private Map<Instance,Double> aPriori;

    private static final double ACCEPTENCE = 0.05;
    private static final double REJECTION = 0.12;

    Map<Instance,int[]> successRate;

    /** The maximum values for numeric attributes. */
    private double [] m_MaxArray;

    /**
    * Returns a string describing classifier
    * @return a description suitable for
    * displaying in the explorer/experimenter gui
    */
    public String globalInfo() {


    return "Nearest-neighbour classifier. IB3";
    }

    /**
    * Generates the classifier.
    *
    * @param instances set of instances serving as training data
    * @exception Exception if the classifier has not been generated
    successfully
    */
    public void buildClassifier(Instances instances) throws Exception {

    if (instances.classAttribute().isNumeric()) {
    throw new Exception("IB3: Class is numeric!");
    }
    if (instances.checkForStringAttributes()) {
    throw new UnsupportedAttributeTypeException("IB3: Cannot handle
    string attributes!");
    }
    // Throw away training instances with missing class
    instances.deleteWithMissingClass();
    m_Train = new Instances(instances, 0,1);
    m_Train = buildIB3TrainingSet(instances);
    m_Train.deleteWithMissingClass();



    m_MinArray = new double [m_Train.numAttributes()];
    m_MaxArray = new double [m_Train.numAttributes()];
    for (int i = 0; i < m_Train.numAttributes(); i++) {
    m_MinArray = m_MaxArray = Double.NaN;
    }
    Enumeration enu = m_Train.enumerateInstances();
    while (enu.hasMoreElements()) {
    updateMinMax((Instance) enu.nextElement());
    }
    }

    private Instances buildIB3TrainingSet(Instances instances) {

    calculateAprior(instances);
    double distance
    =0,minDistance=Double.MAX_VALUE,classValue=Double.NaN;

    /*** Sucess rate*/
    successRate = new HashMap<Instance,int[]>();

    Instances res = new Instances(instances,0,1);
    this.addSuccessSuccessRate(res.firstInstance());
    //Iterate on original
    for(int i=0;i<instances.numInstances();i++)
    {
    Instance candidate = instances.instance(i);
    Instance yInstance = null;
    //Find nearest neighbor
    for(int j=0;j<res.numInstances();j++)
    {
    Instance conceptDescription = res.instance(j);
    if(!isAcceptable(conceptDescription))
    continue;
    if (!conceptDescription.classIsMissing())
    {
    distance = distance(candidate, conceptDescription);
    if (distance < minDistance)
    {
    minDistance = distance;
    classValue = conceptDescription.classValue();
    yInstance = conceptDescription;
    }
    }
    }
    if (yInstance!=null)
    {
    if(candidate.classValue()!=classValue&&classValue!=Double.NaN)
    {
    res.add(candidate);
    addFailureSuccessRate(yInstance);
    }
    else
    {
    addSuccessSuccessRate(yInstance);
    }
    }

    for(int j=0;j<res.numInstances();j++)
    {
    Instance conceptDescription = res.instance(j);
    if(isRejected(conceptDescription))
    {
    res.delete(j);
    successRate.remove(conceptDescription);
    }
    }
    }
    return res;
    }

    private void addSuccessSuccessRate(Instance instance) {
    if(!successRate.containsKey(instance))
    {
    successRate.put(instance, new int[]{1,1});
    }
    else
    {
    successRate.put(instance, new int[]
    {successRate.get(instance)[0]+1,
    successRate.get(instance)[1]+1});
    }
    }

    private void addFailureSuccessRate(Instance instance) {
    if(!successRate.containsKey(instance))
    {
    successRate.put(instance, new int[]{1,0});
    }
    else
    {
    successRate.put(instance, new int[]
    {successRate.get(instance)[0]+1,
    successRate.get(instance)[1]});
    }
    }

    /**
    * Is the instance rejected
    * @param instanceIndex
    * @return
    */
    private boolean isRejected(Instance instance) {
    int [] inf = successRate.get(instance);
    double rate = (double)inf[1]/inf[0];
    return (aPriori.get(instance)-rate<REJECTION);
    }

    /**
    * is the Instance acceptable
    * @param j
    * @return
    */
    private boolean isAcceptable(Instance instance) {
    int [] inf = successRate.get(instance);
    double rate = (double)inf[1]/inf[0];
    return (rate-aPriori.get(instance)>ACCEPTENCE);
    }

    /**
    *
    * @param instances
    * @return double array of aPriory
    */
    private void calculateAprior(Instances instances) {

    this.aPriori = new
    Hashtable<Instance,Double>(instances.numInstances());

    /** count classes*/
    Map<Double,Double> classCounter = new
    HashMap<Double,Double>(m_Train.numClasses());
    for(Enumeration enumeration =
    instances.enumerateInstances();enumeration.hasMoreElements();)
    {
    Instance ins = (Instance)enumeration.nextElement();
    if (classCounter.containsKey(ins.classValue()))
    {
    classCounter.put(ins.classValue(), new
    Double(classCounter.get(ins.classValue())+ 1));
    }
    else
    {
    classCounter.put(ins.classValue(), new Double(1));
    }
    }

    /** Update instances a priori*/
    for(Enumeration enumeration =
    instances.enumerateInstances();enumeration.hasMoreElements();)
    {
    Instance ins = (Instance)enumeration.nextElement();
    aPriori.put(ins,
    (double)classCounter.get(ins.classValue())
    /instances.numInstances());
    }
    }

    /**
    * Updates the classifier.
    *
    * @param instance the instance to be put into the classifier
    * @exception Exception if the instance could not be included
    successfully
    */
    public void updateClassifier(Instance instance) throws Exception {

    if (m_Train.equalHeaders(instance.dataset()) == false) {
    throw new Exception("Incompatible instance types");
    }
    if (instance.classIsMissing()) {
    return;
    }
    m_Train.add(instance);
    updateMinMax(instance);
    }

    /**
    * Classifies the given test instance.
    *
    * @param instance the instance to be classified
    * @return the predicted class for the instance
    * @exception Exception if the instance can't be classified
    */
    public double classifyInstance(Instance instance) throws Exception {

    if (m_Train.numInstances() == 0) {
    throw new Exception("No training instances!");
    }
    double distance, minDistance = Double.MAX_VALUE, classValue = 0;
    updateMinMax(instance);
    Enumeration enu = m_Train.enumerateInstances();
    while (enu.hasMoreElements())
    {
    Instance trainInstance = (Instance) enu.nextElement();
    if (!trainInstance.classIsMissing())
    {
    distance = distance(instance, trainInstance);
    if (distance < minDistance)
    {
    minDistance = distance;
    classValue = trainInstance.classValue();
    }
    }
    }
    return classValue;
    }

    /**
    * Returns a description of this classifier.
    *
    * @return a description of this classifier as a string.
    */
    public String toString() {

    return ("IB3 classifier");
    }

    /**
    * Calculates the distance between two instances
    *
    * @param first the first instance
    * @param second the second instance
    * @return the distance between the two given instances
    */
    private double distance(Instance first, Instance second) {

    double diff, distance = 0;

    for(int i = 0; i < m_Train.numAttributes(); i++) {
    if (i == m_Train.classIndex()) {
    continue;
    }
    if (m_Train.attribute(i).isNominal()) {

    // If attribute is nominal
    if (first.isMissing(i) || second.isMissing(i) ||
    ((int)first.value(i) != (int)second.value(i))) {
    distance += 1;
    }
    } else {

    // If attribute is numeric
    if (first.isMissing(i) || second.isMissing(i)){
    if (first.isMissing(i) && second.isMissing(i)) {
    diff = 1;
    } else {
    if (second.isMissing(i)) {
    diff = norm(first.value(i), i);
    } else {
    diff = norm(second.value(i), i);
    }
    if (diff < 0.5) {
    diff = 1.0 - diff;
    }
    }
    } else {
    diff = norm(first.value(i), i) - norm(second.value(i), i);
    }
    distance += diff * diff;
    }
    }

    return distance;
    }

    /**
    * Normalizes a given value of a numeric attribute.
    *
    * @param x the value to be normalized
    * @param i the attribute's index
    */
    private double norm(double x,int i) {

    if (Double.isNaN(m_MinArray)
    || Utils.eq(m_MaxArray, m_MinArray)) {
    return 0;
    } else {
    return (x - m_MinArray) / (m_MaxArray - m_MinArray);
    }
    }

    /**
    * Updates the minimum and maximum values for all the attributes
    * based on a new instance.
    *
    * @param instance the new instance
    */
    private void updateMinMax(Instance instance) {

    for (int j = 0;j < m_Train.numAttributes(); j++) {
    if ((m_Train.attribute(j).isNumeric()) &&
    (!instance.isMissing(j))) {
    if (Double.isNaN(m_MinArray[j])) {
    m_MinArray[j] = instance.value(j);
    m_MaxArray[j] = instance.value(j);
    } else {
    if (instance.value(j) < m_MinArray[j]) {
    m_MinArray[j] = instance.value(j);
    } else {
    if (instance.value(j) > m_MaxArray[j]) {
    m_MaxArray[j] = instance.value(j);
    }
    }
    }
    }
    }
    }

    /**
    * Main method for testing this class.
    *
    * @param argv should contain command line arguments for evaluation
    * (see Evaluation).
    */
    public static void main(String [] argv) {

    try {
    System.out.println(Evaluation.evaluateModel(new IB3(), argv));
    } catch (Exception e) {
    System.err.println(e.getMessage());
    }
    }
    }
     
    Mize-ze, Dec 31, 2006
    #2
    1. Advertising

  3. Mize-ze

    Daniel Pitts Guest

    Mize-ze wrote:
    > Here is the full code just in case ....

    That is way too much for me to read through and parse.

    Try writing an sscce <http://physci.org/codes/sscce/>, and then perhaps
    we can help you...

    Without looking at your source code. If you wrote the class that
    defines the Key of the map, make sure that equals and hashCode are both
    implemented and consistent. Basically, if a.equals(b) == true, then
    a.hashCode() == b.hashCode() must be true.

    Hope this helps.
    Daniel.
     
    Daniel Pitts, Dec 31, 2006
    #3
  4. Mize-ze

    Paul Tomblin Guest

    In a previous article, "Mize-ze" <> said:
    >Hello,
    >I am inserting a key and a object into a Map. later in the code I try
    >to retrieve the object by calling
    >Map.get(key) and I get a null.
    >I can't see where is my problem...


    I only had to read this far to guess what the problem is - you haven't
    implemented hashCode on your key class, or if you have, you haven't
    implemented it properly, and you're using HashMap.

    I know this, because I made the same mistake (AGAIN) a few weeks ago. I
    changed something from TreeSet to HashSet and things weren't working the
    way I expected.

    --
    Paul Tomblin <> http://blog.xcski.com/
    It might not be practical, it might not be a good idea, but it could work.
    Sort of like Windows.
    -- berry
     
    Paul Tomblin, Dec 31, 2006
    #4
  5. On 31.12.2006 01:55, Daniel Pitts wrote:
    > Mize-ze wrote:
    >> Here is the full code just in case ....

    > That is way too much for me to read through and parse.
    >
    > Try writing an sscce <http://physci.org/codes/sscce/>, and then perhaps
    > we can help you...
    >
    > Without looking at your source code. If you wrote the class that
    > defines the Key of the map, make sure that equals and hashCode are both
    > implemented and consistent. Basically, if a.equals(b) == true, then
    > a.hashCode() == b.hashCode() must be true.


    Also, if the Map is a TreeMap compareTo() must be implemented according
    to the contract or you must use a proper Comparator.

    robert
     
    Robert Klemme, Jan 1, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alan Silver
    Replies:
    2
    Views:
    6,725
    Alan Silver
    Jul 12, 2005
  2. vizlab
    Replies:
    3
    Views:
    4,221
    Michael Bar-Sinai
    Oct 17, 2007
  3. Replies:
    5
    Views:
    26,735
    Mike Schilling
    Mar 29, 2006
  4. Patrick Guio
    Replies:
    6
    Views:
    3,214
    chris
    Oct 20, 2004
  5. Col
    Replies:
    1
    Views:
    631
    peter koch
    Apr 21, 2006
Loading...

Share This Page