-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathLinearRegression.cs
More file actions
100 lines (85 loc) · 3.25 KB
/
LinearRegression.cs
File metadata and controls
100 lines (85 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using System;
using System.Collections.Generic;
using System.Linq;
namespace Algorithms.MachineLearning;
/// <summary>
/// Implements simple linear regression for one independent variable (univariate).
/// Linear regression is a supervised learning algorithm used to model the relationship
/// between a scalar dependent variable (Y) and an independent variable (X).
/// The model fits a line: Y = a + bX, where 'a' is the intercept and 'b' is the slope.
/// </summary>
public class LinearRegression
{
// Intercept (a) and slope (b) of the fitted line
public double Intercept { get; private set; }
public double Slope { get; private set; }
public bool IsFitted { get; private set; }
/// <summary>
/// Fits the linear regression model to the provided data.
/// </summary>
/// <param name="x">List of independent variable values.</param>
/// <param name="y">List of dependent variable values.</param>
/// <exception cref="ArgumentException">Thrown if input lists are null, empty, or of different lengths.</exception>
public void Fit(IList<double> x, IList<double> y)
{
if (x == null || y == null)
{
throw new ArgumentException("Input data cannot be null.");
}
if (x.Count == 0 || y.Count == 0)
{
throw new ArgumentException("Input data cannot be empty.");
}
if (x.Count != y.Count)
{
throw new ArgumentException("Input lists must have the same length.");
}
// Calculate means
double xMean = x.Average();
double yMean = y.Average();
// Calculate slope (b) and intercept (a)
double numerator = 0.0;
double denominator = 0.0;
for (int i = 0; i < x.Count; i++)
{
numerator += (x[i] - xMean) * (y[i] - yMean);
denominator += (x[i] - xMean) * (x[i] - xMean);
}
const double epsilon = 1e-12;
if (Math.Abs(denominator) < epsilon)
{
throw new ArgumentException("Variance of X must not be zero.");
}
Slope = numerator / denominator;
Intercept = yMean - Slope * xMean;
IsFitted = true;
}
/// <summary>
/// Predicts the output value for a given input using the fitted model.
/// </summary>
/// <param name="x">Input value.</param>
/// <returns>Predicted output value.</returns>
/// <exception cref="InvalidOperationException">Thrown if the model is not fitted.</exception>
public double Predict(double x)
{
if (!IsFitted)
{
throw new InvalidOperationException("Model must be fitted before prediction.");
}
return Intercept + Slope * x;
}
/// <summary>
/// Predicts output values for a list of inputs using the fitted model.
/// </summary>
/// <param name="xValues">List of input values.</param>
/// <returns>List of predicted output values.</returns>
/// <exception cref="InvalidOperationException">Thrown if the model is not fitted.</exception>
public IList<double> Predict(IList<double> xValues)
{
if (!IsFitted)
{
throw new InvalidOperationException("Model must be fitted before prediction.");
}
return xValues.Select(Predict).ToList();
}
}