<commit_before>package edu.berkeley.compbio.jlibsvm.multi;

import edu.berkeley.compbio.jlibsvm.SVM;
import edu.berkeley.compbio.jlibsvm.SvmProblem;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationProblem;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationProblemImpl;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationSVM;
import edu.berkeley.compbio.jlibsvm.binary.BinaryModel;
import edu.berkeley.compbio.jlibsvm.labelinverter.LabelInverter;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id$
 */
public class MultiClassificationSVM<L extends Comparable<L>, P> extends SVM<L, P, MultiClassProblem<L, P>>
	{
	private static final Logger logger = Logger.getLogger(MultiClassificationSVM.class);

	BinaryClassificationSVM<L, P> binarySvm;	//private Class labelClass;

	public MultiClassificationSVM(BinaryClassificationSVM<L, P> binarySvm, Class labelClass)
		{
		super(binarySvm.kernel, binarySvm.param);
		this.binarySvm = binarySvm;		//	this.labelClass = labelClass;
		}

	public String getSvmType()
		{
		return "multiclass " + binarySvm.getSvmType();
		}

	/*	@Override
   public Class getLabelClass()
	   {
	   return labelClass;
	   }*/


	public void setupQMatrix(SvmProblem<L, P> problem)
		{
		binarySvm.setupQMatrix(problem);
		qMatrix = binarySvm.qMatrix; // just for the sake of reporting later
		}


	public MultiClassModel<L, P> train(MultiClassProblem<L, P> problem)
		{
		int numLabels = problem.getLabels().size();

		MultiClassModel<L, P> model = new MultiClassModel<L, P>(kernel, param, numLabels);


		Map<L, Float> weights = prepareWeights(problem);

		/*
		if (param.multiclassMode != MultiClassModel.MulticlassMode.OneVsAllOnly)
			{
			// create and train one-class classifiers

			logger.info("Training one-class classifiers for " + numLabels + " labels");

			for (Map.Entry<L,Set<P>> entry : problem.getExamplesByLabel().entrySet())
				{
				Map<P, Float> subExamples = new HashMap<P, Float>(problem.getExamples().size());

				for (P point : entry.getValue())
					{
					subExamples.put(point, 1f);
					}

				OneClassProblem<L, P> subProblem =
						new OneClassProblemImpl<L, P>(subExamples, entry.getKey());

				model.putOneClassModel(entry.getKey(), oneClassSvm.train(subProblem));
				}
			}
*/
		if (param.oneVsAllMode != MultiClassModel.OneVsAllMode.None)
			{
			// create and train one vs all classifiers

			logger.info("Training one-vs-all classifiers for " + numLabels + " labels");
			int c = 0;
			LabelInverter<L> labelInverter = problem.getLabelInverter();
			for (L label : problem.getLabels())
				{
				Map<P, L> subExamples = new HashMap<P, L>(problem.getExamples().size());
				L notLabel = labelInverter.invert(label);

				Collection<Map.Entry<P, L>> entries = problem.getExamples().entrySet();
				if (param.falseClassSVlimit != 0)
					{
					// guarantee entries in random order if limiting the number of false examples
					List<Map.Entry<P, L>> entryList = new ArrayList<Map.Entry<P, L>>(entries);
					Collections.shuffle(entryList);
					entries = entryList;
					}

				int falseExamples = 0;
				for (Map.Entry<P, L> entry : entries)
					{
					if (entry.getValue().equals(label))
						{
						subExamples.put(entry.getKey(), label);
						}
					else if (param.falseClassSVlimit == 0 || falseExamples < param.falseClassSVlimit)
						{
						subExamples.put(entry.getKey(), notLabel);
						falseExamples++;
						}
					}

				BinaryClassificationProblem<L, P> subProblem =
						new BinaryClassificationProblemImpl<L, P>(problem.getLabelClass(), subExamples,
						                                          problem.getExampleIds());

				//** Unbalanced data: see prepareWeights
				// since these will be extremely unbalanced, this should nearly guarantee that no positive examples are misclassified.

				//float costOfNegativeMisclassification = weights.get(label);
				//float costOfPositiveMisclassification = weights.get(notLabel);

				model.putOneVsAllModel(label, binarySvm.train(subProblem, weights.get(label), weights.get(notLabel)));

				c++;
				if (c % 100 == 0)
					{
					logger.debug("Trained " + c + " one-vs-all models");
					}
				}
			}


		if (param.allVsAllMode != MultiClassModel.AllVsAllMode.None)
			{
			// create and train all vs all classifiers

			logger.info("Training " + (numLabels * (numLabels - 1)) / 2 + " one-vs-one classifiers for " + numLabels
					+ " labels");
			int c = 0;
			Map<L, Set<P>> examplesByLabel = problem.getExamplesByLabel();
			for (L label1 : problem.getLabels())
				{
				for (L label2 : problem.getLabels())
					{
					if (label1.compareTo(label2) < 0)// avoid redundant pairs
						{
						final Set<P> label1Examples = examplesByLabel.get(label1);
						final Set<P> label2Examples = examplesByLabel.get(label2);

						// PERF constructing each example set explicitly sucks, especially since they'll later be rebuilt with Boolean values anyway;
						// can we make a UnionMap or something?
						Map<P, L> subExamples = new HashMap<P, L>(label1Examples.size() + label2Examples.size());

						for (P label1Example : label1Examples)
							{
							subExamples.put(label1Example, label1);
							}
						for (P label2Example : label2Examples)
							{
							subExamples.put(label2Example, label2);
							}

						// Map<P,L> subExamples = new BinaryMap<P,L>(label1Examples, label1, label2Examples, label2);

						//BinaryClassificationProblem<P> subProblem = new BinaryClassificationProblem<P>(label1Examples, label2Examples);

						BinaryClassificationProblem<L, P> subProblem =
								new BinaryClassificationProblemImpl<L, P>(problem.getLabelClass(), subExamples,
								                                          problem.getExampleIds());

						//** Unbalanced data: see prepareWeights
						final BinaryModel<L, P> binaryModel =
								binarySvm.train(subProblem, weights.get(label1), weights.get(label2));

						model.putOneVsOneModel(label1, label2, binaryModel);
						c++;
						if (c % 100 == 0)
							{
							logger.debug("Trained " + c + " one-vs-one models");
							}
						}
					}
				}
			}

		return model;
		}
<commit_msg>Horrible multiclass svm bug wrt inconsistent example IDs vs the kernel cache<commit_after>package edu.berkeley.compbio.jlibsvm.multi;

import edu.berkeley.compbio.jlibsvm.SVM;
import edu.berkeley.compbio.jlibsvm.SvmProblem;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationProblem;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationProblemImpl;
import edu.berkeley.compbio.jlibsvm.binary.BinaryClassificationSVM;
import edu.berkeley.compbio.jlibsvm.binary.BinaryModel;
import edu.berkeley.compbio.jlibsvm.labelinverter.LabelInverter;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @version $Id$
 */
public class MultiClassificationSVM<L extends Comparable<L>, P> extends SVM<L, P, MultiClassProblem<L, P>>
	{
	private static final Logger logger = Logger.getLogger(MultiClassificationSVM.class);

	BinaryClassificationSVM<L, P> binarySvm;	//private Class labelClass;

	public MultiClassificationSVM(BinaryClassificationSVM<L, P> binarySvm, Class labelClass)
		{
		super(binarySvm.kernel, binarySvm.param);
		this.binarySvm = binarySvm;		//	this.labelClass = labelClass;
		}

	public String getSvmType()
		{
		return "multiclass " + binarySvm.getSvmType();
		}

	/*	@Override
   public Class getLabelClass()
	   {
	   return labelClass;
	   }*/


	public void setupQMatrix(SvmProblem<L, P> problem)
		{
		binarySvm.setupQMatrix(problem);
		qMatrix = binarySvm.qMatrix; // just for the sake of reporting later
		}


	public MultiClassModel<L, P> train(MultiClassProblem<L, P> problem)
		{
		int numLabels = problem.getLabels().size();

		MultiClassModel<L, P> model = new MultiClassModel<L, P>(kernel, param, numLabels);


		Map<L, Float> weights = prepareWeights(problem);

		/*
		if (param.multiclassMode != MultiClassModel.MulticlassMode.OneVsAllOnly)
			{
			// create and train one-class classifiers

			logger.info("Training one-class classifiers for " + numLabels + " labels");

			for (Map.Entry<L,Set<P>> entry : problem.getExamplesByLabel().entrySet())
				{
				Map<P, Float> subExamples = new HashMap<P, Float>(problem.getExamples().size());

				for (P point : entry.getValue())
					{
					subExamples.put(point, 1f);
					}

				OneClassProblem<L, P> subProblem =
						new OneClassProblemImpl<L, P>(subExamples, entry.getKey());

				model.putOneClassModel(entry.getKey(), oneClassSvm.train(subProblem));
				}
			}
*/
		if (param.oneVsAllMode != MultiClassModel.OneVsAllMode.None)
			{
			// create and train one vs all classifiers

			logger.info("Training one-vs-all classifiers for " + numLabels + " labels");
			int c = 0;
			LabelInverter<L> labelInverter = problem.getLabelInverter();
			for (L label : problem.getLabels())
				{
				Map<P, L> subExamples = new HashMap<P, L>(problem.getExamples().size());
				L notLabel = labelInverter.invert(label);

				Collection<Map.Entry<P, L>> entries = problem.getExamples().entrySet();
				if (param.falseClassSVlimit != 0)
					{
					// guarantee entries in random order if limiting the number of false examples
					List<Map.Entry<P, L>> entryList = new ArrayList<Map.Entry<P, L>>(entries);
					Collections.shuffle(entryList);
					entries = entryList;
					}

				int falseExamples = 0;
				for (Map.Entry<P, L> entry : entries)
					{
					if (entry.getValue().equals(label))
						{
						subExamples.put(entry.getKey(), label);
						}
					else if (param.falseClassSVlimit == 0 || falseExamples < param.falseClassSVlimit)
						{
						subExamples.put(entry.getKey(), notLabel);
						falseExamples++;
						}
					}

				BinaryClassificationProblem<L, P> subProblem =
						new BinaryClassificationProblemImpl<L, P>(problem.getLabelClass(), subExamples,
						                                          problem.getExampleIds());

				//** Unbalanced data: see prepareWeights
				// since these will be extremely unbalanced, this should nearly guarantee that no positive examples are misclassified.

				//float costOfNegativeMisclassification = weights.get(label);
				//float costOfPositiveMisclassification = weights.get(notLabel);

				model.putOneVsAllModel(label, binarySvm.train(subProblem, weights.get(label), weights.get(notLabel)));

				logger.debug("one-vs-all " + c + ": " + qMatrix.perfString());

				c++;
				if (c % 100 == 0)
					{
					logger.debug("Trained " + c + " one-vs-all models");
					}
				}
			}


		if (param.allVsAllMode != MultiClassModel.AllVsAllMode.None)
			{
			// create and train all vs all classifiers

			logger.info("Training " + (numLabels * (numLabels - 1)) / 2 + " one-vs-one classifiers for " + numLabels
					+ " labels");
			int c = 0;
			Map<L, Set<P>> examplesByLabel = problem.getExamplesByLabel();
			for (L label1 : problem.getLabels())
				{
				for (L label2 : problem.getLabels())
					{
					if (label1.compareTo(label2) < 0)// avoid redundant pairs
						{
						final Set<P> label1Examples = examplesByLabel.get(label1);
						final Set<P> label2Examples = examplesByLabel.get(label2);

						// PERF constructing each example set explicitly sucks, especially since they'll later be rebuilt with Boolean values anyway;
						// can we make a UnionMap or something?
						Map<P, L> subExamples = new HashMap<P, L>(label1Examples.size() + label2Examples.size());

						for (P label1Example : label1Examples)
							{
							subExamples.put(label1Example, label1);
							}
						for (P label2Example : label2Examples)
							{
							subExamples.put(label2Example, label2);
							}

						// Map<P,L> subExamples = new BinaryMap<P,L>(label1Examples, label1, label2Examples, label2);

						//BinaryClassificationProblem<P> subProblem = new BinaryClassificationProblem<P>(label1Examples, label2Examples);

						BinaryClassificationProblem<L, P> subProblem =
								new BinaryClassificationProblemImpl<L, P>(problem.getLabelClass(), subExamples,
								                                          problem.getExampleIds());

						//** Unbalanced data: see prepareWeights
						final BinaryModel<L, P> binaryModel =
								binarySvm.train(subProblem, weights.get(label1), weights.get(label2));

						model.putOneVsOneModel(label1, label2, binaryModel);

						logger.debug("one-vs-one " + c + ": " + qMatrix.perfString());

						c++;
						if (c % 100 == 0)
							{
							logger.debug("Trained " + c + " one-vs-one models");
							}
						}
					}
				}
			}

		return model;
		}

{'fraction_non_alphanumeric': 0.12302692664809657, 'fraction_numerical': 0.007118539151965335, 'mean_word_length': 3.3591905564924116, 'pattern_counts': {'":': 2, '<': 101, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1091618', 'n_tokens_mistral': 5128, 'n_tokens_neox': 3994, 'n_words': 871}