#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab 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.
*
* HeuristicLab 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 HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using HeuristicLab.Algorithms.DataAnalysis;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Problems.DataAnalysis;
namespace HeuristicLab.Algorithms.NCA {
[Item("NCAModel", "")]
[StorableClass]
public class NCAModel : NamedItem, INCAModel {
[Storable]
private string targetVariable;
[Storable]
private string[] allowedInputVariables;
[Storable]
private double[] classValues;
///
/// Get a clone of the class values
///
public double[] ClassValues {
get { return (double[])classValues.Clone(); }
}
[Storable]
private int k;
[Storable]
private double[,] transformationMatrix;
///
/// Get a clone of the transformation matrix
///
public double[,] TransformationMatrix {
get { return (double[,])transformationMatrix.Clone(); }
}
[Storable]
private double[,] transformedTrainingset;
///
/// Get a clone of the transformed trainingset
///
public double[,] TransformedTrainingset {
get { return (double[,])transformedTrainingset.Clone(); }
}
[Storable]
private Scaling scaling;
[StorableConstructor]
protected NCAModel(bool deserializing) : base(deserializing) { }
protected NCAModel(NCAModel original, Cloner cloner)
: base(original, cloner) {
k = original.k;
targetVariable = original.targetVariable;
allowedInputVariables = (string[])original.allowedInputVariables.Clone();
if (original.classValues != null)
this.classValues = (double[])original.classValues.Clone();
if (original.transformationMatrix != null)
this.transformationMatrix = (double[,])original.transformationMatrix.Clone();
if (original.transformedTrainingset != null)
this.transformedTrainingset = (double[,])original.transformedTrainingset.Clone();
this.scaling = cloner.Clone(original.scaling);
}
public NCAModel(double[,] transformedTrainingset, Scaling scaling, double[,] transformationMatrix, int k, string targetVariable, IEnumerable allowedInputVariables, double[] classValues = null)
: base() {
this.name = ItemName;
this.description = ItemDescription;
this.transformedTrainingset = transformedTrainingset;
this.scaling = scaling;
this.transformationMatrix = transformationMatrix;
this.k = k;
this.targetVariable = targetVariable;
this.allowedInputVariables = allowedInputVariables.ToArray();
if (classValues != null)
this.classValues = (double[])classValues.Clone();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new NCAModel(this, cloner);
}
public IEnumerable GetEstimatedClassValues(Dataset dataset, IEnumerable rows) {
var k = Math.Min(this.k, transformedTrainingset.GetLength(0));
var transformedRow = new double[transformationMatrix.GetLength(1)];
var kVotes = new SortedList(k + 1);
foreach (var r in rows) {
for (int i = 0; i < transformedRow.Length; i++) transformedRow[i] = 0;
int j = 0;
foreach (var v in allowedInputVariables) {
var values = scaling.GetScaledValues(dataset, v, rows);
double val = dataset.GetDoubleValue(v, r);
for (int i = 0; i < transformedRow.Length; i++)
transformedRow[i] += val * transformationMatrix[j, i];
j++;
}
kVotes.Clear();
for (int a = 0; a < transformedTrainingset.GetLength(0); a++) {
double d = 0;
for (int y = 0; y < transformedRow.Length; y++) {
d += (transformedRow[y] - transformedTrainingset[a, y]) * (transformedRow[y] - transformedTrainingset[a, y]);
}
while (kVotes.ContainsKey(d)) d += 1e-12;
if (kVotes.Count <= k || kVotes.Last().Key > d) {
kVotes.Add(d, classValues[a]);
if (kVotes.Count > k) kVotes.RemoveAt(kVotes.Count - 1);
}
}
yield return kVotes.Values.ToLookup(x => x).MaxItems(x => x.Count()).First().Key;
}
}
public NCAClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
return new NCAClassificationSolution(problemData, this);
}
IClassificationSolution IClassificationModel.CreateClassificationSolution(IClassificationProblemData problemData) {
return CreateClassificationSolution(problemData);
}
public double[,] Reduce(Dataset dataset, IEnumerable rows) {
var result = new double[rows.Count(), transformationMatrix.GetLength(1)];
int v = 0;
foreach (var r in rows) {
int i = 0;
foreach (var variable in allowedInputVariables) {
double val = dataset.GetDoubleValue(variable, r);
for (int j = 0; j < result.GetLength(1); j++)
result[v, j] += val * transformationMatrix[i, j];
i++;
}
v++;
}
return result;
}
}
}