📄 weightedhamming.javaold
字号:
/* * 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. *//* * WeightedHamming.java * Copyright (C) 2001 Sugato Basu * */package weka.core.metrics;import weka.core.*;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.Vector;/** * WeightedHamming class * * Implements weighted euclidean distance metric * * @author Mikhail Bilenko (mbilenko@cs.utexas.edu) * @version $Revision: 1.4 $ */public class WeightedHamming extends LearnableMetric implements OptionHandler { /** We can have different ways of converting from distance to similarity */ public static final int CONVERSION_LAPLACIAN = 1; public static final int CONVERSION_UNIT = 2; public static final int CONVERSION_EXPONENTIAL = 4; public static final Tag[] TAGS_CONVERSION = { new Tag(CONVERSION_UNIT, "similarity = 1-distance"), new Tag(CONVERSION_LAPLACIAN, "similarity=1/(1+distance)"), new Tag(CONVERSION_EXPONENTIAL, "similarity=exp(-distance)") }; /** The method of converting, by default laplacian */ protected int m_conversionType = CONVERSION_LAPLACIAN; /** A metric learner responsible for training the parameters of the metric */ // protected MetricLearner m_metricLearner = new ClassifierMetricLearner("weka.classifiers.functions.SMO"); protected MetricLearner m_metricLearner = null; // protected MetricLearner m_metricLearner = new ClassifierMetricLearner("weka.classifiers.sparse.SVMlight"); // protected String m_metricLearnerName = new String("ClassifierMetricLearner"); protected String m_metricLearnerName = null; /** * Create a new metric. * @param numAttributes the number of attributes that the metric will work on */ public WeightedHamming(int numAttributes) throws Exception { buildMetric(numAttributes); } /** Create a default new metric */ public WeightedHamming() { } /** * Creates a new metric which takes specified attributes. * * @param _attrIdxs An array containing attribute indeces that will * be used in the metric */ public WeightedHamming(int[] _attrIdxs) throws Exception { setAttrIdxs(_attrIdxs); buildMetric(_attrIdxs.length); } /** * Reset all values that have been learned */ public void resetMetric() throws Exception { m_trained = false; if (m_attrWeights != null) { for (int i = 0; i < m_attrWeights.length; i++) { m_attrWeights[i] = 1; } } } /** * Generates a new Metric. Has to initialize all fields of the metric * with default values. * * @param numAttributes the number of attributes that the metric will work on * @exception Exception if the distance metric has not been * generated successfully. */ public void buildMetric(int numAttributes) throws Exception { m_numAttributes = numAttributes; m_attrWeights = new double[numAttributes]; for (int i = 0; i < numAttributes; i++) { m_attrWeights[i] = 1; } } /** * Generates a new Metric. Has to initialize all fields of the metric * with default values * * @param options an array of options suitable for passing to setOptions. * May be null. * @exception Exception if the distance metric has not been * generated successfully. */ public void buildMetric(int numAttributes, String[] options) throws Exception { buildMetric(numAttributes); } /** * Create a new metric for operating on specified instances * @param data instances that the metric will be used on */ public void buildMetric(Instances data) throws Exception { m_classIndex = data.classIndex(); m_numAttributes = data.numAttributes(); if (m_classIndex != m_numAttributes-1 && m_classIndex != -1) { throw new Exception("Class attribute (" + m_classIndex + ") should be the last attribute!!!"); } if (m_classIndex != -1) { m_numAttributes--; } System.out.println("About to build metric with " + m_numAttributes + " attributes, trainable=" + m_trainable); buildMetric(m_numAttributes); if (m_trainable) { learnMetric(data); } } /** * Returns a distance value between two instances. * @param instance1 First instance. * @param instance2 Second instance. * @exception Exception if distance could not be estimated. */ public double distance(Instance instance1, Instance instance2) throws Exception { // either pass the computation to the external classifier, or do the work yourself if (m_trainable && m_external && m_trained) { return m_metricLearner.getDistance(instance1, instance2); } else { return distanceInternal(instance1, instance2); } } /** * Returns a distance value between two instances. * @param instance1 First instance. * @param instance2 Second instance. * @exception Exception if distance could not be estimated. */ public double distanceInternal(Instance instance1, Instance instance2) throws Exception { if (instance1 instanceof SparseInstance && instance2 instanceof SparseInstance) { return distanceSparse((SparseInstance)instance1, (SparseInstance)instance2); } else if (instance1 instanceof SparseInstance) { return distanceSparseNonSparse((SparseInstance)instance1, instance2); } else if (instance2 instanceof SparseInstance) { return distanceSparseNonSparse((SparseInstance)instance2, instance1); } else { return distanceNonSparse(instance1, instance2); } } /** Returns a distance value between two sparse instances. * @param instance1 First sparse instance. * @param instance2 Second sparse instance. * @exception Exception if distance could not be estimated. */ public double distanceSparse(SparseInstance instance1, SparseInstance instance2) throws Exception { double distance = 0, value1, value2; SparseInstance inst1 = (SparseInstance) instance1; SparseInstance inst2 = (SparseInstance) instance2; // iterate through the attributes that are present in the first instance for (int i = 0; i < instance1.numValues(); i++) { Attribute attribute = instance1.attributeSparse(i); int attrIdx = attribute.index(); // Skip the class index if (attrIdx == m_classIndex) { continue; } value1 = instance1.value(attrIdx); // get the corresponding value of the second instance int idx2 = instance2.locateIndex(attrIdx); if (idx2 >=0 && attrIdx == instance2.index(idx2)) { value2 = instance2.value(attrIdx); } else { value2 = 0; } if (isBinary(value1) && isBinary(value2)) { distance += m_attrWeights[attrIdx] * Math.abs(value1 - value2); } } // Go through the attributes that are present in the second instance, but not first instance for (int i = 0; i < instance2.numValues(); i++) { Attribute attribute = instance2.attributeSparse(i); int attrIdx = attribute.index(); // Skip the class index if (attrIdx == m_classIndex) { continue; } // only include attributes that are not present in first instance int idx1 = instance1.locateIndex(attrIdx); if (idx1 < 0 || attrIdx != instance1.index(idx1)) { value2 = instance2.value(attrIdx); if (isBinary(value2)) { distance += m_attrWeights[attrIdx] * value2; } } } return distance; } /** returns true of argument is 0 or 1 */ protected boolean isBinary(double val) { return (val == 0 || val == 1); } /** Returns a distance value between a non-sparse instance and a sparse instance * @param instance1 sparse instance. * @param instance2 sparse instance. * @exception Exception if distance could not be estimated. */ public double distanceSparseNonSparse(SparseInstance instance1, Instance instance2) throws Exception { double diff, distance = 0; double [] values2 = instance2.toDoubleArray(); for (int i = 0; i < values2.length; i++) { // Skip the class index if (i == m_classIndex) { continue; } if (isBinary(values2[i]) && isBinary(instance1.value(i))) { diff = Math.abs(values2[i] - instance1.value(i)); distance += m_attrWeights[i] * diff; } } return distance; }; /** Returns a distance value between non-sparse instances without using the weights * @param instance1 non-sparse instance. * @param instance2 non-sparse instance. * @exception Exception if distance could not be estimated. */ public double distanceNonSparse(Instance instance1, Instance instance2) throws Exception { double value1, value2, diff, distance = 0; double [] values1 = instance1.toDoubleArray(); double [] values2 = instance2.toDoubleArray(); // Go through all attributes for (int i = 0; i < values1.length; i++) { // Skip the class index if (i == m_classIndex) { continue; } if (isBinary(values1[i]) && isBinary(values2[i])) { diff = Math.abs(values1[i] - values2[i]); distance += m_attrWeights[i] * diff; } } return distance; }; /** * Returns a distance value between two instances. * @param instance1 First instance. * @param instance2 Second instance. * @exception Exception if distance could not be estimated. */ public double distanceNonWeighted(Instance instance1, Instance instance2) throws Exception { if (instance1 instanceof SparseInstance && instance2 instanceof SparseInstance) { return distanceSparseNonWeighted((SparseInstance)instance1, (SparseInstance)instance2); } else if (instance1 instanceof SparseInstance) { return distanceSparseNonSparseNonWeighted((SparseInstance)instance1, instance2); } else if (instance2 instanceof SparseInstance) { return distanceSparseNonSparseNonWeighted((SparseInstance)instance2, instance1); } else { return distanceNonSparseNonWeighted(instance1, instance2); } } /** Returns a distance value between two sparse instances without using the weights. * @param instance1 First sparse instance. * @param instance2 Second sparse instance. * @exception Exception if distance could not be estimated. */ public double distanceSparseNonWeighted(SparseInstance instance1, SparseInstance instance2) throws Exception { double distance = 0, value1, value2; SparseInstance inst1 = (SparseInstance) instance1; SparseInstance inst2 = (SparseInstance) instance2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -