Changeset 15531


Ignore:
Timestamp:
12/18/17 12:27:14 (20 months ago)
Author:
bwerth
Message:

#2850 added named weights and automatic adaption thereof

Location:
branches/Weighted TSNE/3.4/TSNE
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/Weighted TSNE/3.4/TSNE/Distances/WeightedEuclideanDistance.cs

    r15487 r15531  
    2929using HeuristicLab.Parameters;
    3030using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     31using HeuristicLab.Problems.DataAnalysis;
    3132
    3233namespace HeuristicLab.Algorithms.DataAnalysis {
     
    3435  [Item("WeightedEuclideanDistance", "A weighted norm function that uses Euclidean distance √(Σ(w[i]²*(p1[i]-p2[i])²))")]
    3536  public class WeightedEuclideanDistance : ParameterizedNamedItem, IDistance<IEnumerable<double>> {
     37    [Storable]
     38    private double[] weights;
    3639    public const string WeightsParameterName = "Weights";
    37     public IValueParameter<DoubleArray> WeigthsParameter {
     40    public IValueParameter<DoubleArray> WeightsParameter {
    3841      get { return (IValueParameter<DoubleArray>) Parameters[WeightsParameterName]; }
    3942    }
    4043
    4144    public DoubleArray Weights {
    42       get { return WeigthsParameter.Value; }
    43       set { WeigthsParameter.Value = value; }
     45      get { return WeightsParameter.Value; }
     46      set { WeightsParameter.Value = value; }
    4447    }
    4548
     
    5255    protected WeightedEuclideanDistance(WeightedEuclideanDistance original, Cloner cloner) : base(original, cloner) {
    5356      RegisterParameterEvents();
     57      weights = original.weights != null ? original.weights.ToArray() : null;
    5458    }
    5559    public override IDeepCloneable Clone(Cloner cloner) {
     
    5761    }
    5862    public WeightedEuclideanDistance() {
    59       Parameters.Add(new ValueParameter<DoubleArray>(WeightsParameterName, "The weights used to modify the euclidean distance."));
     63      Parameters.Add(new ValueParameter<DoubleArray>(WeightsParameterName, "The weights used to modify the euclidean distance.", new DoubleArray(new[] {1.0})));
    6064      RegisterParameterEvents();
    6165    }
     
    7680
    7781    public double Get(IEnumerable<double> a, IEnumerable<double> b) {
    78       return GetDistance(a, b, Weights);
     82      return GetDistance(a, b, weights);
    7983    }
    8084    public IComparer<IEnumerable<double>> GetDistanceComparer(IEnumerable<double> item) {
     
    8892    }
    8993
     94    public void AdaptToProblemData(IDataAnalysisProblemData problemData) {
     95      Weights = new DoubleArray(problemData.AllowedInputVariables.Select(v => Weights.ElementNames.Contains(v) ? GetWeight(v) : 1).ToArray())
     96        {ElementNames = problemData.AllowedInputVariables};
     97    }
     98    public void Initialize(IDataAnalysisProblemData problemData) {
     99      if (Weights.Length != problemData.AllowedInputVariables.Count()) throw new ArgumentException("Number of Weights does not match the number of input variables");
     100      weights = Weights.ElementNames.All(v => v == null || v.Equals(string.Empty)) ?
     101        Weights.ToArray() :
     102        problemData.AllowedInputVariables.Select(GetWeight).ToArray();
     103    }
     104    private double GetWeight(string v) {
     105      var w = Weights;
     106      var names = w.ElementNames.ToArray();
     107      for (var i = 0; i < w.Length; i++) if (names[i].Equals(v)) return w[i];
     108      throw new ArgumentException("weigth for " + v + " was requested but not specified.");
     109    }
    90110    private void RegisterParameterEvents() {
    91       WeigthsParameter.ValueChanged += OnWeightsArrayChanged;
    92       WeigthsParameter.Value.ItemChanged += OnWeightChanged;
     111      WeightsParameter.ValueChanged += OnWeightsArrayChanged;
     112      WeightsParameter.Value.ItemChanged += OnWeightChanged;
    93113    }
    94114    private void OnWeightChanged(object sender, EventArgs<int> e) {
    95       WeigthsParameter.Value.ItemChanged -= OnWeightChanged;
     115      WeightsParameter.Value.ItemChanged -= OnWeightChanged;
    96116      Weights[e.Value] = Math.Max(0, Weights[e.Value]);
    97       WeigthsParameter.Value.ItemChanged -= OnWeightChanged;
     117      WeightsParameter.Value.ItemChanged -= OnWeightChanged;
    98118    }
    99119    private void OnWeightsArrayChanged(object sender, EventArgs e) {
    100       for (int i = 0; i < Weights.Length; i++)
     120      for (var i = 0; i < Weights.Length; i++)
    101121        Weights[i] = Math.Max(0, Weights[i]);
    102       WeigthsParameter.Value.ItemChanged += OnWeightChanged;
     122      WeightsParameter.Value.ItemChanged += OnWeightChanged;
    103123    }
    104124  }
  • branches/Weighted TSNE/3.4/TSNE/TSNEAlgorithm.cs

    r15487 r15531  
    195195      set { RandomInitializationParameter.Value.Value = value; }
    196196    }
    197 
    198197    public int UpdateInterval {
    199198      get { return UpdateIntervalParameter.Value.Value; }
     
    219218    [StorableHook(HookType.AfterDeserialization)]
    220219    private void AfterDeserialization() {
     220      if (Parameters.ContainsKey(RandomInitializationParameterName))
     221        Parameters.Add(new FixedValueParameter<BoolValue>(RandomInitializationParameterName, "Wether data points should be randomly initialized or according to the first 2 dimensions", new BoolValue(true)));
    221222      RegisterParameterEvents();
    222223    }
     
    279280      var problemData = Problem.ProblemData;
    280281      // set up and initialize everything if necessary
     282      var wdist = DistanceFunction as WeightedEuclideanDistance;
     283      if (wdist != null) wdist.Initialize(problemData);
    281284      if (state == null) {
    282285        if (SetSeedRandomly) Seed = new System.Random().Next();
     
    299302
    300303        if (Normalization) data = NormalizeInputData(data);
    301         var randomInit = Parameters.ContainsKey(RandomInitializationParameterName) ? RandomInitialization : true;
    302         state = TSNEStatic<double[]>.CreateState(data, DistanceFunction, random, NewDimensions, Perplexity, Theta, StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta, randomInit);
     304        state = TSNEStatic<double[]>.CreateState(data, DistanceFunction, random, NewDimensions, Perplexity, Theta, StopLyingIteration, MomentumSwitchIteration, InitialMomentum, FinalMomentum, Eta, RandomInitialization);
    303305        SetUpResults(allindices);
    304306        iter = 0;
     
    338340      if (Problem == null || Problem.ProblemData == null) return;
    339341      OnPerplexityChanged(this, null);
     342      OnColumnsChanged(this, null);
    340343      Problem.ProblemData.Changed += OnPerplexityChanged;
    341344      Problem.ProblemData.Changed += OnColumnsChanged;
     
    349352    private void OnColumnsChanged(object sender, EventArgs e) {
    350353      if (Problem == null || Problem.ProblemData == null || Problem.ProblemData.Dataset == null || !Parameters.ContainsKey(DistanceFunctionParameterName)) return;
    351       DistanceFunctionParameter.ValidValues.OfType<WeightedEuclideanDistance>().Single().Weights = new DoubleArray(Problem.ProblemData.AllowedInputVariables.Select(x => 1.0).ToArray());
     354      DistanceFunctionParameter.ValidValues.OfType<WeightedEuclideanDistance>().Single().AdaptWeightVector(Problem.ProblemData);
    352355    }
    353356
     
    546549      var colorGradient = ColorGradient.Colors;
    547550      var range = high - low;
    548       var h = cell / range * colorGradient.Count;
     551      var h = Math.Min(cell / range * colorGradient.Count, colorGradient.Count - 1);
    549552      return colorGradient[(int) h];
    550553    }
Note: See TracChangeset for help on using the changeset viewer.