Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/05/12 11:58:17 (12 years ago)
Author:
mkommend
Message:

#1081: Merged trunk changes and fixed compilation errors due to the merge.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.TimeSeries/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaAlgorithm.cs

    r8471 r8742  
    3535
    3636namespace HeuristicLab.Algorithms.DataAnalysis {
    37   internal delegate void Reporter(double quality, double[] coefficients);
     37  internal delegate void Reporter(double quality, double[] coefficients, double[] gradients);
    3838  /// <summary>
    3939  /// Neighborhood Components Analysis
    4040  /// </summary>
    41   [Item("Neighborhood Components Analysis (NCA)", "Implementation of Neighborhood Components Analysis based on the description of J. Goldberger, S. Roweis, G. Hinton, R. Salakhutdinov. 2005. Neighbourhood Component Analysis. Advances in Neural Information Processing Systems, 17. pp. 513-520.")]
     41  [Item("Neighborhood Components Analysis (NCA)", @"Implementation of Neighborhood Components Analysis
     42based on the description of J. Goldberger, S. Roweis, G. Hinton, R. Salakhutdinov. 2005.
     43Neighbourhood Component Analysis. Advances in Neural Information Processing Systems, 17. pp. 513-520
     44with additional regularizations described in Z. Yang, J. Laaksonen. 2007.
     45Regularized Neighborhood Component Analysis. Lecture Notes in Computer Science, 4522. pp. 253-262.")]
    4246  [Creatable("Data Analysis")]
    4347  [StorableClass]
     
    5963      get { return (IFixedValueParameter<IntValue>)Parameters["Iterations"]; }
    6064    }
     65    public IFixedValueParameter<DoubleValue> RegularizationParameter {
     66      get { return (IFixedValueParameter<DoubleValue>)Parameters["Regularization"]; }
     67    }
    6168    #endregion
    6269
    6370    #region Properties
    64     private int K {
     71    public int K {
    6572      get { return KParameter.Value.Value; }
    6673      set { KParameter.Value.Value = value; }
    6774    }
    68     private int Dimensions {
     75    public int Dimensions {
    6976      get { return DimensionsParameter.Value.Value; }
    7077      set { DimensionsParameter.Value.Value = value; }
    7178    }
    72     private int NeighborSamples {
     79    public int NeighborSamples {
    7380      get { return NeighborSamplesParameter.Value.Value; }
    7481      set { NeighborSamplesParameter.Value.Value = value; }
    7582    }
    76     private int Iterations {
     83    public int Iterations {
    7784      get { return IterationsParameter.Value.Value; }
    7885      set { IterationsParameter.Value.Value = value; }
     86    }
     87    public double Regularization {
     88      get { return RegularizationParameter.Value.Value; }
     89      set { RegularizationParameter.Value.Value = value; }
    7990    }
    8091    #endregion
     
    8596    public NcaAlgorithm()
    8697      : base() {
    87       Parameters.Add(new FixedValueParameter<IntValue>("K", "The K for the nearest neighbor.", new IntValue(1)));
     98      Parameters.Add(new FixedValueParameter<IntValue>("K", "The K for the nearest neighbor.", new IntValue(3)));
    8899      Parameters.Add(new FixedValueParameter<IntValue>("Dimensions", "The number of dimensions that NCA should reduce the data to.", new IntValue(2)));
    89100      Parameters.Add(new ConstrainedValueParameter<INCAInitializer>("Initialization", "Which method should be used to initialize the matrix. Typically LDA (linear discriminant analysis) should provide a good estimate."));
    90       Parameters.Add(new FixedValueParameter<IntValue>("NeighborSamples", "How many of the neighbors should be sampled in order to speed up the calculation. This should be at least the value of k and at most the number of training instances minus one.", new IntValue(50)));
    91       Parameters.Add(new FixedValueParameter<IntValue>("Iterations", "How many iterations the conjugate gradient (CG) method should be allowed to perform. The method might still terminate earlier if a local optima has already been reached.", new IntValue(20)));
     101      Parameters.Add(new FixedValueParameter<IntValue>("NeighborSamples", "How many of the neighbors should be sampled in order to speed up the calculation. This should be at least the value of k and at most the number of training instances minus one.", new IntValue(60)));
     102      Parameters.Add(new FixedValueParameter<IntValue>("Iterations", "How many iterations the conjugate gradient (CG) method should be allowed to perform. The method might still terminate earlier if a local optima has already been reached.", new IntValue(50)));
     103      Parameters.Add(new FixedValueParameter<DoubleValue>("Regularization", "A non-negative paramter which can be set to increase generalization and avoid overfitting. If set to 0 the algorithm is similar to NCA as proposed by Goldberger et al.", new DoubleValue(0)));
    92104
    93105      INCAInitializer defaultInitializer = null;
     
    105117    }
    106118
     119    [StorableHook(HookType.AfterDeserialization)]
     120    private void AfterDeserialization() {
     121      if (!Parameters.ContainsKey("Regularization")) {
     122        Parameters.Add(new FixedValueParameter<DoubleValue>("Regularization", "A non-negative paramter which can be set to increase generalization and avoid overfitting. If set to 0 the algorithm is similar to NCA as proposed by Goldberger et al.", new DoubleValue(0)));
     123      }
     124    }
     125
    107126    public override void Prepare() {
    108127      if (Problem != null) base.Prepare();
     
    113132
    114133      var clonedProblem = (IClassificationProblemData)Problem.ProblemData.Clone();
    115       var model = Train(clonedProblem, K, Dimensions, NeighborSamples, Iterations, initializer.Initialize(clonedProblem, Dimensions), ReportQuality, CancellationToken.None);
    116       Results.Add(new Result("ClassificationSolution", "The classification solution.", model.CreateClassificationSolution(clonedProblem)));
    117     }
    118 
    119     public static INcaClassificationSolution CreateClassificationSolution(IClassificationProblemData data, int k, int dimensions, int neighborSamples, int iterations, INCAInitializer initializer) {
     134      var model = Train(clonedProblem, K, Dimensions, NeighborSamples, Regularization, Iterations, initializer.Initialize(clonedProblem, Dimensions), ReportQuality, CancellationToken.None);
     135      var solution = model.CreateClassificationSolution(clonedProblem);
     136      if (!Results.ContainsKey("ClassificationSolution"))
     137        Results.Add(new Result("ClassificationSolution", "The classification solution.", solution));
     138      else Results["ClassificationSolution"].Value = solution;
     139    }
     140
     141    public static INcaClassificationSolution CreateClassificationSolution(IClassificationProblemData data, int k, int dimensions, int neighborSamples, double regularization, int iterations, INCAInitializer initializer) {
    120142      var clonedProblem = (IClassificationProblemData)data.Clone();
    121       var model = Train(clonedProblem, k, dimensions, neighborSamples, iterations, initializer);
     143      var model = Train(clonedProblem, k, dimensions, neighborSamples, regularization, iterations, initializer);
    122144      return model.CreateClassificationSolution(clonedProblem);
    123145    }
    124146
    125     public static INcaModel Train(IClassificationProblemData problemData, int k, int dimensions, int neighborSamples, int iterations, INCAInitializer initializer) {
    126       return Train(problemData, k, dimensions, neighborSamples, iterations, initializer.Initialize(problemData, dimensions), null, CancellationToken.None);
    127     }
    128 
    129     public static INcaModel Train(IClassificationProblemData problemData, int k, int neighborSamples, int iterations, double[,] initalMatrix) {
     147    public static INcaModel Train(IClassificationProblemData problemData, int k, int dimensions, int neighborSamples, double regularization, int iterations, INCAInitializer initializer) {
     148      return Train(problemData, k, dimensions, neighborSamples, regularization, iterations, initializer.Initialize(problemData, dimensions), null, CancellationToken.None);
     149    }
     150
     151    public static INcaModel Train(IClassificationProblemData problemData, int k, int neighborSamples, double regularization, int iterations, double[,] initalMatrix) {
    130152      var matrix = new double[initalMatrix.Length];
    131153      for (int i = 0; i < initalMatrix.GetLength(0); i++)
    132154        for (int j = 0; j < initalMatrix.GetLength(1); j++)
    133155          matrix[i * initalMatrix.GetLength(1) + j] = initalMatrix[i, j];
    134       return Train(problemData, k, initalMatrix.GetLength(1), neighborSamples, iterations, matrix, null, CancellationToken.None);
    135     }
    136 
    137     private static INcaModel Train(IClassificationProblemData data, int k, int dimensions, int neighborSamples, int iterations, double[] matrix, Reporter reporter, CancellationToken cancellation) {
     156      return Train(problemData, k, initalMatrix.GetLength(1), neighborSamples, regularization, iterations, matrix, null, CancellationToken.None);
     157    }
     158
     159    private static INcaModel Train(IClassificationProblemData data, int k, int dimensions, int neighborSamples, double regularization, int iterations, double[] matrix, Reporter reporter, CancellationToken cancellation) {
    138160      var scaling = new Scaling(data.Dataset, data.AllowedInputVariables, data.TrainingIndices);
    139161      var scaledData = AlglibUtil.PrepareAndScaleInputMatrix(data.Dataset, data.AllowedInputVariables, data.TrainingIndices, scaling);
     
    146168      alglib.mincgsetcond(state, 0, 0, 0, iterations);
    147169      alglib.mincgsetxrep(state, true);
     170      //alglib.mincgsetgradientcheck(state, 0.01);
    148171      int neighborSampleSize = neighborSamples;
    149       Optimize(state, scaledData, classes, dimensions, neighborSampleSize, cancellation, reporter);
     172      Optimize(state, scaledData, classes, dimensions, neighborSampleSize, regularization, cancellation, reporter);
    150173      alglib.mincgresults(state, out matrix, out rep);
     174      if (rep.terminationtype == -7) throw new InvalidOperationException("Gradient verification failed.");
    151175
    152176      var transformationMatrix = new double[attributes, dimensions];
     
    159183    }
    160184
    161     private static void Optimize(alglib.mincgstate state, double[,] data, double[] classes, int dimensions, int neighborSampleSize, CancellationToken cancellation, Reporter reporter) {
     185    private static void Optimize(alglib.mincgstate state, double[,] data, double[] classes, int dimensions, int neighborSampleSize, double lambda, CancellationToken cancellation, Reporter reporter) {
    162186      while (alglib.mincgiteration(state)) {
    163187        if (cancellation.IsCancellationRequested) break;
    164188        if (state.needfg) {
    165           Gradient(state.x, ref state.innerobj.f, state.innerobj.g, data, classes, dimensions, neighborSampleSize);
     189          Gradient(state.x, ref state.innerobj.f, state.innerobj.g, data, classes, dimensions, neighborSampleSize, lambda);
    166190          continue;
    167191        }
    168192        if (state.innerobj.xupdated) {
    169193          if (reporter != null)
    170             reporter(state.innerobj.f, state.innerobj.x);
     194            reporter(state.innerobj.f, state.innerobj.x, state.innerobj.g);
    171195          continue;
    172196        }
     
    175199    }
    176200
    177     private static void Gradient(double[] A, ref double func, double[] grad, double[,] data, double[] classes, int dimensions, int neighborSampleSize) {
     201    private static void Gradient(double[] A, ref double func, double[] grad, double[,] data, double[] classes, int dimensions, int neighborSampleSize, double lambda) {
    178202      var instances = data.GetLength(0);
    179203      var attributes = data.GetLength(1);
     
    192216          }
    193217          var kVector = new Matrix(GetRow(data, k));
    194           transformedDistances[k] = Math.Exp(-iVector.Multiply(AMatrix).Subtract(kVector.Multiply(AMatrix)).SquaredVectorLength());
    195         }
    196         var sample = transformedDistances.OrderByDescending(x => x.Value).Take(neighborSampleSize).ToArray();
    197         var normalization = sample.Sum(x => x.Value);
    198         if (normalization > 0) {
    199           foreach (var s in sample) {
    200             if (s.Value <= 0) break;
    201             alglib.sparseset(probabilities, i, s.Key, s.Value / normalization);
    202           }
     218          transformedDistances[k] = Math.Exp(-iVector.Multiply(AMatrix).Subtract(kVector.Multiply(AMatrix)).SumOfSquares());
     219        }
     220        var normalization = transformedDistances.Sum(x => x.Value);
     221        if (normalization <= 0) continue;
     222        foreach (var s in transformedDistances.Where(x => x.Value > 0).OrderByDescending(x => x.Value).Take(neighborSampleSize)) {
     223          alglib.sparseset(probabilities, i, s.Key, s.Value / normalization);
    203224        }
    204225      }
     
    224245      }
    225246
    226       func = -pi.Sum();
     247      func = -pi.Sum() + lambda * AMatrix.SumOfSquares();
    227248
    228249      r = 0;
    229250      var newGrad = AMatrix.Multiply(-2.0).Transpose().Multiply(new Matrix(innerSum)).Transpose();
    230251      foreach (var g in newGrad) {
    231         grad[r++] = g;
    232       }
    233     }
    234 
    235     private void ReportQuality(double func, double[] coefficients) {
     252        grad[r] = g + lambda * 2 * A[r];
     253        r++;
     254      }
     255    }
     256
     257    private void ReportQuality(double func, double[] coefficients, double[] gradients) {
    236258      var instances = Problem.ProblemData.TrainingIndices.Count();
    237259      DataTable qualities;
     
    243265      qualities.Rows["Quality"].Values.Add(-func / instances);
    244266
     267      string[] attributNames = Problem.ProblemData.AllowedInputVariables.ToArray();
     268      if (gradients != null) {
     269        DataTable grads;
     270        if (!Results.ContainsKey("Gradients")) {
     271          grads = new DataTable("Gradients");
     272          for (int i = 0; i < gradients.Length; i++)
     273            grads.Rows.Add(new DataRow(attributNames[i / Dimensions] + "-" + (i % Dimensions), string.Empty));
     274          Results.Add(new Result("Gradients", grads));
     275        } else grads = (DataTable)Results["Gradients"].Value;
     276        for (int i = 0; i < gradients.Length; i++)
     277          grads.Rows[attributNames[i / Dimensions] + "-" + (i % Dimensions)].Values.Add(gradients[i]);
     278      }
     279
    245280      if (!Results.ContainsKey("Quality")) {
    246281        Results.Add(new Result("Quality", new DoubleValue(-func / instances)));
    247282      } else ((DoubleValue)Results["Quality"].Value).Value = -func / instances;
     283
     284      var attributes = attributNames.Length;
     285      var transformationMatrix = new double[attributes, Dimensions];
     286      var counter = 0;
     287      for (var i = 0; i < attributes; i++)
     288        for (var j = 0; j < Dimensions; j++)
     289          transformationMatrix[i, j] = coefficients[counter++];
     290
     291      var scaling = new Scaling(Problem.ProblemData.Dataset, attributNames, Problem.ProblemData.TrainingIndices);
     292      var model = new NcaModel(K, transformationMatrix, Problem.ProblemData.Dataset, Problem.ProblemData.TrainingIndices, Problem.ProblemData.TargetVariable, attributNames, scaling, Problem.ProblemData.ClassValues.ToArray());
     293
     294      IClassificationSolution solution = model.CreateClassificationSolution(Problem.ProblemData);
     295      if (!Results.ContainsKey("ClassificationSolution")) {
     296        Results.Add(new Result("ClassificationSolution", solution));
     297      } else {
     298        Results["ClassificationSolution"].Value = solution;
     299      }
    248300    }
    249301
     
    252304        yield return data[row, i];
    253305    }
     306
    254307  }
    255308}
Note: See TracChangeset for help on using the changeset viewer.