Java tutorial
/* * Copyright (C) 2016 jcastro * * 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package delfos.group.results.groupevaluationmeasures.precisionrecall; import delfos.ERROR_CODES; import delfos.common.exceptions.dataset.users.UserNotFound; import delfos.dataset.basic.loader.types.DatasetLoader; import delfos.dataset.basic.rating.Rating; import delfos.dataset.basic.rating.RelevanceCriteria; import delfos.group.groupsofusers.GroupOfUsers; import delfos.group.results.groupevaluationmeasures.GroupEvaluationMeasure; import delfos.group.results.groupevaluationmeasures.GroupEvaluationMeasureResult; import delfos.group.results.grouprecomendationresults.GroupRecommenderSystemResult; import delfos.io.xml.evaluationmeasures.confusionmatricescurve.ConfusionMatricesCurveXML; import delfos.results.evaluationmeasures.confusionmatrix.ConfusionMatricesCurve; import delfos.results.evaluationmeasures.confusionmatrix.ConfusionMatrix; import delfos.rs.recommendation.Recommendation; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.jdom2.Element; /** * Medida de evaluacin para sistemas de recomendacin a grupos que calcula la precisin y recall a lo largo de todos * los tamao de recomendacin al grupo. * * @author jcastro-inf ( https://github.com/jcastro-inf ) */ public class PRSpace_EachMember extends GroupEvaluationMeasure { /** * Nombre del elemento que almacena la informacin de un grupo de usuarios */ public static final String GROUP_OF_USERS_ELEMENT = "GroupOfUsers"; /** * Nombre del atributo que almacena la lista de usuarios que forman el grupo */ public static final String USERS_ATTRIBUTE = "users"; @Override public boolean usesRatingPrediction() { return false; } @Override public GroupEvaluationMeasureResult getMeasureResult(GroupRecommenderSystemResult groupRecommenderSystemResult, DatasetLoader<? extends Rating> originalDatasetLoader, RelevanceCriteria relevanceCriteria, DatasetLoader<? extends Rating> trainingDatasetLoader, DatasetLoader<? extends Rating> testDatasetLoader) { Map<GroupOfUsers, ConfusionMatricesCurve> groupsCurves = new TreeMap<>(); Element measureElement = new Element(getName()); for (GroupOfUsers group : groupRecommenderSystemResult.getGroupsOfUsers()) { Collection<Recommendation> groupRecommendations = groupRecommenderSystemResult.getGroupOutput(group) .getRecommendations().getRecommendations(); Set<Integer> recommendedItems = new TreeSet<>(); for (Recommendation r : groupRecommendations) { recommendedItems.add(r.getIdItem()); } Element groupElement = new Element(GROUP_OF_USERS_ELEMENT); groupElement.setAttribute(USERS_ATTRIBUTE, group.getIdMembers().toString()); List<ConfusionMatrix> matrices = new ArrayList<>(); /** * Estas variables se utilizan en la generacin de la curva para el grupo, pero se pueden inicializar en el * clculo de la curva de cada usuario */ int truePositive_group = 0; int falseNegative_group = 0; int falsePositive_group = 0; int trueNegative_group = 0; /** * Almacena una lista de conjuntos. Cada elemento de la lista representa cada un conjunto con un booleano si * al usuario est satisfecho con esa recomendacin. */ List<Set<Boolean>> relevanteParaUser = new ArrayList<>(group.size()); for (int i = 0; i < groupRecommendations.size(); i++) { relevanteParaUser.add(new TreeSet<>()); } Map<Integer, ConfusionMatricesCurve> matricesParaCadaMiembro = new TreeMap<>(); for (int idUser : group.getIdMembers()) { Element userElement = new Element("User"); userElement.setAttribute("idUser", Integer.toString(idUser)); int truePositive = 0; int falseNegative = 0; int falsePositive = 0; int trueNegative = 0; Map<Integer, ? extends Rating> userRatings = null; try { userRatings = testDatasetLoader.getRatingsDataset().getUserRatingsRated(idUser); } catch (UserNotFound ex) { ERROR_CODES.USER_NOT_FOUND.exit(ex); throw new IllegalArgumentException(ex); } for (int idItem : userRatings.keySet()) { if (recommendedItems.contains(idItem) && relevanceCriteria.isRelevant(userRatings.get(idItem).getRatingValue())) { falseNegative++; } else { trueNegative++; } } falseNegative_group += falseNegative; trueNegative_group += trueNegative; int i = 0; for (Recommendation r : groupRecommendations) { int idItem = r.getIdItem(); if (!userRatings.containsKey(idItem)) { continue; } if (relevanceCriteria.isRelevant(userRatings.get(idItem).getRatingValue())) { relevanteParaUser.get(i).add(true); truePositive++; falseNegative--; } else { relevanteParaUser.get(i).add(false); falsePositive++; trueNegative--; } matrices.add(new ConfusionMatrix(falsePositive, falseNegative, truePositive, trueNegative)); i++; } matricesParaCadaMiembro.put(idUser, new ConfusionMatricesCurve(matrices.toArray(new ConfusionMatrix[1]))); //Aado la curva del usuario a los resultados del grupo userElement.addContent(ConfusionMatricesCurveXML.getElement(matricesParaCadaMiembro.get(idUser))); groupElement.addContent(userElement); } List<ConfusionMatrix> groupMatrices = new ArrayList<>(); //Ahora se calcula la curva para el grupo for (int i = 0; i < relevanteParaUser.size(); i++) { Set<Boolean> set = relevanteParaUser.get(i); for (boolean b : set) { if (b) { relevanteParaUser.get(i).add(true); truePositive_group++; falseNegative_group--; } else { relevanteParaUser.get(i).add(false); falsePositive_group++; trueNegative_group--; } } double precision; double recall; if (((double) truePositive_group + (double) falsePositive_group) == 0) { precision = 0; } else { precision = (double) truePositive_group / ((double) truePositive_group + (double) falsePositive_group); } if (((double) truePositive_group + (double) falseNegative_group) == 0) { recall = 0; } else { recall = (double) truePositive_group / ((double) truePositive_group + (double) falseNegative_group); } groupMatrices.add(new ConfusionMatrix(falsePositive_group, falseNegative_group, truePositive_group, trueNegative_group)); } groupsCurves.put(group, new ConfusionMatricesCurve(groupMatrices.toArray(new ConfusionMatrix[1]))); groupElement.addContent(ConfusionMatricesCurveXML.getElement(groupsCurves.get(group))); measureElement.addContent(groupElement); } ConfusionMatricesCurve curvaTotal = ConfusionMatricesCurve.mergeCurves(groupsCurves.values()); measureElement.addContent(ConfusionMatricesCurveXML.getElement(curvaTotal)); return new GroupEvaluationMeasureResult(this, curvaTotal.getAreaUnderROC()); } }