private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs <IndexedItem <Tuple <T, double> > > e)
 {
     if (InvokeRequired)
     {
         Invoke(new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_ItemsRemoved), sender, e);
     }
     else
     {
         IndexedDataRow <T> row = null;
         valuesRowsTable.TryGetValue((IObservableList <Tuple <T, double> >)sender, out row);
         if (row != null)
         {
             if (row.Values.Count == 0)
             {
                 RemoveDataRow(row);
             }
             else
             {
                 Series rowSeries = chart.Series[row.Name];
                 if (!invisibleSeries.Contains(rowSeries))
                 {
                     rowSeries.Points.Clear();
                     FillSeriesWithRowValues(rowSeries, row);
                     RecalculateAxesScale(chart.ChartAreas[0]);
                     UpdateYCursorInterval();
                 }
             }
         }
     }
 }
        /// <summary>
        /// Add the DataRow as a series to the chart.
        /// </summary>
        /// <param name="row">DataRow to add as series to the chart.</param>
        protected virtual void AddDataRow(IndexedDataRow <T> row)
        {
            if (row.Values.Count == 0)
            {
                return;
            }

            Series series = new Series(row.Name);

            if (row.VisualProperties.DisplayName.Trim() != String.Empty)
            {
                series.LegendText = row.VisualProperties.DisplayName;
            }
            else
            {
                series.LegendText = row.Name;
            }
            ConfigureSeries(series, row);
            FillSeriesWithRowValues(series, row);

            chart.Series.Add(series);
            ConfigureChartArea(chart.ChartAreas[0]);
            RecalculateAxesScale(chart.ChartAreas[0]);
            UpdateYCursorInterval();
        }
 /// <summary>
 /// Automatically called for every existing data row and whenever a data row is added
 /// to the data table. Do not call this method directly.
 /// </summary>
 /// <param name="row">The DataRow that was added.</param>
 protected virtual void RegisterDataRowEvents(IndexedDataRow <T> row)
 {
     row.NameChanged             += new EventHandler(Row_NameChanged);
     row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
     valuesRowsTable.Add(row.Values, row);
     row.Values.ItemsAdded      += new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_ItemsAdded);
     row.Values.ItemsRemoved    += new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_ItemsRemoved);
     row.Values.ItemsReplaced   += new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_ItemsReplaced);
     row.Values.ItemsMoved      += new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_ItemsMoved);
     row.Values.CollectionReset += new CollectionItemsChangedEventHandler <IndexedItem <Tuple <T, double> > >(Values_CollectionReset);
 }
        /// <summary>
        /// Remove the corresponding series for a certain DataRow.
        /// </summary>
        /// <param name="row">DataRow which series should be removed.</param>
        protected virtual void RemoveDataRow(IndexedDataRow <T> row)
        {
            if (chart.Series.All(x => x.Name != row.Name))
            {
                return;
            }
            Series series = chart.Series[row.Name];

            chart.Series.Remove(series);
            if (invisibleSeries.Contains(series))
            {
                invisibleSeries.Remove(series);
            }
            RecalculateAxesScale(chart.ChartAreas[0]);
        }
示例#5
0
        public void TestIndexedDataTable()
        {
            var dt = new IndexedDataTable <int>("test", "test description");
            var dr = new IndexedDataRow <int>("test row");

            dr.Values.Add(Tuple.Create(1, 1.0));
            dr.Values.Add(Tuple.Create(2, 2.0));
            dr.Values.Add(Tuple.Create(3, 3.0));
            dt.Rows.Add(dr);
            var ser = new ProtoBufSerializer();

            ser.Serialize(dt, tempFile);
            var dt2 = (IndexedDataTable <int>)ser.Deserialize(tempFile);

            Assert.AreEqual(dt.Rows["test row"].Values[0], dt2.Rows["test row"].Values[0]);
            Assert.AreEqual(dt.Rows["test row"].Values[1], dt2.Rows["test row"].Values[1]);
            Assert.AreEqual(dt.Rows["test row"].Values[2], dt2.Rows["test row"].Values[2]);
        }
 private void FillSeriesWithRowValues(Series series, IndexedDataRow <T> row)
 {
     for (int i = 0; i < row.Values.Count; i++)
     {
         var value = row.Values[i];
         if (IsInvalidValue(value.Item2))
         {
             continue;
         }
         var point = new DataPoint();
         point.SetValueXY(value.Item1, value.Item2);
         if (i == row.Values.Count - 1)
         {
             point.Label             = series.Name;
             point.MarkerStyle       = MarkerStyle.Cross;
             point.MarkerSize        = 15;
             point.MarkerBorderWidth = 1;
         }
         series.Points.Add(point);
     }
 }
        private void CreateSolutionPath()
        {
            double[] lambda;
            double[] trainNMSE;
            double[] testNMSE;
            double[,] coeff;
            double[] intercept;
            RunElasticNetLinearRegression(Problem.ProblemData, Penality, out lambda, out trainNMSE, out testNMSE, out coeff, out intercept);

            var coeffTable = new IndexedDataTable <double>("Coefficients", "The paths of standarized coefficient values over different lambda values");

            coeffTable.VisualProperties.YAxisMaximumAuto = false;
            coeffTable.VisualProperties.YAxisMinimumAuto = false;
            coeffTable.VisualProperties.XAxisMaximumAuto = false;
            coeffTable.VisualProperties.XAxisMinimumAuto = false;

            coeffTable.VisualProperties.XAxisLogScale    = true;
            coeffTable.VisualProperties.XAxisTitle       = "Lambda";
            coeffTable.VisualProperties.YAxisTitle       = "Coefficients";
            coeffTable.VisualProperties.SecondYAxisTitle = "Number of variables";

            var nLambdas         = lambda.Length;
            var nCoeff           = coeff.GetLength(1);
            var dataRows         = new IndexedDataRow <double> [nCoeff];
            var allowedVars      = Problem.ProblemData.AllowedInputVariables.ToArray();
            var numNonZeroCoeffs = new int[nLambdas];

            var ds = Problem.ProblemData.Dataset;
            var doubleVariables          = allowedVars.Where(ds.VariableHasType <double>);
            var factorVariableNames      = allowedVars.Where(ds.VariableHasType <string>);
            var factorVariablesAndValues = ds.GetFactorVariableValues(factorVariableNames, Enumerable.Range(0, ds.Rows)); // must consider all factor values (in train and test set)

            {
                int i = 0;
                foreach (var factorVariableAndValues in factorVariablesAndValues)
                {
                    foreach (var factorValue in factorVariableAndValues.Value)
                    {
                        double sigma = ds.GetStringValues(factorVariableAndValues.Key)
                                       .Select(s => s == factorValue ? 1.0 : 0.0)
                                       .StandardDeviation(); // calc std dev of binary indicator
                        var path = Enumerable.Range(0, nLambdas).Select(r => Tuple.Create(lambda[r], coeff[r, i] * sigma)).ToArray();
                        dataRows[i] = new IndexedDataRow <double>(factorVariableAndValues.Key + "=" + factorValue, factorVariableAndValues.Key + "=" + factorValue, path);
                        i++;
                    }
                }

                foreach (var doubleVariable in doubleVariables)
                {
                    double sigma = ds.GetDoubleValues(doubleVariable).StandardDeviation();
                    var    path  = Enumerable.Range(0, nLambdas).Select(r => Tuple.Create(lambda[r], coeff[r, i] * sigma)).ToArray();
                    dataRows[i] = new IndexedDataRow <double>(doubleVariable, doubleVariable, path);
                    i++;
                }
                // add to coeffTable by total weight (larger area under the curve => more important);
                foreach (var r in dataRows.OrderByDescending(r => r.Values.Select(t => t.Item2).Sum(x => Math.Abs(x))))
                {
                    coeffTable.Rows.Add(r);
                }
            }

            for (int i = 0; i < coeff.GetLength(0); i++)
            {
                for (int j = 0; j < coeff.GetLength(1); j++)
                {
                    if (!coeff[i, j].IsAlmost(0.0))
                    {
                        numNonZeroCoeffs[i]++;
                    }
                }
            }
            if (lambda.Length > 2)
            {
                coeffTable.VisualProperties.XAxisMinimumFixedValue = Math.Pow(10, Math.Floor(Math.Log10(lambda.Last())));
                coeffTable.VisualProperties.XAxisMaximumFixedValue = Math.Pow(10, Math.Ceiling(Math.Log10(lambda.Skip(1).First())));
            }
            coeffTable.Rows.Add(new IndexedDataRow <double>("Number of variables", "The number of non-zero coefficients for each step in the path", lambda.Zip(numNonZeroCoeffs, (l, v) => Tuple.Create(l, (double)v))));
            coeffTable.Rows["Number of variables"].VisualProperties.ChartType   = DataRowVisualProperties.DataRowChartType.Points;
            coeffTable.Rows["Number of variables"].VisualProperties.SecondYAxis = true;

            Results.Add(new Result(coeffTable.Name, coeffTable.Description, coeffTable));

            var errorTable = new IndexedDataTable <double>("NMSE", "Path of NMSE values over different lambda values");

            errorTable.VisualProperties.YAxisMaximumAuto = false;
            errorTable.VisualProperties.YAxisMinimumAuto = false;
            errorTable.VisualProperties.XAxisMaximumAuto = false;
            errorTable.VisualProperties.XAxisMinimumAuto = false;

            errorTable.VisualProperties.YAxisMinimumFixedValue = 0;
            errorTable.VisualProperties.YAxisMaximumFixedValue = 1.0;
            errorTable.VisualProperties.XAxisLogScale          = true;
            errorTable.VisualProperties.XAxisTitle             = "Lambda";
            errorTable.VisualProperties.YAxisTitle             = "Normalized mean of squared errors (NMSE)";
            errorTable.VisualProperties.SecondYAxisTitle       = "Number of variables";
            errorTable.Rows.Add(new IndexedDataRow <double>("NMSE (train)", "Path of NMSE values over different lambda values", lambda.Zip(trainNMSE, (l, v) => Tuple.Create(l, v))));
            errorTable.Rows.Add(new IndexedDataRow <double>("NMSE (test)", "Path of NMSE values over different lambda values", lambda.Zip(testNMSE, (l, v) => Tuple.Create(l, v))));
            errorTable.Rows.Add(new IndexedDataRow <double>("Number of variables", "The number of non-zero coefficients for each step in the path", lambda.Zip(numNonZeroCoeffs, (l, v) => Tuple.Create(l, (double)v))));
            if (lambda.Length > 2)
            {
                errorTable.VisualProperties.XAxisMinimumFixedValue = Math.Pow(10, Math.Floor(Math.Log10(lambda.Last())));
                errorTable.VisualProperties.XAxisMaximumFixedValue = Math.Pow(10, Math.Ceiling(Math.Log10(lambda.Skip(1).First())));
            }
            errorTable.Rows["NMSE (train)"].VisualProperties.ChartType          = DataRowVisualProperties.DataRowChartType.Points;
            errorTable.Rows["NMSE (test)"].VisualProperties.ChartType           = DataRowVisualProperties.DataRowChartType.Points;
            errorTable.Rows["Number of variables"].VisualProperties.ChartType   = DataRowVisualProperties.DataRowChartType.Points;
            errorTable.Rows["Number of variables"].VisualProperties.SecondYAxis = true;

            Results.Add(new Result(errorTable.Name, errorTable.Description, errorTable));
        }
        private void ConfigureSeries(Series series, IndexedDataRow <T> row)
        {
            RemoveCustomPropertyIfExists(series, "PointWidth");
            series.BorderWidth     = 1;
            series.BorderDashStyle = ChartDashStyle.Solid;
            series.BorderColor     = Color.Empty;

            series.Color             = row.VisualProperties.Color;
            series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;

            series.SmartLabelStyle.Enabled = true;
            series.SmartLabelStyle.AllowOutsidePlotArea      = LabelOutsidePlotAreaStyle.No;
            series.SmartLabelStyle.CalloutLineAnchorCapStyle = LineAnchorCapStyle.None;
            series.SmartLabelStyle.CalloutLineColor          = series.Color;
            series.SmartLabelStyle.CalloutLineWidth          = 2;
            series.SmartLabelStyle.CalloutStyle       = LabelCalloutStyle.Underlined;
            series.SmartLabelStyle.IsOverlappedHidden = false;
            series.SmartLabelStyle.MaxMovingDistance  = 200;

            switch (row.VisualProperties.ChartType)
            {
            case DataRowVisualProperties.DataRowChartType.Line:
                series.ChartType       = SeriesChartType.FastLine;
                series.BorderWidth     = row.VisualProperties.LineWidth;
                series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
                break;

            case DataRowVisualProperties.DataRowChartType.Bars:
                // Bar is incompatible with anything but Bar and StackedBar*
                if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100))
                {
                    series.ChartType = SeriesChartType.Bar;
                    chart.ChartAreas[0].AxisX.Interval = 1;
                }
                else
                {
                    series.ChartType = SeriesChartType.FastPoint; //default
                    row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
                }
                break;

            case DataRowVisualProperties.DataRowChartType.Columns:
                series.ChartType = SeriesChartType.Column;
                break;

            case DataRowVisualProperties.DataRowChartType.Points:
                series.ChartType = SeriesChartType.FastPoint;
                break;

            case DataRowVisualProperties.DataRowChartType.StepLine:
                series.ChartType       = SeriesChartType.StepLine;
                series.BorderWidth     = row.VisualProperties.LineWidth;
                series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
                break;

            default:
                series.ChartType = SeriesChartType.FastPoint;
                break;
            }
            series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
            series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
            if (row.VisualProperties.DisplayName.Trim() != String.Empty)
            {
                series.LegendText = row.VisualProperties.DisplayName;
            }
            else
            {
                series.LegendText = row.Name;
            }
            series.ToolTip = series.LegendText + " X = #VALX, Y = #VALY";
        }
示例#9
0
        private static IndexedDataTable <double> CoefficientGraph(double[,] coeff, double[] lambda, IEnumerable <string> allowedVars, IDataset ds, bool showOnlyRelevantBasisFuncs = true)
        {
            var coeffTable = new IndexedDataTable <double>("Coefficients", "The paths of standarized coefficient values over different lambda values");

            coeffTable.VisualProperties.YAxisMaximumAuto = false;
            coeffTable.VisualProperties.YAxisMinimumAuto = false;
            coeffTable.VisualProperties.XAxisMaximumAuto = false;
            coeffTable.VisualProperties.XAxisMinimumAuto = false;

            coeffTable.VisualProperties.XAxisLogScale    = true;
            coeffTable.VisualProperties.XAxisTitle       = "Lambda";
            coeffTable.VisualProperties.YAxisTitle       = "Coefficients";
            coeffTable.VisualProperties.SecondYAxisTitle = "Number of variables";

            var nLambdas         = lambda.Length;
            var nCoeff           = coeff.GetLength(1);
            var dataRows         = new IndexedDataRow <double> [nCoeff];
            var numNonZeroCoeffs = new int[nLambdas];

            var doubleVariables          = allowedVars.Where(ds.VariableHasType <double>);
            var factorVariableNames      = allowedVars.Where(ds.VariableHasType <string>);
            var factorVariablesAndValues = ds.GetFactorVariableValues(factorVariableNames, Enumerable.Range(0, ds.Rows)); //must consider all factor values (in train and test set)

            for (int i = 0; i < coeff.GetLength(0); i++)
            {
                for (int j = 0; j < coeff.GetLength(1); j++)
                {
                    if (!coeff[i, j].IsAlmost(0.0))
                    {
                        numNonZeroCoeffs[i]++;
                    }
                }
            }

            {
                int i = 0;
                foreach (var factorVariableAndValues in factorVariablesAndValues)
                {
                    foreach (var factorValue in factorVariableAndValues.Value)
                    {
                        double sigma = ds.GetStringValues(factorVariableAndValues.Key)
                                       .Select(s => s == factorValue ? 1.0 : 0.0)
                                       .StandardDeviation(); // calc std dev of binary indicator
                        var path = Enumerable.Range(0, nLambdas).Select(r => Tuple.Create(lambda[r], coeff[r, i] * sigma)).ToArray();
                        dataRows[i] = new IndexedDataRow <double>(factorVariableAndValues.Key + "=" + factorValue, factorVariableAndValues.Key + "=" + factorValue, path);
                        i++;
                    }
                }

                foreach (var doubleVariable in doubleVariables)
                {
                    double sigma = ds.GetDoubleValues(doubleVariable).StandardDeviation();
                    var    path  = Enumerable.Range(0, nLambdas).Select(r => Tuple.Create(lambda[r], coeff[r, i] * sigma)).ToArray();
                    dataRows[i] = new IndexedDataRow <double>(doubleVariable, doubleVariable, path);
                    i++;
                }

                // add to coeffTable by total weight (larger area under the curve => more important);
                foreach (var r in dataRows.OrderByDescending(r => r.Values.Select(t => t.Item2).Sum(x => Math.Abs(x))))
                {
                    coeffTable.Rows.Add(r);
                }
            }

            if (lambda.Length > 2)
            {
                coeffTable.VisualProperties.XAxisMinimumFixedValue = Math.Pow(10, Math.Floor(Math.Log10(lambda.Last())));
                coeffTable.VisualProperties.XAxisMaximumFixedValue = Math.Pow(10, Math.Ceiling(Math.Log10(lambda.Skip(1).First())));
            }

            coeffTable.Rows.Add(new IndexedDataRow <double>("Number of variables", "The number of non-zero coefficients for each step in the path", lambda.Zip(numNonZeroCoeffs, (l, v) => Tuple.Create(l, (double)v))));
            coeffTable.Rows["Number of variables"].VisualProperties.ChartType   = DataRowVisualProperties.DataRowChartType.Points;
            coeffTable.Rows["Number of variables"].VisualProperties.SecondYAxis = true;

            return(coeffTable);
        }