Free cookie consent management tool by TermsFeed Policy Generator

Changeset 5818 for trunk/sources


Ignore:
Timestamp:
03/23/11 13:52:29 (13 years ago)
Author:
gkronber
Message:

#1418 Fixed a problem with scaling of regression and classification solutions (moved scale method out of solution into the model because of leaky abstraction).

Location:
trunk/sources
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveTrainingBestSolutionAnalyzer.cs

    r5809 r5818  
    7777    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
    7878      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    79       var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    8079      if (ApplyLinearScaling.Value) {
    81         solution.ScaleModel();
     80        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    8281      }
    83       return solution;
     82      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    8483    }
    8584  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/MultiObjective/SymbolicClassificationMultiObjectiveValidationBestSolutionAnalyzer.cs

    r5809 r5818  
    6666    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQualities) {
    6767      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    68       var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    6968      if (ApplyLinearScaling.Value) {
    70         solution.ScaleModel();
     69        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    7170      }
    72       return solution;
     71      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    7372    }
    7473  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveTrainingBestSolutionAnalyzer.cs

    r5809 r5818  
    7575    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    7676      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    77       var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    7877      if (ApplyLinearScaling.Value) {
    79         solution.ScaleModel();
     78        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    8079      }
    81       return solution;
     80      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    8281    }
    8382  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SingleObjective/SymbolicClassificationSingleObjectiveValidationBestSolutionAnalyzer.cs

    r5809 r5818  
    6666    protected override ISymbolicClassificationSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    6767      var model = new SymbolicDiscriminantFunctionClassificationModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    68       var solution = new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    6968      if (ApplyLinearScaling.Value) {
    70         solution.ScaleModel();
     69        SymbolicDiscriminantFunctionClassificationModel.Scale(model, ProblemDataParameter.ActualValue);
    7170      }
    72       return solution;
     71      return new SymbolicDiscriminantFunctionClassificationSolution(model, ProblemDataParameter.ActualValue);
    7372    }
    7473  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationModel.cs

    r5809 r5818  
    115115    }
    116116    #endregion
     117
     118    public static void Scale(SymbolicDiscriminantFunctionClassificationModel model, IClassificationProblemData problemData) {
     119      var dataset = problemData.Dataset;
     120      var targetVariable = problemData.TargetVariable;
     121      var rows = problemData.TrainingIndizes;
     122      var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
     123      var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
     124      double alpha;
     125      double beta;
     126      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
     127
     128      ConstantTreeNode alphaTreeNode = null;
     129      ConstantTreeNode betaTreeNode = null;
     130      // check if model has been scaled previously by analyzing the structure of the tree
     131      var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
     132      if (startNode.GetSubtree(0).Symbol is Addition) {
     133        var addNode = startNode.GetSubtree(0);
     134        if (addNode.SubtreesCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
     135          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
     136          var mulNode = addNode.GetSubtree(0);
     137          if (mulNode.SubtreesCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
     138            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
     139          }
     140        }
     141      }
     142      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
     143      if (alphaTreeNode != null && betaTreeNode != null) {
     144        betaTreeNode.Value *= beta;
     145        alphaTreeNode.Value *= beta;
     146        alphaTreeNode.Value += alpha;
     147      } else {
     148        var mainBranch = startNode.GetSubtree(0);
     149        startNode.RemoveSubtree(0);
     150        var scaledMainBranch = MakeSum(MakeProduct(beta, mainBranch), alpha);
     151        startNode.AddSubtree(scaledMainBranch);
     152      }
     153    }
     154
     155    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
     156      if (alpha.IsAlmost(0.0)) {
     157        return treeNode;
     158      } else {
     159        var node = (new Addition()).CreateTreeNode();
     160        var alphaConst = MakeConstant(alpha);
     161        node.AddSubtree(treeNode);
     162        node.AddSubtree(alphaConst);
     163        return node;
     164      }
     165    }
     166
     167    private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
     168      if (beta.IsAlmost(1.0)) {
     169        return treeNode;
     170      } else {
     171        var node = (new Multiplication()).CreateTreeNode();
     172        var betaConst = MakeConstant(beta);
     173        node.AddSubtree(treeNode);
     174        node.AddSubtree(betaConst);
     175        return node;
     176      }
     177    }
     178
     179    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
     180      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
     181      node.Value = c;
     182      return node;
     183    }
    117184  }
    118185}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicDiscriminantFunctionClassificationSolution.cs

    r5809 r5818  
    8787      ModelLength = Model.SymbolicExpressionTree.Length;
    8888      ModelDepth = Model.SymbolicExpressionTree.Depth;
    89     }
    90 
    91     public void ScaleModel() {
    92       var dataset = ProblemData.Dataset;
    93       var targetVariable = ProblemData.TargetVariable;
    94       var rows = ProblemData.TrainingIndizes;
    95       var estimatedValues = GetEstimatedValues(rows);
    96       var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
    97       double alpha;
    98       double beta;
    99       OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
    100 
    101       ConstantTreeNode alphaTreeNode = null;
    102       ConstantTreeNode betaTreeNode = null;
    103       // check if model has been scaled previously by analyzing the structure of the tree
    104       var startNode = Model.SymbolicExpressionTree.Root.GetSubtree(0);
    105       if (startNode.GetSubtree(0).Symbol is Addition) {
    106         var addNode = startNode.GetSubtree(0);
    107         if (addNode.SubtreesCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
    108           alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
    109           var mulNode = addNode.GetSubtree(0);
    110           if (mulNode.SubtreesCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
    111             betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
    112           }
    113         }
    114       }
    115       // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
    116       if (alphaTreeNode != null && betaTreeNode != null) {
    117         betaTreeNode.Value *= beta;
    118         alphaTreeNode.Value *= beta;
    119         alphaTreeNode.Value += alpha;
    120       } else {
    121         var mainBranch = startNode.GetSubtree(0);
    122         startNode.RemoveSubtree(0);
    123         var scaledMainBranch = MakeSum(MakeProduct(beta, mainBranch), alpha);
    124         startNode.AddSubtree(scaledMainBranch);
    125       }
    126 
    127       OnModelChanged(EventArgs.Empty);
    128     }
    129 
    130     private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
    131       if (alpha.IsAlmost(0.0)) {
    132         return treeNode;
    133       } else {
    134         var node = (new Addition()).CreateTreeNode();
    135         var alphaConst = MakeConstant(alpha);
    136         node.AddSubtree(treeNode);
    137         node.AddSubtree(alphaConst);
    138         return node;
    139       }
    140     }
    141 
    142     private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
    143       if (beta.IsAlmost(1.0)) {
    144         return treeNode;
    145       } else {
    146         var node = (new Multiplication()).CreateTreeNode();
    147         var betaConst = MakeConstant(beta);
    148         node.AddSubtree(treeNode);
    149         node.AddSubtree(betaConst);
    150         return node;
    151       }
    152     }
    153 
    154     private static ISymbolicExpressionTreeNode MakeConstant(double c) {
    155       var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
    156       node.Value = c;
    157       return node;
    158     }
     89    }   
    15990  }
    16091}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs

    r5809 r5818  
    5353
    5454    protected override void UpdateModel(ISymbolicExpressionTree tree) {
    55       Content.Model = new SymbolicRegressionModel(tree, Content.Model.Interpreter);
    56       Content.ScaleModel();
     55      var model = new SymbolicRegressionModel(tree, Content.Model.Interpreter);
     56      SymbolicRegressionModel.Scale(model, Content.ProblemData);
     57      Content.Model = model;
    5758    }
    5859
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveTrainingBestSolutionAnalyzer.cs

    r5809 r5818  
    7777    protected override ISymbolicRegressionSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
    7878      var model = new SymbolicRegressionModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    79       var solution = new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    8079      if (ApplyLinearScaling.Value)
    81         solution.ScaleModel();
    82       return solution;
     80        SymbolicRegressionModel.Scale(model, ProblemDataParameter.ActualValue);
     81      return new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    8382    }
    8483  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveValidationBestSolutionAnalyzer.cs

    r5809 r5818  
    6666    protected override ISymbolicRegressionSolution CreateSolution(ISymbolicExpressionTree bestTree, double[] bestQuality) {
    6767      var model = new SymbolicRegressionModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    68       var solution = new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    6968      if (ApplyLinearScaling.Value)
    70         solution.ScaleModel();
    71       return solution;
     69        SymbolicRegressionModel.Scale(model, ProblemDataParameter.ActualValue);
     70      return new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    7271    }
    7372  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveTrainingBestSolutionAnalyzer.cs

    r5809 r5818  
    7676    protected override ISymbolicRegressionSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    7777      var model = new SymbolicRegressionModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    78       var solution = new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    7978      if (ApplyLinearScaling.Value)
    80         solution.ScaleModel();
    81       return solution;
     79        SymbolicRegressionModel.Scale(model, ProblemDataParameter.ActualValue);
     80      return new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    8281    }
    8382  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/SymbolicRegressionSingleObjectiveValidationBestSolutionAnalyzer.cs

    r5809 r5818  
    6868    protected override ISymbolicRegressionSolution CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality) {
    6969      var model = new SymbolicRegressionModel(bestTree, SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper);
    70       var solution = new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    7170      if (ApplyLinearScaling.Value)
    72         solution.ScaleModel();
    73       return solution;
     71        SymbolicRegressionModel.Scale(model, ProblemDataParameter.ActualValue);
     72      return new SymbolicRegressionSolution(model, ProblemDataParameter.ActualValue);
    7473    }
    7574  }
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionModel.cs

    r5809 r5818  
    6666        .LimitToRange(lowerEstimationLimit, upperEstimationLimit);
    6767    }
     68
     69    public static void Scale(SymbolicRegressionModel model, IRegressionProblemData problemData) {
     70      var dataset = problemData.Dataset;
     71      var targetVariable = problemData.TargetVariable;
     72      var rows = problemData.TrainingIndizes;
     73      var estimatedValues = model.Interpreter.GetSymbolicExpressionTreeValues(model.SymbolicExpressionTree, dataset, rows);
     74      var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
     75      double alpha;
     76      double beta;
     77      OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
     78
     79      ConstantTreeNode alphaTreeNode = null;
     80      ConstantTreeNode betaTreeNode = null;
     81      // check if model has been scaled previously by analyzing the structure of the tree
     82      var startNode = model.SymbolicExpressionTree.Root.GetSubtree(0);
     83      if (startNode.GetSubtree(0).Symbol is Addition) {
     84        var addNode = startNode.GetSubtree(0);
     85        if (addNode.SubtreesCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
     86          alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
     87          var mulNode = addNode.GetSubtree(0);
     88          if (mulNode.SubtreesCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
     89            betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
     90          }
     91        }
     92      }
     93      // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
     94      if (alphaTreeNode != null && betaTreeNode != null) {
     95        betaTreeNode.Value *= beta;
     96        alphaTreeNode.Value *= beta;
     97        alphaTreeNode.Value += alpha;
     98      } else {
     99        var mainBranch = startNode.GetSubtree(0);
     100        startNode.RemoveSubtree(0);
     101        var scaledMainBranch = MakeSum(MakeProduct(beta, mainBranch), alpha);
     102        startNode.AddSubtree(scaledMainBranch);
     103      }
     104    }
     105
     106    private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
     107      if (alpha.IsAlmost(0.0)) {
     108        return treeNode;
     109      } else {
     110        var node = (new Addition()).CreateTreeNode();
     111        var alphaConst = MakeConstant(alpha);
     112        node.AddSubtree(treeNode);
     113        node.AddSubtree(alphaConst);
     114        return node;
     115      }
     116    }
     117
     118    private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
     119      if (beta.IsAlmost(1.0)) {
     120        return treeNode;
     121      } else {
     122        var node = (new Multiplication()).CreateTreeNode();
     123        var betaConst = MakeConstant(beta);
     124        node.AddSubtree(treeNode);
     125        node.AddSubtree(betaConst);
     126        return node;
     127      }
     128    }
     129
     130    private static ISymbolicExpressionTreeNode MakeConstant(double c) {
     131      var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
     132      node.Value = c;
     133      return node;
     134    }
    68135  }
    69136}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolution.cs

    r5809 r5818  
    8484      ModelDepth = Model.SymbolicExpressionTree.Depth;
    8585    }
    86 
    87     public void ScaleModel() {
    88       var dataset = ProblemData.Dataset;
    89       var targetVariable = ProblemData.TargetVariable;
    90       var rows = ProblemData.TrainingIndizes;
    91       var estimatedValues = GetEstimatedValues(rows);
    92       var targetValues = dataset.GetEnumeratedVariableValues(targetVariable, rows);
    93       double alpha;
    94       double beta;
    95       OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out alpha, out beta);
    96 
    97       ConstantTreeNode alphaTreeNode = null;
    98       ConstantTreeNode betaTreeNode = null;
    99       // check if model has been scaled previously by analyzing the structure of the tree
    100       var startNode = Model.SymbolicExpressionTree.Root.GetSubtree(0);
    101       if (startNode.GetSubtree(0).Symbol is Addition) {
    102         var addNode = startNode.GetSubtree(0);
    103         if (addNode.SubtreesCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {
    104           alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;
    105           var mulNode = addNode.GetSubtree(0);
    106           if (mulNode.SubtreesCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {
    107             betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;
    108           }
    109         }
    110       }
    111       // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes
    112       if (alphaTreeNode != null && betaTreeNode != null) {
    113         betaTreeNode.Value *= beta;
    114         alphaTreeNode.Value *= beta;
    115         alphaTreeNode.Value += alpha;
    116       } else {
    117         var mainBranch = startNode.GetSubtree(0);
    118         startNode.RemoveSubtree(0);
    119         var scaledMainBranch = MakeSum(MakeProduct(beta, mainBranch), alpha);
    120         startNode.AddSubtree(scaledMainBranch);
    121       }
    122 
    123       OnModelChanged(EventArgs.Empty);
    124     }
    125 
    126     private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {
    127       if (alpha.IsAlmost(0.0)) {
    128         return treeNode;
    129       } else {
    130         var node = (new Addition()).CreateTreeNode();
    131         var alphaConst = MakeConstant(alpha);
    132         node.AddSubtree(treeNode);
    133         node.AddSubtree(alphaConst);
    134         return node;
    135       }
    136     }
    137 
    138     private static ISymbolicExpressionTreeNode MakeProduct(double beta, ISymbolicExpressionTreeNode treeNode) {
    139       if (beta.IsAlmost(1.0)) {
    140         return treeNode;
    141       } else {
    142         var node = (new Multiplication()).CreateTreeNode();
    143         var betaConst = MakeConstant(beta);
    144         node.AddSubtree(treeNode);
    145         node.AddSubtree(betaConst);
    146         return node;
    147       }
    148     }
    149 
    150     private static ISymbolicExpressionTreeNode MakeConstant(double c) {
    151       var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();
    152       node.Value = c;
    153       return node;
    154     }
    15586  }
    15687}
  • trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineEvaluators/OnlineLinearScalingParameterCalculator.cs

    r5809 r5818  
    103103        double originalElement = originalEnumerator.Current;
    104104        double targetElement = targetEnumerator.Current;
    105         // don't consider very large or very small values for scaling
    106         // careful: this also excludes infinity and NaN values
    107         if (originalElement > -1.0E07 && originalElement < 1.0E07) {
    108           calculator.Add(originalElement, targetElement);
    109         }
     105        calculator.Add(originalElement, targetElement);
    110106      }
    111107
Note: See TracChangeset for help on using the changeset viewer.