Skip to content

[Repo Assist] feat: implement OLS.Linear.Univariable.fitWithWeighting (weighted simple linear regression)#369

Draft
github-actions[bot] wants to merge 2 commits intodeveloperfrom
repo-assist/improve-weighted-slr-20260406-4b1ca01b9d045c66
Draft

[Repo Assist] feat: implement OLS.Linear.Univariable.fitWithWeighting (weighted simple linear regression)#369
github-actions[bot] wants to merge 2 commits intodeveloperfrom
repo-assist/improve-weighted-slr-20260406-4b1ca01b9d045c66

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 6, 2026

🤖 This is an automated PR from Repo Assist.

Closes #205

Problem

OLS.Linear.Univariable had no weighted variant. Using LinearRegressor.fit with Weighting and Method.SimpleLinear threw a failwithf at runtime. The only workaround was Polynomial.fitWithWeighting 1, which is non-obvious and unnecessarily general.

Root cause

The Univariable module simply never had a weighted implementation.

Fix

Add OLS.Linear.Univariable.fitWithWeighting that solves the WLS normal equations analytically in a single pass:

[Σw    Σwx ] [a]   [Σwy ]
[Σwx   Σwx²] [b] = [Σwxy]

Closed-form solution — no matrix allocation required:

let slope     = (sw * swxy - swx * swy) / (sw * swxx - swx * swx)
let intercept = (swy - slope * swx) / sw

Wire LinearRegressor.fit to use it when Weighting is provided and FittingMethod = SimpleLinear.

Usage

open FSharp.Stats.Fitting.LinearRegression

let xData   = vector [|1.; 2.; 3.; 4.; 5.; 6.|]
let yData   = vector [|4.; 7.; 9.; 10.; 11.; 15.|]
let weights = vector [|1.; 1.; 1.; 1.; 1.; 0.1|]   // down-weight last point

// Direct API
let coef = OLS.Linear.Univariable.fitWithWeighting weights xData yData

// OO API (now works — no longer throws)
let coef2 = LinearRegression.fit(xData, yData, Weighting = weights)
```

## Trade-offs

- The analytical formula uses one pass over the data (O(n), zero heap allocations beyond the final `Coefficients` wrapper), compared to `Polynomial.fitWithWeighting 1` which allocates multiple arrays and calls `solveLinearSystem`.
- The two approaches agree to machine precision (verified by test).
- A degenerate case (all weight concentrated at one x value, giving a singular system) raises `ArgumentException` with a clear message.

## Test Status

6 new tests added, 1199/1199 pass:
```
Passed!  - Failed: 0, Passed: 1199, Skipped: 0, Total: 1199

Tests cover: equal-unit-weight = unweighted, exact coefficient recovery, outlier down-weighting, scale invariance, agreement with Polynomial.fitWithWeighting 1, and LinearRegressor.fit dispatch.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@7ee2b60744abf71b985bead4599640f165edcd93

…ar regression

Closes #205

Add OLS.Linear.Univariable.fitWithWeighting that fits y = a + bx by solving
the weighted least-squares normal equations analytically in a single pass:

  [Σw   Σwx ] [a]   [Σwy ]
  [Σwx  Σwx²] [b] = [Σwxy]

The closed-form solution avoids matrix inversion overhead and handles the
common case (order-1 polynomial with weights) cleanly.

Also wire the new function into LinearRegressor.fit (the OO API entry
point) so the existing Weighting parameter now works for SimpleLinear
instead of raising a NotImplementedException.

Added 6 tests covering:
- equal-unit-weight reproduces unweighted fit
- exact line recovery (intercept=2, slope=3)
- down-weighting an outlier improves accuracy
- scaling all weights leaves coefficients unchanged
- agreement with Polynomial.fitWithWeighting order=1
- LinearRegressor.fit dispatch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Weighted simple linear regression

0 participants