/// <summary> Creates a cost matrix that is a copy of another. /// /// </summary> /// <param name="toCopy">the matrix to copy. /// </param> public CostMatrix(CostMatrix toCopy):base(toCopy.size(), toCopy.size()) { for (int x = 0; x < toCopy.size(); x++) for (int y = 0; y < toCopy.size(); y++) setXmlElement(x, y, toCopy.getXmlElement(x, y)); }
/// <summary> Initializes all the counters for the evaluation and also takes a /// cost matrix as parameter. /// Use <code>useNoPriors()</code> if the dataset is the test set and you /// can't initialize with the priors from the training set via /// <code>setPriors(Instances)</code>. /// /// </summary> /// <param name="data"> set of training instances, to get some header /// information and prior class distribution information /// </param> /// <param name="costMatrix"> the cost matrix---if null, default costs will be used /// </param> /// <throws> Exception if cost matrix is not compatible with </throws> /// <summary> data, the class is not defined or the class is numeric /// </summary> /// <seealso cref="useNoPriors()"> /// </seealso> /// <seealso cref="setPriors(Instances)"> /// </seealso> public Evaluation(Instances data, CostMatrix costMatrix) { m_NumClasses = data.numClasses(); m_NumFolds = 1; m_ClassIsNominal = data.classAttribute().Nominal; if (m_ClassIsNominal) { double[][] tmpArray = new double[m_NumClasses][]; for (int i = 0; i < m_NumClasses; i++) { tmpArray[i] = new double[m_NumClasses]; } m_ConfusionMatrix = tmpArray; m_ClassNames = new System.String[m_NumClasses]; for (int i = 0; i < m_NumClasses; i++) { m_ClassNames[i] = data.classAttribute().value_Renamed(i); } } m_CostMatrix = costMatrix; if (m_CostMatrix != null) { if (!m_ClassIsNominal) { throw new System.Exception("Class has to be nominal if cost matrix " + "given!"); } if (m_CostMatrix.size() != m_NumClasses) { throw new System.Exception("Cost matrix not compatible with data!"); } } m_ClassPriors = new double[m_NumClasses]; Priors = data; m_MarginCounts = new double[k_MarginResolution + 1]; }
/// <summary> Applies the cost matrix to a set of instances. If a random number generator is /// supplied the instances will be resampled, otherwise they will be rewighted. /// Adapted from code once sitting in Instances.java /// /// </summary> /// <param name="data">the instances to reweight. /// </param> /// <param name="random">a random number generator for resampling, if null then instances are /// rewighted. /// </param> /// <returns> a new dataset reflecting the cost of misclassification. /// </returns> /// <exception cref="Exception">if the data has no class or the matrix in inappropriate. /// </exception> public virtual Instances applyCostMatrix(Instances data, System.Random random) { double sumOfWeightFactors = 0, sumOfMissClassWeights, sumOfWeights; double[] weightOfInstancesInClass, weightFactor, weightOfInstances; Instances newData; if (data.classIndex() < 0) { throw new System.Exception("Class index is not set!"); } if (size() != data.numClasses()) { throw new System.Exception("Misclassification cost matrix has " + "wrong format!"); } weightFactor = new double[data.numClasses()]; weightOfInstancesInClass = new double[data.numClasses()]; for (int j = 0; j < data.numInstances(); j++) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" weightOfInstancesInClass[(int) data.instance(j).classValue()] += data.instance(j).weight(); } sumOfWeights = Utils.sum(weightOfInstancesInClass); // normalize the matrix if not already for (int i = 0; i < size(); i++) if (!Utils.eq(getXmlElement(i, i), 0)) { CostMatrix normMatrix = new CostMatrix(this); normMatrix.normalize(); return normMatrix.applyCostMatrix(data, random); } for (int i = 0; i < data.numClasses(); i++) { // Using Kai Ming Ting's formula for deriving weights for // the classes and Breiman's heuristic for multiclass // problems. sumOfMissClassWeights = 0; for (int j = 0; j < data.numClasses(); j++) { if (Utils.sm(getXmlElement(i, j), 0)) { throw new System.Exception("Neg. weights in misclassification " + "cost matrix!"); } sumOfMissClassWeights += getXmlElement(i, j); } weightFactor[i] = sumOfMissClassWeights * sumOfWeights; sumOfWeightFactors += sumOfMissClassWeights * weightOfInstancesInClass[i]; } for (int i = 0; i < data.numClasses(); i++) { weightFactor[i] /= sumOfWeightFactors; } // Store new weights weightOfInstances = new double[data.numInstances()]; for (int i = 0; i < data.numInstances(); i++) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" weightOfInstances[i] = data.instance(i).weight() * weightFactor[(int) data.instance(i).classValue()]; } // Change instances weight or do resampling if (random != null) { return data.resampleWithWeights(random, weightOfInstances); } else { Instances instances = new Instances(data); for (int i = 0; i < data.numInstances(); i++) { instances.instance(i).Weight = weightOfInstances[i]; } return instances; } }
/// <summary> Attempts to load a cost matrix. /// /// </summary> /// <param name="costFileName">the filename of the cost matrix /// </param> /// <param name="numClasses">the number of classes that should be in the cost matrix /// (only used if the cost file is in old format). /// </param> /// <returns> a <code>CostMatrix</code> value, or null if costFileName is empty /// </returns> /// <throws> Exception if an error occurs. </throws> protected internal static CostMatrix handleCostOption(System.String costFileName, int numClasses) { if ((costFileName != null) && (costFileName.Length != 0)) { System.Console.Out.WriteLine("NOTE: The behaviour of the -m option has changed between WEKA 3.0" + " and WEKA 3.1. -m now carries out cost-sensitive *evaluation*" + " only. For cost-sensitive *prediction*, use one of the" + " cost-sensitive metaschemes such as" + " weka.classifiers.meta.CostSensitiveClassifier or" + " weka.classifiers.meta.MetaCost"); //UPGRADE_ISSUE: Class hierarchy differences between 'java.io.Reader' and 'System.IO.StreamReader' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1186'" System.IO.StreamReader costReader = null; try { //UPGRADE_TODO: The differences in the expected value of parameters for constructor 'java.io.BufferedReader.BufferedReader' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'" //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'" //UPGRADE_TODO: Constructor 'java.io.FileReader.FileReader' was converted to 'System.IO.StreamReader' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" costReader = new System.IO.StreamReader(new System.IO.StreamReader(costFileName, System.Text.Encoding.Default).BaseStream, new System.IO.StreamReader(costFileName, System.Text.Encoding.Default).CurrentEncoding); } catch (System.Exception e) { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.getMessage' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" throw new System.Exception("Can't open file " + e.Message + '.'); } try { // First try as a proper cost matrix format return new CostMatrix(costReader); } catch (System.Exception ex) { try { // Now try as the poxy old format :-) //System.err.println("Attempting to read old format cost file"); try { costReader.Close(); // Close the old one //UPGRADE_TODO: The differences in the expected value of parameters for constructor 'java.io.BufferedReader.BufferedReader' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'" //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'" //UPGRADE_TODO: Constructor 'java.io.FileReader.FileReader' was converted to 'System.IO.StreamReader' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073'" costReader = new System.IO.StreamReader(new System.IO.StreamReader(costFileName, System.Text.Encoding.Default).BaseStream, new System.IO.StreamReader(costFileName, System.Text.Encoding.Default).CurrentEncoding); } catch (System.Exception e) { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.getMessage' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" throw new System.Exception("Can't open file " + e.Message + '.'); } CostMatrix costMatrix = new CostMatrix(numClasses); //System.err.println("Created default cost matrix"); costMatrix.readOldFormat(costReader); return costMatrix; //System.err.println("Read old format"); } catch (System.Exception e2) { // re-throw the original exception //System.err.println("Re-throwing original exception"); throw ex; } } } else { return null; } }