/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator.learner.meta; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.rapidminer.example.Attribute; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.set.Condition; import com.rapidminer.example.set.ConditionCreationException; import com.rapidminer.example.set.ConditionedExampleSet; import com.rapidminer.example.table.AttributeFactory; import com.rapidminer.operator.Model; import com.rapidminer.operator.OperatorCapability; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeList; import com.rapidminer.parameter.ParameterTypeString; import com.rapidminer.tools.RandomGenerator; /** */ @Deprecated public class HierarchicalLearner extends AbstractMetaLearner { public static final String PARAMETER_HIERARCHY = "hierarchy"; public static final String PARAMETER_PARENT_CLASS = "parent_class"; public static final String PARAMETER_CHILD_CLASS = "child_class"; public HierarchicalLearner(OperatorDescription description) { super(description); } public Model learn(ExampleSet inputSet) throws OperatorException { Attribute classLabel = inputSet.getAttributes().getLabel(); if (classLabel.getMapping().size() == 2) { return applyInnerLearner(inputSet); } // create model hierarchy / tree List<String[]> hierarchyEntries = getParameterList(PARAMETER_HIERARCHY); Map<String, HierarchicalModel.Node> nodeMap = new HashMap<String, HierarchicalModel.Node>(); Set<HierarchicalModel.Node> innerNodes = new HashSet<HierarchicalModel.Node>(); for (String[] entries : hierarchyEntries) { String parentClass = entries[0]; String childClass = entries[1]; HierarchicalModel.Node parentNode = nodeMap.get(parentClass); if (parentNode == null) { parentNode = new HierarchicalModel.Node(parentClass); } HierarchicalModel.Node childNode = nodeMap.get(childClass); if (childNode == null) { childNode = new HierarchicalModel.Node(childClass); } parentNode.addChild(childNode); nodeMap.put(parentClass, parentNode); nodeMap.put(childClass, childNode); innerNodes.add(childNode); } HierarchicalModel.Node root = new HierarchicalModel.Node("_ROOT_"); for (HierarchicalModel.Node node : nodeMap.values()) { if (!innerNodes.contains(node)) { root.addChild(node); } } try { // compute model (by DFS) computeModel(root, inputSet, classLabel); } catch (ConditionCreationException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new HierarchicalModel(inputSet, root); } private void computeModel(HierarchicalModel.Node node, ExampleSet eSet, Attribute originalLabel) throws ConditionCreationException, OperatorException { // create child->parent label replacement map (by DFS) Map<String, String> classesMap = new HashMap<String, String>(); for (HierarchicalModel.Node child : node.getChildren()) { if (child.getChildrenClasses().size() > 0) { for (String childClass : child.getChildrenClasses()) { classesMap.put(childClass, child.getClassName()); } } else { classesMap.put(child.getClassName(), child.getClassName()); } } // create working label with parent class labels eSet.getAttributes().setSpecialAttribute(originalLabel, "label_original"); Attribute workingLabel = AttributeFactory.createAttribute(originalLabel.getName() + "_" + node.getClassName(), originalLabel.getValueType()); eSet.getExampleTable().addAttribute(workingLabel); eSet.getAttributes().addRegular(workingLabel); for (Example example : eSet) { double index = example.getValue(originalLabel); if (!Double.isNaN(index)) { String value = originalLabel.getMapping().mapIndex((int) index); String mapVl = classesMap.get(value); if (mapVl != null) { example.setValue(workingLabel, workingLabel.getMapping().mapString(mapVl)); } else { example.setValue(workingLabel, Double.NaN); } } else { example.setValue(workingLabel, Double.NaN); } } eSet.getAttributes().setLabel(workingLabel); Model model = applyInnerLearner(eSet); node.setModel(model); // compute models for child nodes for (HierarchicalModel.Node child : node.getChildren()) { if (child.getChildren().size() > 0) { Condition c = ConditionedExampleSet.createCondition(ConditionedExampleSet.KNOWN_CONDITION_NAMES[ConditionedExampleSet.CONDITION_ATTRIBUTE_VALUE_FILTER], eSet, workingLabel.getName() + "=" + child.getClassName()); ExampleSet trainingSet = new ConditionedExampleSet(eSet, c); computeModel(child, trainingSet, originalLabel); } } eSet.getAttributes().setLabel(originalLabel); eSet.getAttributes().remove(workingLabel); eSet.getExampleTable().removeAttribute(workingLabel); } @Override public boolean supportsCapability(OperatorCapability capability) { switch (capability) { case NUMERICAL_LABEL: case NO_LABEL: case UPDATABLE: case FORMULA_PROVIDER: return false; default: return true; } } @Override public List<ParameterType> getParameterTypes() { List<ParameterType> types = super.getParameterTypes(); types.add(new ParameterTypeList(PARAMETER_HIERARCHY, "The hierarchy...", new ParameterTypeString(PARAMETER_PARENT_CLASS, "The parent class.", false), new ParameterTypeString(PARAMETER_CHILD_CLASS, "The child class.", false))); types.addAll(RandomGenerator.getRandomGeneratorParameters(this)); return types; } }