- Timestamp:
- 01/04/22 10:43:14 (3 years ago)
- Location:
- branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/NMSESingleObjectiveConstraintsEvaluator.cs
r18146 r18178 247 247 248 248 if (OptimizeParameters) 249 SymbolicRegressionParameterOptimizationEvaluator.OptimizeParameters(249 Optimize( 250 250 interpreter, tree, 251 251 problemData, rows, 252 applyLinearScaling: false, // Tree already contains scaling terms253 252 ParameterOptimizationIterations, 254 253 updateVariableWeights: true, … … 268 267 PenalityFactor); 269 268 } 269 270 public static double Optimize(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, 271 ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable<int> rows, 272 int maxIterations, bool updateVariableWeights = true, 273 double lowerEstimationLimit = double.MinValue, double upperEstimationLimit = double.MaxValue, 274 bool updateParametersInTree = true, Action<double[], double, object> iterationCallback = null, EvaluationsCounter counter = null) { 275 276 // Numeric parameters in the tree become variables for parameter optimization. 277 // Variables in the tree become parameters (fixed values) for parameter optimization. 278 // For each parameter (variable in the original tree) we store the 279 // variable name, variable value (for factor vars) and lag as a DataForVariable object. 280 // A dictionary is used to find parameters 281 double[] initialParameters; 282 var parameters = new List<TreeToAutoDiffTermConverter.DataForVariable>(); 283 284 TreeToAutoDiffTermConverter.ParametricFunction func; 285 TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad; 286 if (!TreeToAutoDiffTermConverter.TryConvertToAutoDiff(tree, updateVariableWeights, addLinearScalingTerms: false, out parameters, out initialParameters, out func, out func_grad)) 287 throw new NotSupportedException("Could not optimize parameters of symbolic expression tree due to not supported symbols used in the tree."); 288 var parameterEntries = parameters.ToArray(); // order of entries must be the same for x 289 290 // extract inital parameters 291 double[] c = (double[])initialParameters.Clone(); 292 293 double originalQuality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate( 294 tree, problemData, rows, 295 interpreter, applyLinearScaling: false, 296 lowerEstimationLimit, 297 upperEstimationLimit); 298 299 if (counter == null) counter = new EvaluationsCounter(); 300 var rowEvaluationsCounter = new EvaluationsCounter(); 301 302 alglib.lsfitstate state; 303 alglib.lsfitreport rep; 304 int retVal; 305 306 IDataset ds = problemData.Dataset; 307 double[,] x = new double[rows.Count(), parameters.Count]; 308 int row = 0; 309 foreach (var r in rows) { 310 int col = 0; 311 foreach (var info in parameterEntries) { 312 if (ds.VariableHasType<double>(info.variableName)) { 313 x[row, col] = ds.GetDoubleValue(info.variableName, r + info.lag); 314 } else if (ds.VariableHasType<string>(info.variableName)) { 315 x[row, col] = ds.GetStringValue(info.variableName, r) == info.variableValue ? 1 : 0; 316 } else throw new InvalidProgramException("found a variable of unknown type"); 317 col++; 318 } 319 row++; 320 } 321 double[] y = ds.GetDoubleValues(problemData.TargetVariable, rows).ToArray(); 322 int n = x.GetLength(0); 323 int m = x.GetLength(1); 324 int k = c.Length; 325 326 alglib.ndimensional_pfunc function_cx_1_func = CreatePFunc(func); 327 alglib.ndimensional_pgrad function_cx_1_grad = CreatePGrad(func_grad); 328 alglib.ndimensional_rep xrep = (p, f, obj) => iterationCallback(p, f, obj); 329 330 try { 331 alglib.lsfitcreatefg(x, y, c, n, m, k, false, out state); 332 alglib.lsfitsetcond(state, 0.0, maxIterations); 333 alglib.lsfitsetxrep(state, iterationCallback != null); 334 alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, xrep, rowEvaluationsCounter); 335 alglib.lsfitresults(state, out retVal, out c, out rep); 336 } catch (ArithmeticException) { 337 return originalQuality; 338 } catch (alglib.alglibexception) { 339 return originalQuality; 340 } 341 342 counter.FunctionEvaluations += rowEvaluationsCounter.FunctionEvaluations / n; 343 counter.GradientEvaluations += rowEvaluationsCounter.GradientEvaluations / n; 344 345 //retVal == -7 => parameter optimization failed due to wrong gradient 346 // -8 => optimizer detected NAN / INF in the target 347 // function and/ or gradient 348 if (retVal != -7 && retVal != -8) { 349 UpdateParameters(tree, c, updateVariableWeights); 350 } 351 var quality = SymbolicRegressionSingleObjectiveMeanSquaredErrorEvaluator.Calculate( 352 tree, problemData, rows, 353 interpreter, applyLinearScaling: false, 354 lowerEstimationLimit, upperEstimationLimit); 355 356 if (!updateParametersInTree) UpdateParameters(tree, initialParameters, updateVariableWeights); 357 358 if (originalQuality < quality || double.IsNaN(quality)) { 359 UpdateParameters(tree, initialParameters, updateVariableWeights); 360 return originalQuality; 361 } 362 return quality; 363 } 364 365 private static void UpdateParameters(ISymbolicExpressionTree tree, double[] parameters, bool updateVariableWeights) { 366 int i = 0; 367 foreach (var node in tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>()) { 368 NumberTreeNode numberTreeNode = node as NumberTreeNode; 369 VariableTreeNodeBase variableTreeNodeBase = node as VariableTreeNodeBase; 370 FactorVariableTreeNode factorVarTreeNode = node as FactorVariableTreeNode; 371 if (numberTreeNode != null) { 372 if (numberTreeNode.Parent.Symbol is Power 373 && numberTreeNode.Parent.GetSubtree(1) == numberTreeNode) continue; // exponents in powers are not optimizated (see TreeToAutoDiffTermConverter) 374 numberTreeNode.Value = parameters[i++]; 375 } else if (updateVariableWeights && variableTreeNodeBase != null) 376 variableTreeNodeBase.Weight = parameters[i++]; 377 else if (factorVarTreeNode != null) { 378 for (int j = 0; j < factorVarTreeNode.Weights.Length; j++) 379 factorVarTreeNode.Weights[j] = parameters[i++]; 380 } 381 } 382 } 383 384 private static alglib.ndimensional_pfunc CreatePFunc(TreeToAutoDiffTermConverter.ParametricFunction func) { 385 return (double[] c, double[] x, ref double fx, object o) => { 386 fx = func(c, x); 387 var counter = (EvaluationsCounter)o; 388 counter.FunctionEvaluations++; 389 }; 390 } 391 392 private static alglib.ndimensional_pgrad CreatePGrad(TreeToAutoDiffTermConverter.ParametricFunctionGradient func_grad) { 393 return (double[] c, double[] x, ref double fx, double[] grad, object o) => { 394 var tuple = func_grad(c, x); 395 fx = tuple.Item2; 396 Array.Copy(tuple.Item1, grad, grad.Length); 397 var counter = (EvaluationsCounter)o; 398 counter.GradientEvaluations++; 399 }; 400 } 401 402 public class EvaluationsCounter { 403 public int FunctionEvaluations = 0; 404 public int GradientEvaluations = 0; 405 } 270 406 } 271 407 } -
branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructuredSymbolicRegressionSingleObjectiveProblem.cs
r18177 r18178 57 57 } 58 58 59 public SymbolicRegressionSingleObjectiveEvaluator TreeEvaluator => TreeEvaluatorParameter.Value; 60 59 61 public StructureTemplate StructureTemplate => StructureTemplateParameter.Value; 60 62 … … 199 201 var tree = BuildTree(individual); 200 202 201 if (StructureTemplate.ApplyLinearScaling) { 203 // NMSEConstraintsEvaluator sets linear scaling terms itself 204 if (StructureTemplate.ApplyLinearScaling && !(TreeEvaluator is NMSESingleObjectiveConstraintsEvaluator)) { 202 205 AdjustLinearScalingParams(ProblemData, tree, Interpreter); 203 206 } … … 205 208 individual[SymbolicExpressionTreeName] = tree; 206 209 207 return TreeEvaluator Parameter.Value.Evaluate(210 return TreeEvaluator.Evaluate( 208 211 tree, ProblemData, 209 212 ProblemData.TrainingIndices,
Note: See TracChangeset
for help on using the changeset viewer.