Changeset 8704 for trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective
- Timestamp:
- 09/27/12 12:58:46 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs
r8664 r8704 20 20 #endregion 21 21 22 using System; 22 23 using System.Collections.Generic; 23 24 using System.Linq; 25 using AutoDiff; 24 26 using HeuristicLab.Common; 25 27 using HeuristicLab.Core; … … 100 102 public override IOperation Apply() { 101 103 AddResults(); 102 int seed = RandomParameter.ActualValue.Next();103 104 var solution = SymbolicExpressionTreeParameter.ActualValue; 104 105 double quality; … … 106 107 IEnumerable<int> constantOptimizationRows = GenerateRowsToEvaluate(ConstantOptimizationRowsPercentage.Value); 107 108 quality = OptimizeConstants(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, solution, ProblemDataParameter.ActualValue, 108 constantOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value, ConstantOptimizationI mprovement.Value, ConstantOptimizationIterations.Value, 0.001,109 constantOptimizationRows, ApplyLinearScalingParameter.ActualValue.Value, ConstantOptimizationIterations.Value, 109 110 EstimationLimitsParameter.ActualValue.Upper, EstimationLimitsParameter.ActualValue.Lower, 110 111 EvaluatedTreesParameter.ActualValue, EvaluatedTreeNodesParameter.ActualValue); … … 157 158 158 159 public static double OptimizeConstants(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, IRegressionProblemData problemData, 159 IEnumerable<int> rows, bool applyLinearScaling, double improvement, int iterations, double differentialStep, double upperEstimationLimit = double.MaxValue, double lowerEstimationLimit = double.MinValue, IntValue evaluatedTrees = null, IntValue evaluatedTreeNodes = null) { 160 IEnumerable<int> rows, bool applyLinearScaling, int maxIterations, double upperEstimationLimit = double.MaxValue, double lowerEstimationLimit = double.MinValue, IntValue evaluatedTrees = null, IntValue evaluatedTreeNodes = null) { 161 162 List<AutoDiff.Variable> variables = new List<AutoDiff.Variable>(); 163 List<AutoDiff.Variable> parameters = new List<AutoDiff.Variable>(); 164 List<string> variableNames = new List<string>(); 165 166 AutoDiff.Term func; 167 if (!TryTransformToAutoDiff(tree.Root.GetSubtree(0), variables, parameters, variableNames, out func)) return 0.0; 168 if (variableNames.Count == 0) return 0.0; 169 170 AutoDiff.IParametricCompiledTerm compiledFunc = AutoDiff.TermUtils.Compile(func, variables.ToArray(), parameters.ToArray()); 171 160 172 List<SymbolicExpressionTreeTerminalNode> terminalNodes = tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>().ToList(); 161 double[] c = new double[terminalNodes.Count]; 162 int treeLength = tree.Length; 163 164 //extract inital constants 165 for (int i = 0; i < terminalNodes.Count; i++) { 166 ConstantTreeNode constantTreeNode = terminalNodes[i] as ConstantTreeNode; 167 if (constantTreeNode != null) c[i] = constantTreeNode.Value; 168 VariableTreeNode variableTreeNode = terminalNodes[i] as VariableTreeNode; 169 if (variableTreeNode != null) c[i] = variableTreeNode.Weight; 170 } 171 172 double epsg = 0; 173 double epsf = improvement; 174 double epsx = 0; 175 int maxits = iterations; 176 double diffstep = differentialStep; 177 178 alglib.minlmstate state; 179 alglib.minlmreport report; 180 181 alglib.minlmcreatev(1, c, diffstep, out state); 182 alglib.minlmsetcond(state, epsg, epsf, epsx, maxits); 183 alglib.minlmoptimize(state, CreateCallBack(interpreter, tree, problemData, rows, applyLinearScaling, upperEstimationLimit, lowerEstimationLimit, treeLength, evaluatedTrees, evaluatedTreeNodes), null, terminalNodes); 184 alglib.minlmresults(state, out c, out report); 185 186 for (int i = 0; i < c.Length; i++) { 187 ConstantTreeNode constantTreeNode = terminalNodes[i] as ConstantTreeNode; 188 if (constantTreeNode != null) constantTreeNode.Value = c[i]; 189 VariableTreeNode variableTreeNode = terminalNodes[i] as VariableTreeNode; 190 if (variableTreeNode != null) variableTreeNode.Weight = c[i]; 191 } 192 193 return (state.fi[0] - 1) * -1; 194 } 195 196 private static alglib.ndimensional_fvec CreateCallBack(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling, double upperEstimationLimit, double lowerEstimationLimit, int treeLength, IntValue evaluatedTrees = null, IntValue evaluatedTreeNodes = null) { 197 return (double[] arg, double[] fi, object obj) => { 198 // update constants of tree 199 List<SymbolicExpressionTreeTerminalNode> terminalNodes = (List<SymbolicExpressionTreeTerminalNode>)obj; 200 for (int i = 0; i < terminalNodes.Count; i++) { 201 ConstantTreeNode constantTreeNode = terminalNodes[i] as ConstantTreeNode; 202 if (constantTreeNode != null) constantTreeNode.Value = arg[i]; 203 VariableTreeNode variableTreeNode = terminalNodes[i] as VariableTreeNode; 204 if (variableTreeNode != null) variableTreeNode.Weight = arg[i]; 205 } 206 207 double quality = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling); 208 209 fi[0] = 1 - quality; 210 if (evaluatedTrees != null) evaluatedTrees.Value++; 211 if (evaluatedTreeNodes != null) evaluatedTreeNodes.Value += treeLength; 173 double[] c = new double[variables.Count]; 174 175 { 176 c[0] = 0.0; 177 c[1] = 1.0; 178 //extract inital constants 179 int i = 2; 180 foreach (var node in terminalNodes) { 181 ConstantTreeNode constantTreeNode = node as ConstantTreeNode; 182 VariableTreeNode variableTreeNode = node as VariableTreeNode; 183 if (constantTreeNode != null) 184 c[i++] = constantTreeNode.Value; 185 else if (variableTreeNode != null && !variableTreeNode.Weight.IsAlmost(1.0)) 186 c[i++] = variableTreeNode.Weight; 187 } 188 } 189 190 alglib.lsfitstate state; 191 alglib.lsfitreport rep; 192 int info; 193 194 Dataset ds = problemData.Dataset; 195 double[,] x = new double[rows.Count(), variableNames.Count]; 196 int row = 0; 197 foreach (var r in rows) { 198 for (int col = 0; col < variableNames.Count; col++) { 199 x[row, col] = ds.GetDoubleValue(variableNames[col], r); 200 } 201 row++; 202 } 203 double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray(); 204 int n = x.GetLength(0); 205 int m = x.GetLength(1); 206 int k = c.Length; 207 208 alglib.ndimensional_pfunc function_cx_1_func = CreatePFunc(compiledFunc); 209 alglib.ndimensional_pgrad function_cx_1_grad = CreatePGrad(compiledFunc); 210 211 try { 212 alglib.lsfitcreatefg(x, y, c, n, m, k, false, out state); 213 alglib.lsfitsetcond(state, 0, 0, maxIterations); 214 alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, null, null); 215 alglib.lsfitresults(state, out info, out c, out rep); 216 217 } 218 catch (alglib.alglibexception) { 219 return 0.0; 220 } 221 { 222 // only when no error occurred 223 // set constants in tree 224 int i = 2; 225 foreach (var node in terminalNodes) { 226 ConstantTreeNode constantTreeNode = node as ConstantTreeNode; 227 VariableTreeNode variableTreeNode = node as VariableTreeNode; 228 if (constantTreeNode != null) 229 constantTreeNode.Value = c[i++]; 230 else if (variableTreeNode != null && !variableTreeNode.Weight.IsAlmost(1.0)) 231 variableTreeNode.Weight = c[i++]; 232 } 233 } 234 235 return SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate(interpreter, tree, lowerEstimationLimit, upperEstimationLimit, problemData, rows, applyLinearScaling); 236 } 237 238 private static alglib.ndimensional_pfunc CreatePFunc(AutoDiff.IParametricCompiledTerm compiledFunc) { 239 return (double[] c, double[] x, ref double func, object o) => { 240 func = compiledFunc.Evaluate(c, x); 212 241 }; 213 242 } 214 243 244 private static alglib.ndimensional_pgrad CreatePGrad(AutoDiff.IParametricCompiledTerm compiledFunc) { 245 return (double[] c, double[] x, ref double func, double[] grad, object o) => { 246 var tupel = compiledFunc.Differentiate(c, x); 247 func = tupel.Item2; 248 Array.Copy(tupel.Item1, grad, grad.Length); 249 }; 250 } 251 252 private static bool TryTransformToAutoDiff(ISymbolicExpressionTreeNode node, List<AutoDiff.Variable> variables, List<AutoDiff.Variable> parameters, List<string> variableNames, out AutoDiff.Term term) { 253 if (node.Symbol is Constant) { 254 var var = new AutoDiff.Variable(); 255 variables.Add(var); 256 term = var; 257 return true; 258 } 259 if (node.Symbol is Variable) { 260 // don't tune weights with a value of 1.0 because it was probably set by the simplifier 261 var varNode = node as VariableTreeNode; 262 var par = new AutoDiff.Variable(); 263 parameters.Add(par); 264 variableNames.Add(varNode.VariableName); 265 if (!varNode.Weight.IsAlmost(1.0)) { 266 var w = new AutoDiff.Variable(); 267 variables.Add(w); 268 term = AutoDiff.TermBuilder.Product(w, par); 269 } else { 270 term = par; 271 } 272 return true; 273 } 274 if (node.Symbol is Addition) { 275 List<AutoDiff.Term> terms = new List<Term>(); 276 foreach (var subTree in node.Subtrees) { 277 AutoDiff.Term t; 278 if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, out t)) { 279 term = null; 280 return false; 281 } 282 terms.Add(t); 283 } 284 term = AutoDiff.TermBuilder.Sum(terms); 285 return true; 286 } 287 if (node.Symbol is Multiplication) { 288 AutoDiff.Term a, b; 289 if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, out a) || 290 !TryTransformToAutoDiff(node.GetSubtree(1), variables, parameters, variableNames, out b)) { 291 term = null; 292 return false; 293 } else { 294 List<AutoDiff.Term> factors = new List<Term>(); 295 foreach (var subTree in node.Subtrees.Skip(2)) { 296 AutoDiff.Term f; 297 if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, out f)) { 298 term = null; 299 return false; 300 } 301 factors.Add(f); 302 } 303 term = AutoDiff.TermBuilder.Product(a, b, factors.ToArray()); 304 return true; 305 } 306 } 307 if (node.Symbol is Division) { 308 // only works for at least two subtrees 309 AutoDiff.Term a, b; 310 if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, out a) || 311 !TryTransformToAutoDiff(node.GetSubtree(1), variables, parameters, variableNames, out b)) { 312 term = null; 313 return false; 314 } else { 315 List<AutoDiff.Term> factors = new List<Term>(); 316 foreach (var subTree in node.Subtrees.Skip(2)) { 317 AutoDiff.Term f; 318 if (!TryTransformToAutoDiff(subTree, variables, parameters, variableNames, out f)) { 319 term = null; 320 return false; 321 } 322 factors.Add(1.0 / f); 323 } 324 term = AutoDiff.TermBuilder.Product(a, 1.0 / b, factors.ToArray()); 325 return true; 326 } 327 } 328 if (node.Symbol is Logarithm) { 329 AutoDiff.Term t; 330 if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, out t)) { 331 term = null; 332 return false; 333 } else { 334 term = AutoDiff.TermBuilder.Log(t); 335 return true; 336 } 337 } 338 if (node.Symbol is Exponential) { 339 AutoDiff.Term t; 340 if (!TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, out t)) { 341 term = null; 342 return false; 343 } else { 344 term = AutoDiff.TermBuilder.Exp(t); 345 return true; 346 } 347 } 348 if (node.Symbol is StartSymbol) { 349 var alpha = new AutoDiff.Variable(); 350 var beta = new AutoDiff.Variable(); 351 variables.Add(beta); 352 variables.Add(alpha); 353 AutoDiff.Term branchTerm; 354 if (TryTransformToAutoDiff(node.GetSubtree(0), variables, parameters, variableNames, out branchTerm)) { 355 term = branchTerm * alpha + beta; 356 return true; 357 } else { 358 term = null; 359 return false; 360 } 361 } 362 term = null; 363 return false; 364 } 215 365 } 216 366 }
Note: See TracChangeset
for help on using the changeset viewer.