Ticket #2857: PDP.patch
File PDP.patch, 23.7 KB (added by gkronber, 7 years ago) |
---|
-
Controls/PartialDependencePlot.cs
36 36 namespace HeuristicLab.Problems.DataAnalysis.Views { 37 37 public partial class PartialDependencePlot : UserControl, IPartialDependencePlot { 38 38 private ModifiableDataset sharedFixedVariables; // used for syncronising variable values between charts 39 private ModifiableDataset sharedIndependentVariables; 39 40 private ModifiableDataset internalDataset; // holds the x values for each point drawn 40 41 41 42 private CancellationTokenSource cancelCurrentRecalculateSource; … … 236 237 cancelCurrentRecalculateSource.Cancel(); 237 238 } 238 239 239 public void Configure(IEnumerable<IRegressionSolution> solutions, ModifiableDataset sharedFixedVariables, string freeVariable, int drawingSteps, bool initializeAxisRanges = true) { 240 public void Configure( 241 IEnumerable<IRegressionSolution> solutions, 242 ModifiableDataset sharedFixedVariables, 243 ModifiableDataset sharedIndependentVariables, 244 string freeVariable, int drawingSteps, bool initializeAxisRanges = true) { 240 245 if (!SolutionsCompatible(solutions)) 241 246 throw new ArgumentException("Solutions are not compatible with the problem data."); 242 247 this.freeVariable = freeVariable; … … 249 254 // this change is reflected in the internal dataset (where the value becomes a whole column) 250 255 if (this.sharedFixedVariables != null) 251 256 this.sharedFixedVariables.ItemChanged -= sharedFixedVariables_ItemChanged; 257 252 258 this.sharedFixedVariables = sharedFixedVariables; 253 259 this.sharedFixedVariables.ItemChanged += sharedFixedVariables_ItemChanged; 260 this.sharedIndependentVariables = sharedIndependentVariables; 254 261 255 262 RecalculateTrainingLimits(initializeAxisRanges); 256 263 RecalculateInternalDataset(); … … 285 292 OrderAndColorSeries(); 286 293 } 287 294 295 private async void SharedIndependentVariables_ItemChanged(object sender, EventArgs<int, int> e) { 296 await RecalculateAsync(true, false); 297 } 298 288 299 public async Task RecalculateAsync(bool updateOnFinish = true, bool resetYAxis = true) { 289 300 if (IsDisposed 290 301 || sharedFixedVariables == null || !solutions.Any() || string.IsNullOrEmpty(freeVariable) … … 316 327 calculationPendingLabel.Visible = false; 317 328 if (updateOnFinish) 318 329 Update(); 319 } 320 catch (OperationCanceledException) { } 321 catch (AggregateException ae) { 330 } catch (OperationCanceledException) { } catch (AggregateException ae) { 322 331 if (!ae.InnerExceptions.Any(e => e is OperationCanceledException)) 323 332 throw; 324 333 } … … 411 420 }; 412 421 series.LegendText = series.Name; 413 422 414 var confidenceBoundSolution = solution as IConfidenceRegressionSolution;423 //var confidenceBoundSolution = solution as IConfidenceRegressionSolution; 415 424 Series confidenceIntervalSeries = null; 416 if (confidenceBoundSolution != null) {417 418 419 420 421 422 423 }425 //if (confidenceBoundSolution != null) { 426 confidenceIntervalSeries = new Series { 427 ChartType = SeriesChartType.Range, 428 YValuesPerPoint = 2, 429 Name = "95% Conf. Interval " + series.Name, 430 IsVisibleInLegend = false 431 }; 432 //} 424 433 return Tuple.Create(series, confidenceIntervalSeries); 425 434 } 426 435 … … 467 476 private Task<DoubleLimit> UpdateSeriesDataAsync(IRegressionSolution solution, CancellationToken cancellationToken) { 468 477 return Task.Run(() => { 469 478 var xvalues = internalDataset.GetDoubleValues(FreeVariable).ToList(); 470 var yvalues = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList();479 var yvalues = GetSamples(solution).ToList(); 471 480 472 481 double min = double.MaxValue, max = double.MinValue; 473 482 474 483 var series = seriesCache[solution]; 475 484 for (int i = 0; i < xvalues.Count; i++) { 476 series.Points[i].SetValueXY(xvalues[i], yvalues[i]); 477 if (yvalues[i] < min) min = yvalues[i]; 478 if (yvalues[i] > max) max = yvalues[i]; 485 var avg = yvalues[i].Average(); 486 series.Points[i].SetValueXY(xvalues[i], avg); 487 if (avg < min) min = avg; 488 if (avg > max) max = avg; 479 489 } 480 490 481 491 cancellationToken.ThrowIfCancellationRequested(); 482 492 483 var confidenceBoundSolution = solution as IConfidenceRegressionSolution; 484 if (confidenceBoundSolution != null) { 485 var confidenceIntervalSeries = ciSeriesCache[solution]; 486 var variances = confidenceBoundSolution.Model.GetEstimatedVariances(internalDataset, Enumerable.Range(0, internalDataset.Rows)).ToList(); 487 for (int i = 0; i < xvalues.Count; i++) { 488 var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]); 489 var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]); 490 confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper); 491 if (lower < min) min = lower; 492 if (upper > max) max = upper; 493 } 493 // var confidenceBoundSolution = solution as IConfidenceRegressionSolution; 494 // if (confidenceBoundSolution != null) { 495 // var confidenceIntervalSeries = ciSeriesCache[solution]; 496 // var variances = GetEstimatedVariance(confidenceBoundSolution).ToList(); 497 // for (int i = 0; i < xvalues.Count; i++) { 498 // var lower = yvalues[i] - 1.96 * Math.Sqrt(variances[i]); 499 // var upper = yvalues[i] + 1.96 * Math.Sqrt(variances[i]); 500 // confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper); 501 // if (lower < min) min = lower; 502 // if (upper > max) max = upper; 503 // } 504 // } 505 var confidenceIntervalSeries = ciSeriesCache[solution]; 506 for (int i = 0; i < xvalues.Count; i++) { 507 var avg = yvalues[i].Average(); 508 var variance = yvalues[i].Variance(); 509 var lower = avg - 1.96 * Math.Sqrt(variance); 510 var upper = avg + 1.96 * Math.Sqrt(variance); 511 confidenceIntervalSeries.Points[i].SetValueXY(xvalues[i], lower, upper); 512 if (lower < min) min = lower; 513 if (upper > max) max = upper; 494 514 } 495 515 496 516 cancellationToken.ThrowIfCancellationRequested(); … … 498 518 }, cancellationToken); 499 519 } 500 520 521 private IEnumerable<double[]> GetSamples(IRegressionSolution solution) { 522 var independentVarNames = sharedIndependentVariables.DoubleVariables.ToArray(); 523 524 var predictions = new List<double[]>(); 525 for (int rIdx = 0; rIdx < sharedIndependentVariables.Rows; rIdx++) { 526 foreach (var varName in independentVarNames) { 527 var varVal = sharedIndependentVariables.GetDoubleValue(varName, rIdx); 528 if (internalDataset.VariableNames.Contains(varName)) 529 internalDataset.ReplaceVariable(varName, Enumerable.Repeat(varVal, internalDataset.Rows).ToList()); 530 else 531 internalDataset.AddVariable(varName, Enumerable.Repeat(varVal, internalDataset.Rows).ToList()); 532 533 } 534 var pred = solution.Model.GetEstimatedValues(internalDataset, Enumerable.Range(0, internalDataset.Rows)); 535 predictions.Add(pred.ToArray()); 536 } 537 for (int i = 0; i < internalDataset.Rows; i++) { 538 yield return predictions.Select(p => p[i]).ToArray(); 539 } 540 } 541 501 542 private void ResizeAllSeriesData() { 502 543 if (internalDataset == null) 503 544 return; -
Regression/RegressionSolutionGradientView.cs
93 93 var newTrackbars = CreateConfiguration(); 94 94 95 95 sharedFixedVariables = new ModifiableDataset(variableNames, newTrackbars.Select(tb => new List<double>(1) { (double)tb.Value })); 96 _partialDependencePlot.Configure(new[] { Content }, sharedFixedVariables, variableNames.First(), DrawingSteps);96 _partialDependencePlot.Configure(new[] { Content }, sharedFixedVariables, new ModifiableDataset(), variableNames.First(), DrawingSteps); 97 97 await _partialDependencePlot.RecalculateAsync(); 98 98 99 99 // Add to table and observable lists -
Regression/RegressionSolutionPartialDependencePlotView.cs
39 39 private readonly Dictionary<string, DensityChart> densityCharts; 40 40 private readonly Dictionary<string, Panel> groupingPanels; 41 41 private ModifiableDataset sharedFixedVariables; 42 private ModifiableDataset sharedIndependentVariables; 42 43 43 44 private const int Points = 200; 44 45 private int MaxColumns = 4; … … 45 46 46 47 private IEnumerable<string> VisibleVariables { 47 48 get { 48 foreach (ListViewItem item in variableListView.CheckedItems) 49 yield return item.Text; 49 for (int i = 0; i < checkedVariableList.Items.Count; i++) { 50 var item = checkedVariableList.Items[i]; 51 if (checkedVariableList.GetItemCheckState(i) == CheckState.Checked) 52 yield return (string)item; 53 } 50 54 } 51 55 } 52 56 private IEnumerable<IPartialDependencePlot> VisiblePartialDependencePlots { … … 133 137 sharedFixedVariables.ItemChanged -= SharedFixedVariables_ItemChanged; 134 138 135 139 sharedFixedVariables = new ModifiableDataset(doubleVariables.Concat(factorVariables), doubleVariableValues.Concat(factorVariableValues)); 140 sharedIndependentVariables = new ModifiableDataset(new string[] { "$$$RowIdx" }, new IList[] { problemData.TrainingIndices.ToList() }); 136 141 137 142 138 143 // create controls … … 140 145 densityCharts.Clear(); 141 146 groupingPanels.Clear(); 142 147 foreach (var variableName in doubleVariables) { 143 var plot = CreatePartialDependencePlot(variableName, sharedFixedVariables );148 var plot = CreatePartialDependencePlot(variableName, sharedFixedVariables, sharedIndependentVariables); 144 149 partialDependencePlots.Add(variableName, plot); 145 150 146 151 var densityChart = new DensityChart() { … … 218 223 panel.Controls.Add(plot); 219 224 groupingPanels.Add(variableName, panel); 220 225 } 226 221 227 // update variable list 222 variableListView.ItemChecked -= variableListView_ItemChecked;223 variableListView.Items.Clear();228 checkedVariableList.ItemCheck -= checkedVariableList_ItemCheck; 229 checkedVariableList.Items.Clear(); 224 230 foreach (var variable in allowedInputVariables) 225 variableListView.Items.Add(key: variable, text: variable, imageIndex: 0);231 checkedVariableList.Items.Add(variable, isChecked: Content.Model.VariablesUsedForPrediction.Contains(variable)); 226 232 227 foreach (var variable in Content.Model.VariablesUsedForPrediction) 228 variableListView.Items[variable].Checked = true; 229 variableListView.ItemChecked += variableListView_ItemChecked; 233 checkedVariableList.ItemCheck += checkedVariableList_ItemCheck; 230 234 231 235 sharedFixedVariables.ItemChanged += SharedFixedVariables_ItemChanged; 232 236 … … 294 298 } 295 299 } 296 300 } 297 private PartialDependencePlot CreatePartialDependencePlot(string variableName, ModifiableDataset sharedFixedVariables ) {301 private PartialDependencePlot CreatePartialDependencePlot(string variableName, ModifiableDataset sharedFixedVariables, ModifiableDataset sharedIndependentVariables) { 298 302 var plot = new PartialDependencePlot { 299 303 Dock = DockStyle.Fill, 300 304 Margin = Padding.Empty, … … 314 318 if (recalculations.All(t => t.IsCompleted)) 315 319 SetupYAxis(); 316 320 }; 317 plot.Configure(new[] { Content }, sharedFixedVariables, variableName, Points);321 plot.Configure(new[] { Content }, sharedFixedVariables, sharedIndependentVariables, variableName, Points); 318 322 plot.SolutionAdded += partialDependencePlot_SolutionAdded; 319 323 plot.SolutionRemoved += partialDependencePlot_SolutionRemoved; 320 324 return plot; … … 372 376 var tl = partialDependencePlotTableLayout; 373 377 tl.Controls.Clear(); 374 378 int row = 0, column = 0; 375 double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single(); 379 double yValue = Content.Model.GetEstimatedValues(sharedFixedVariables, new[] { 0 }).Single(); // TODO mean estimation 376 380 string title = Content.ProblemData.TargetVariable + ": " + yValue.ToString("G5", CultureInfo.CurrentCulture); 377 381 378 382 foreach (var v in VisibleVariables) { … … 427 431 } 428 432 } 429 433 430 private async void variableListView_ItemChecked(object sender, ItemCheckedEventArgs e) { 431 var item = e.Item; 432 var variable = item.Text; 434 435 private async void checkedVariableList_ItemCheck(object sender, ItemCheckEventArgs e) { 436 // workaround to set the checkedState of the item to the new value so that remaining code works 437 // see https://stackoverflow.com/questions/3666682/which-checkedlistbox-event-triggers-after-a-item-is-checked 438 // we handle three states here 439 440 CheckedListBox clb = (CheckedListBox)sender; 441 // Switch off event handler 442 clb.ItemCheck -= checkedVariableList_ItemCheck; 443 CheckState newCheckState; 444 if (e.CurrentValue == CheckState.Unchecked) newCheckState = CheckState.Checked; 445 else if (e.CurrentValue == CheckState.Checked) newCheckState = CheckState.Indeterminate; 446 else newCheckState = CheckState.Unchecked; 447 e.NewValue = newCheckState; 448 clb.SetItemCheckState(e.Index, newCheckState); 449 // Switch on event handler 450 clb.ItemCheck += checkedVariableList_ItemCheck; 451 452 var itemChecked = newCheckState == CheckState.Checked; 453 var item = checkedVariableList.Items[e.Index]; 454 var variable = (string)item; 433 455 var plot = partialDependencePlots[variable]; 434 456 var chartsPanel = groupingPanels[variable]; 435 457 var tl = partialDependencePlotTableLayout; 436 458 437 tl.SuspendLayout(); 438 if (item.Checked) { 439 tl.Controls.Add(chartsPanel); 440 await plot.RecalculateAsync(false, false); 459 460 if (newCheckState == CheckState.Indeterminate) { 461 tl.Controls.Remove(chartsPanel); 462 if (!sharedIndependentVariables.DoubleVariables.Contains(variable)) { 463 sharedIndependentVariables.AddVariable(variable, Content.ProblemData.Dataset.GetDoubleValues(variable, Content.ProblemData.TrainingIndices)); 464 } 441 465 } else { 442 tl.Controls.Remove(chartsPanel); 466 if (sharedIndependentVariables.DoubleVariables.Contains(variable)) 467 sharedIndependentVariables.RemoveVariable(variable); 443 468 } 444 445 if (tl.Controls.Count > 0) { 446 SetupYAxis(); 447 ReOrderControls(); 448 SetStyles(); 449 } 450 tl.ResumeLayout(); 451 tl.Refresh(); 452 densityComboBox_SelectedIndexChanged(this, EventArgs.Empty); 469 RecalculateAndRelayoutCharts(); 453 470 } 454 471 455 472 private void automaticYAxisCheckBox_CheckedChanged(object sender, EventArgs e) { -
Regression/RegressionSolutionPartialDependencePlotView.Designer.cs
24 24 /// </summary> 25 25 private void InitializeComponent() { 26 26 this.components = new System.ComponentModel.Container(); 27 this.variableListView = new System.Windows.Forms.ListView();28 27 this.partialDependencePlotTableLayout = new System.Windows.Forms.TableLayoutPanel(); 29 28 this.yAxisConfigGroupBox = new System.Windows.Forms.GroupBox(); 30 29 this.limitView = new HeuristicLab.Problems.DataAnalysis.Views.DoubleLimitView(); 31 30 this.automaticYAxisCheckBox = new System.Windows.Forms.CheckBox(); 32 31 this.densityGroupBox = new System.Windows.Forms.GroupBox(); 32 this.columnsNumericUpDown = new System.Windows.Forms.NumericUpDown(); 33 33 this.columnsLabel = new System.Windows.Forms.Label(); 34 34 this.densityComboBox = new System.Windows.Forms.ComboBox(); 35 35 this.label1 = new System.Windows.Forms.Label(); 36 36 this.configSplitContainer = new System.Windows.Forms.SplitContainer(); 37 37 this.variableGroupBox = new System.Windows.Forms.GroupBox(); 38 this.checkedVariableList = new System.Windows.Forms.CheckedListBox(); 38 39 this.scrollPanel = new System.Windows.Forms.Panel(); 39 40 this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components); 40 this.columnsNumericUpDown = new System.Windows.Forms.NumericUpDown();41 41 this.yAxisConfigGroupBox.SuspendLayout(); 42 42 this.densityGroupBox.SuspendLayout(); 43 ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).BeginInit(); 43 44 ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).BeginInit(); 44 45 this.configSplitContainer.Panel1.SuspendLayout(); 45 46 this.configSplitContainer.Panel2.SuspendLayout(); … … 47 48 this.variableGroupBox.SuspendLayout(); 48 49 this.scrollPanel.SuspendLayout(); 49 50 ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit(); 50 ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).BeginInit();51 51 this.SuspendLayout(); 52 52 // 53 // variableListView54 //55 this.variableListView.CheckBoxes = true;56 this.variableListView.Dock = System.Windows.Forms.DockStyle.Fill;57 this.variableListView.Location = new System.Drawing.Point(3, 16);58 this.variableListView.Name = "variableListView";59 this.variableListView.Size = new System.Drawing.Size(163, 478);60 this.variableListView.TabIndex = 0;61 this.variableListView.UseCompatibleStateImageBehavior = false;62 this.variableListView.View = System.Windows.Forms.View.List;63 this.variableListView.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.variableListView_ItemChecked);64 //65 53 // partialDependencePlotTableLayout 66 54 // 67 55 this.partialDependencePlotTableLayout.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) … … 126 114 this.densityGroupBox.TabStop = false; 127 115 this.densityGroupBox.Text = "Settings"; 128 116 // 117 // columnsNumericUpDown 118 // 119 this.columnsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 120 | System.Windows.Forms.AnchorStyles.Right))); 121 this.columnsNumericUpDown.Location = new System.Drawing.Point(66, 46); 122 this.columnsNumericUpDown.Minimum = new decimal(new int[] { 123 1, 124 0, 125 0, 126 0}); 127 this.columnsNumericUpDown.Name = "columnsNumericUpDown"; 128 this.columnsNumericUpDown.Size = new System.Drawing.Size(94, 20); 129 this.columnsNumericUpDown.TabIndex = 1; 130 this.columnsNumericUpDown.Value = new decimal(new int[] { 131 4, 132 0, 133 0, 134 0}); 135 this.columnsNumericUpDown.ValueChanged += new System.EventHandler(this.columnsNumericUpDown_ValueChanged); 136 // 129 137 // columnsLabel 130 138 // 131 139 this.columnsLabel.AutoSize = true; … … 184 192 // 185 193 // variableGroupBox 186 194 // 187 this.variableGroupBox.Controls.Add(this. variableListView);195 this.variableGroupBox.Controls.Add(this.checkedVariableList); 188 196 this.variableGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; 189 197 this.variableGroupBox.Location = new System.Drawing.Point(0, 151); 190 198 this.variableGroupBox.Name = "variableGroupBox"; … … 193 201 this.variableGroupBox.TabStop = false; 194 202 this.variableGroupBox.Text = "Variables"; 195 203 // 204 // checkedVariableList 205 // 206 this.checkedVariableList.CheckOnClick = true; 207 this.checkedVariableList.Dock = System.Windows.Forms.DockStyle.Fill; 208 this.checkedVariableList.FormattingEnabled = true; 209 this.checkedVariableList.Location = new System.Drawing.Point(3, 16); 210 this.checkedVariableList.Name = "checkedVariableList"; 211 this.checkedVariableList.Size = new System.Drawing.Size(163, 478); 212 this.checkedVariableList.TabIndex = 0; 213 // 196 214 // scrollPanel 197 215 // 198 216 this.scrollPanel.Controls.Add(this.partialDependencePlotTableLayout); … … 207 225 this.errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink; 208 226 this.errorProvider.ContainerControl = this; 209 227 // 210 // columnsNumericUpDown211 //212 this.columnsNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)213 | System.Windows.Forms.AnchorStyles.Right)));214 this.columnsNumericUpDown.Location = new System.Drawing.Point(66, 46);215 this.columnsNumericUpDown.Minimum = new decimal(new int[] {216 1,217 0,218 0,219 0});220 this.columnsNumericUpDown.Name = "columnsNumericUpDown";221 this.columnsNumericUpDown.Size = new System.Drawing.Size(94, 20);222 this.columnsNumericUpDown.TabIndex = 1;223 this.columnsNumericUpDown.Value = new decimal(new int[] {224 4,225 0,226 0,227 0});228 this.columnsNumericUpDown.ValueChanged += new System.EventHandler(this.columnsNumericUpDown_ValueChanged);229 //230 228 // RegressionSolutionPartialDependencePlotView 231 229 // 232 230 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); … … 238 236 this.yAxisConfigGroupBox.PerformLayout(); 239 237 this.densityGroupBox.ResumeLayout(false); 240 238 this.densityGroupBox.PerformLayout(); 239 ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).EndInit(); 241 240 this.configSplitContainer.Panel1.ResumeLayout(false); 242 241 this.configSplitContainer.Panel2.ResumeLayout(false); 243 242 ((System.ComponentModel.ISupportInitialize)(this.configSplitContainer)).EndInit(); … … 246 245 this.scrollPanel.ResumeLayout(false); 247 246 this.scrollPanel.PerformLayout(); 248 247 ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit(); 249 ((System.ComponentModel.ISupportInitialize)(this.columnsNumericUpDown)).EndInit();250 248 this.ResumeLayout(false); 251 249 252 250 } 253 251 254 252 #endregion 255 256 private System.Windows.Forms.ListView variableListView;257 253 private System.Windows.Forms.TableLayoutPanel partialDependencePlotTableLayout; 258 254 private System.Windows.Forms.GroupBox yAxisConfigGroupBox; 259 255 private System.Windows.Forms.CheckBox automaticYAxisCheckBox; … … 267 263 private System.Windows.Forms.ErrorProvider errorProvider; 268 264 private System.Windows.Forms.Label label1; 269 265 private System.Windows.Forms.NumericUpDown columnsNumericUpDown; 266 private System.Windows.Forms.CheckedListBox checkedVariableList; 270 267 } 271 268 }