Skip to content

Commit ae9ad33

Browse files
committed
Pushing packages
1 parent 31c82ac commit ae9ad33

405 files changed

Lines changed: 271052 additions & 37 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
/.vs
2-
packages
32
/Numerics/bin
43
/Numerics/obj
5-
/packages
64
/Test_Numerics/bin
75
/Test_Numerics/obj
86
/TestResults

Numerics/Data/Regression/LinearRegression.cs

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ public class LinearRegression
6565
public LinearRegression(Matrix x, Vector y, bool hasIntercept = true)
6666
{
6767

68-
if (y.Length != x.NumberOfRows) throw new ArgumentException("The y vector must be the same length as the x matrix.");
68+
if (y.Length != x.NumberOfRows) throw new ArgumentException("X and Y must have the same number of rows.");
6969
if (y.Length <= 2) throw new ArithmeticException("There must be at least three data points.");
7070
if (x.NumberOfColumns > y.Length) throw new ArithmeticException($"A regression of the requested order requires at least {x.NumberOfColumns} data points. Only {y.Length} data points have been provided.");
7171

7272
// Set inputs
7373
Y = y;
74-
X = x;
75-
this.hasIntercept = hasIntercept;
74+
X = hasIntercept ? AddInterceptColumn(x) : x;
75+
this.HasIntercept = hasIntercept;
7676
ParameterNames = new List<string>();
7777

7878
// Set model name
@@ -99,7 +99,10 @@ public LinearRegression(Matrix x, Vector y, bool hasIntercept = true)
9999
FitSVD();
100100
}
101101

102-
private bool hasIntercept;
102+
/// <summary>
103+
/// Determines if the linear model has an intercept.
104+
/// </summary>
105+
public bool HasIntercept { get; private set; }
103106

104107
/// <summary>
105108
/// The vector of response values.
@@ -136,6 +139,11 @@ public LinearRegression(Matrix x, Vector y, bool hasIntercept = true)
136139
/// </summary>
137140
public Matrix Covariance { get; private set; }
138141

142+
/// <summary>
143+
/// The residuals of the fitted linear model.
144+
/// </summary>
145+
public double[] Residuals { get; private set; }
146+
139147
/// <summary>
140148
/// The model standard error.
141149
/// </summary>
@@ -144,11 +152,8 @@ public LinearRegression(Matrix x, Vector y, bool hasIntercept = true)
144152
/// <summary>
145153
/// The data sample size.
146154
/// </summary>
147-
public int SampleSize
148-
{
149-
get { return Y.Length; }
150-
}
151-
155+
public int SampleSize => Y.Length;
156+
152157
/// <summary>
153158
/// The model degrees of freedom.
154159
/// </summary>
@@ -164,11 +169,6 @@ public int SampleSize
164169
/// </summary>
165170
public double AdjRSquared { get; private set; }
166171

167-
/// <summary>
168-
/// The residuals of the fitted linear model.
169-
/// </summary>
170-
public double[] Residuals { get; private set; }
171-
172172
/// <summary>
173173
/// Provides a standard summary output table in a list of strings.
174174
/// </summary>
@@ -211,7 +211,7 @@ public List<string> Summary()
211211
int dfR = lm.DegreesOfFreedom, dfF = DegreesOfFreedom;
212212
HypothesisTests.FtestModels(sseR, sseF, dfR, dfF, out F, out fP);
213213
string fPStrg = fP > 1E-4 ? fP.ToString("N4") : fP < 1E-15 ? "< 1E-15" : fP.ToString("E2");
214-
text.Add("F-statistic: " + F.ToString("N1") + ", on " + (hasIntercept ? Parameters.Count - 1 : Parameters.Count).ToString("N0") + " and " + DegreesOfFreedom.ToString("N0") + " DF, p-value: " + fPStrg);
214+
text.Add("F-statistic: " + F.ToString("N1") + ", on " + (HasIntercept ? Parameters.Count - 1 : Parameters.Count).ToString("N0") + " and " + DegreesOfFreedom.ToString("N0") + " DF, p-value: " + fPStrg);
215215
text.Add("");
216216

217217
// Residuals
@@ -230,29 +230,14 @@ public List<string> Summary()
230230
private void FitSVD()
231231
{
232232
double meanY = Statistics.Statistics.Mean(Y.ToArray());
233-
var xx = X;
234-
// see if we need to add an intercept column
235-
if (hasIntercept)
236-
{
237-
xx = new Matrix(X.NumberOfRows, X.NumberOfColumns + 1);
238-
for (int r = 0; r < X.NumberOfRows; r++)
239-
{
240-
xx[r, 0] = 1;
241-
for (int c = 0; c < X.NumberOfColumns; c++)
242-
{
243-
xx[r, c + 1] = X[r, c];
244-
}
245-
}
246-
}
247-
248-
int i, j, k, n = xx.NumberOfRows, m = xx.NumberOfColumns;
233+
int i, j, k, n = X.NumberOfRows, m = X.NumberOfColumns;
249234
double sse = 0.0, sst = 0.0, sum = 0.0;
250235
DegreesOfFreedom = n - m;
251236
Residuals = new double[n];
252237
Covariance = new Matrix(m);
253238

254239
// Estimate coefficients
255-
var svd = new SingularValueDecomposition(xx);
240+
var svd = new SingularValueDecomposition(X);
256241
double tol = 1E-12;
257242
double thresh = (tol > 0d ? tol * svd.W[0] : -1d);
258243
var betas = svd.Solve(Y, thresh); // vector of fitted coefficients
@@ -261,7 +246,7 @@ private void FitSVD()
261246
for (i = 0; i < n; i++)
262247
{
263248
sum = 0.0;
264-
for (j = 0; j < m; j++) sum += xx[i, j] * betas[j];
249+
for (j = 0; j < m; j++) sum += X[i, j] * betas[j];
265250
Residuals[i] = Y[i] - sum;
266251
sse += Tools.Sqr(Residuals[i]);
267252
sst += Tools.Sqr(Y[i] - meanY);
@@ -288,6 +273,21 @@ private void FitSVD()
288273

289274
}
290275

276+
/// <summary>
277+
/// Helper method to add an intercept column to the covariate matrix.
278+
/// </summary>
279+
/// <param name="x">The matrix of predictor values.</param>
280+
private static Matrix AddInterceptColumn(Matrix x)
281+
{
282+
Matrix result = new Matrix(x.NumberOfRows, x.NumberOfColumns + 1);
283+
for (int i = 0; i < x.NumberOfRows; i++)
284+
{
285+
result[i, 0] = 1.0;
286+
for (int j = 0; j < x.NumberOfColumns; j++)
287+
result[i, j + 1] = x[i, j];
288+
}
289+
return result;
290+
}
291291

292292
/// <summary>
293293
/// Returns the predicted Y values given the X-values.
@@ -298,7 +298,7 @@ public double[] Predict(Matrix x)
298298
var result = new double[x.NumberOfRows];
299299
for (int i = 0; i < x.NumberOfRows; i++)
300300
{
301-
if (hasIntercept == true)
301+
if (HasIntercept == true)
302302
{
303303
var values = new List<double>() { 1 };
304304
values.AddRange(x.Row(i));
@@ -325,7 +325,7 @@ public double[] Predict(Matrix x)
325325
for (int i = 0; i < x.NumberOfRows; i++)
326326
{
327327
double mu = 0;
328-
if (hasIntercept == true)
328+
if (HasIntercept == true)
329329
{
330330
var values = new List<double>() { 1 };
331331
values.AddRange(x.Row(i));
@@ -349,4 +349,5 @@ public double[] Predict(Matrix x)
349349
}
350350

351351
}
352+
352353
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* NOTICE:
3+
* The U.S. Army Corps of Engineers, Risk Management Center (USACE-RMC) makes no guarantees about
4+
* the results, or appropriateness of outputs, obtained from Numerics.
5+
*
6+
* LIST OF CONDITIONS:
7+
* Redistribution and use in source and binary forms, with or without modification, are permitted
8+
* provided that the following conditions are met:
9+
* ● Redistributions of source code must retain the above notice, this list of conditions, and the
10+
* following disclaimer.
11+
* ● Redistributions in binary form must reproduce the above notice, this list of conditions, and
12+
* the following disclaimer in the documentation and/or other materials provided with the distribution.
13+
* ● The names of the U.S. Government, the U.S. Army Corps of Engineers, the Institute for Water
14+
* Resources, or the Risk Management Center may not be used to endorse or promote products derived
15+
* from this software without specific prior written permission. Nor may the names of its contributors
16+
* be used to endorse or promote products derived from this software without specific prior
17+
* written permission.
18+
*
19+
* DISCLAIMER:
20+
* THIS SOFTWARE IS PROVIDED BY THE U.S. ARMY CORPS OF ENGINEERS RISK MANAGEMENT CENTER
21+
* (USACE-RMC) "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22+
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
* DISCLAIMED. IN NO EVENT SHALL USACE-RMC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
using Numerics.Mathematics.LinearAlgebra;
32+
using System;
33+
using System.Collections.Generic;
34+
using System.Linq;
35+
using System.Text;
36+
using System.Threading.Tasks;
37+
38+
namespace Numerics.MachineLearning
39+
{
40+
/// <summary>
41+
/// A class for performing generalized linear regression.
42+
/// </summary>
43+
/// <remarks>
44+
/// <para>
45+
/// <b> Authors: </b>
46+
/// Haden Smith, USACE Risk Management Center, cole.h.smith@usace.army.mil
47+
/// </para>
48+
/// </remarks>
49+
public class GeneralizedLinearModel
50+
{
51+
52+
public GeneralizedLinearModel(Matrix x, Vector y, bool hasIntercept = true)
53+
{
54+
if (y.Length != x.NumberOfRows) throw new ArgumentException("X and Y must have the same number of rows.");
55+
if (y.Length <= 2) throw new ArithmeticException("There must be at least three data points.");
56+
if (x.NumberOfColumns > y.Length) throw new ArithmeticException($"A regression of the requested order requires at least {x.NumberOfColumns} data points. Only {y.Length} data points have been provided.");
57+
58+
// Set inputs
59+
Y = y;
60+
X = hasIntercept ? AddInterceptColumn(x) : x;
61+
this.HasIntercept = hasIntercept;
62+
DegreesOfFreedom = y.Length - x.NumberOfRows;
63+
64+
// Set model name
65+
if (Y.Header == null || Y.Header.Length == 0)
66+
{
67+
Y.Header = "Y Data";
68+
}
69+
70+
// Set parameter names for summary report.
71+
ParameterNames = new List<string>();
72+
if (hasIntercept) ParameterNames.Add("Intercept");
73+
if (X.Header != null && X.Header.Length == x.NumberOfColumns)
74+
{
75+
ParameterNames.AddRange(X.Header);
76+
}
77+
else
78+
{
79+
for (int i = 1; i <= x.NumberOfColumns; i++)
80+
{
81+
ParameterNames.Add("β" + i);
82+
}
83+
}
84+
}
85+
86+
/// <summary>
87+
/// Determines if the linear model has an intercept.
88+
/// </summary>
89+
public bool HasIntercept { get; private set; }
90+
91+
/// <summary>
92+
/// The vector of response values.
93+
/// </summary>
94+
public Vector Y { get; private set; }
95+
96+
/// <summary>
97+
/// The matrix of predictor values.
98+
/// </summary>
99+
public Matrix X { get; private set; }
100+
101+
/// <summary>
102+
/// The list of estimated parameter values.
103+
/// </summary>
104+
public List<double> Parameters { get; private set; }
105+
106+
/// <summary>
107+
/// The list of the estimated parameter names.
108+
/// </summary>
109+
public List<string> ParameterNames { get; private set; }
110+
111+
/// <summary>
112+
/// The list of the estimated parameter standard errors.
113+
/// </summary>
114+
public List<double> ParameterStandardErrors { get; private set; }
115+
116+
/// <summary>
117+
/// The list of the estimated parameter t-statistics.
118+
/// </summary>
119+
public List<double> ParameterTStats { get; private set; }
120+
121+
/// <summary>
122+
/// The estimate parameter covariance matrix.
123+
/// </summary>
124+
public Matrix Covariance { get; private set; }
125+
126+
127+
/// <summary>
128+
/// The residuals of the fitted linear model.
129+
/// </summary>
130+
public double[] Residuals { get; private set; }
131+
132+
/// <summary>
133+
/// The model standard error.
134+
/// </summary>
135+
public double StandardError { get; private set; }
136+
137+
/// <summary>
138+
/// The data sample size.
139+
/// </summary>
140+
public int SampleSize => Y.Length;
141+
142+
/// <summary>
143+
/// The model degrees of freedom.
144+
/// </summary>
145+
public int DegreesOfFreedom { get; private set; }
146+
147+
/// <summary>
148+
/// The Coefficient of Determination (or R-squared).
149+
/// </summary>
150+
public double RSquared { get; private set; }
151+
152+
/// <summary>
153+
/// the Akaike Information Criterion (AIC).
154+
/// </summary>
155+
public double AIC { get; private set; }
156+
157+
/// <summary>
158+
/// the Akaike Information Criterion corrected for small sample sizes (AICc)
159+
/// </summary>
160+
public double AICc { get; private set; }
161+
162+
/// <summary>
163+
/// The Bayesian information criterion (BIC).
164+
/// </summary>
165+
public double BIC { get; private set; }
166+
167+
/// <summary>
168+
/// Estimate robust standard errors.
169+
/// </summary>
170+
public bool UseRobustSE { get; set; } = false;
171+
172+
private Func<double, double> _inverseLink;
173+
private Func<double, double> _inverseLinkDerivative;
174+
private Func<(double mu, double y), double> _logLikelihoodTerm;
175+
private Func<(double eta, double y), double> _logLikelihoodGradient;
176+
177+
/// <summary>
178+
/// Helper method to add an intercept column to the covariate matrix.
179+
/// </summary>
180+
/// <param name="x">The matrix of predictor values.</param>
181+
private static Matrix AddInterceptColumn(Matrix x)
182+
{
183+
Matrix result = new Matrix(x.NumberOfRows, x.NumberOfColumns + 1);
184+
for (int i = 0; i < x.NumberOfRows; i++)
185+
{
186+
result[i, 0] = 1.0;
187+
for (int j = 0; j < x.NumberOfColumns; j++)
188+
result[i, j + 1] = x[i, j];
189+
}
190+
return result;
191+
}
192+
193+
}
194+
}
18.3 KB
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)