measly 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ pypi:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read # a permissions block zeroes every scope not listed
13
+ id-token: write # mints the OIDC token PyPI trades for upload rights
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ # The release tag and pyproject.toml are two sources of truth for the
18
+ # version. PyPI rejects a duplicate upload, so catch a mismatch here.
19
+ - if: github.event_name == 'release' # on dispatch the ref is a branch
20
+ run: grep -q "^version = \"${GITHUB_REF_NAME#v}\"$" pyproject.toml
21
+ - run: uv build
22
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,20 @@
1
+ name: test
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ pytest:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python: ["3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ with:
18
+ python-version: ${{ matrix.python }}
19
+ - run: uv sync --group dev --locked
20
+ - run: uv run pytest tests -q
@@ -0,0 +1,14 @@
1
+ .vibe-wise
2
+ data/
3
+ __pycache__/
4
+ *.py[cod]
5
+ .venv/
6
+ *.egg-info/
7
+ playground/
8
+ .ruff_cache
9
+
10
+ demo/
11
+ .pytest_cache/
12
+ dist/
13
+
14
+ CLAUDE.md
measly-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Remi Tregan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
measly-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.5
2
+ Name: measly
3
+ Version: 0.1.0
4
+ Summary: Estimate whether a model is data-limited, and whether more capacity would pay off.
5
+ Project-URL: Homepage, https://github.com/tremgan/measly
6
+ Project-URL: Source, https://github.com/tremgan/measly
7
+ Project-URL: Issues, https://github.com/tremgan/measly/issues
8
+ Author-email: Remi Tregan <tregan.remi@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: active-learning,learning-curve,sample-size,scaling-law
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: matplotlib>=3.8
19
+ Requires-Dist: numpy>=1.26
20
+ Requires-Dist: scipy>=1.17.1
21
+ Requires-Dist: xarray>=2026.9.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # measly🍽️
25
+
26
+ More data helps. measly estimates how much.
27
+
28
+ measly estimates whether a model is data-limited, meaning whether measuring more samples would improve its performance. It is built for fields where each measurement is slow and expensive, such as the life sciences.
29
+
30
+ Note that measly's sweep trains `'n_draws' * 'n_models' * 'n_fractions'` models, which can be extremely computationally expensive. The premise is that this is (should be) still cheaper than collecting new data. If this is not the case, measly isn't appropriate for your use case.
31
+
32
+ ## Problem Definition
33
+
34
+ measly fits a model to many random subsets of the dataset at different fractions of its size. Each draw gives one learning curve, and each curve is fitted with a scaling law. The default is `pow4`:
35
+
36
+ $$L(n) = L_\infty + A\,(n + d)^{-\alpha}$$
37
+
38
+ `pow3`, the three-parameter form most of the literature quotes, is `pow4`
39
+ with $d$ fixed at zero:
40
+
41
+ $$L(n) = L_\infty + A\,n^{-\alpha}$$
42
+
43
+
44
+ ![a learning curve for two model capacities](docs/learning-curve.png)
45
+
46
+ At 75 examples the 75-feature model is more than three times worse. At 750 it
47
+ is 1% better. The curves cross near 400.
48
+
49
+ A pilot study hides that crossover. Measured only at 75 examples, you would
50
+ have picked the small model and been wrong about every later round. A model's
51
+ rank at one sample size says little about its rank at the next.
52
+
53
+ Both gains are small but positive, and the larger model gains about 40% more.
54
+ So collecting more data helps a little, and mostly the high-capacity model.
55
+
56
+ The gain interval is far tighter than the loss interval. Every size
57
+ in a draw is scored on the same test set, so that draw's whole curve shifts up
58
+ or down together. The shift dominates the loss band and cancels in the gain,
59
+ because each curve is compared against its own level, not an average over
60
+ draws.
61
+
62
+ ## Does it work?
63
+
64
+ The example data is synthetic, so the projection can be checked against the
65
+ truth. [`examples/capacity.py`](examples/capacity.py) draws extra rows from the
66
+ same process, refits at four sizes past the measured range, and scores on
67
+ 20,000 held-out rows. These are the open diamonds in the figure. The larger
68
+ sets extend the pilot, as collecting more data would. Only the new rows are
69
+ redrawn across the ten repeats.
70
+
71
+ ```
72
+ model examples actual projected interval error
73
+ ridge(20 features) 938 1.1592 +-0.0027 1.0795 [0.9534, 1.2388] 6.9%
74
+ ridge(20 features) 1125 1.1539 +-0.0047 1.0762 [0.9357, 1.2321] 6.7%
75
+ ridge(20 features) 1312 1.1519 +-0.0047 1.0737 [0.9322, 1.2308] 6.8%
76
+ ridge(20 features) 1500 1.1499 +-0.0042 1.0717 [0.9312, 1.2301] 6.8%
77
+ ridge(75 features) 938 1.0736 +-0.0091 1.1035 [0.9201, 1.3113] 2.8%
78
+ ridge(75 features) 1125 1.0594 +-0.0090 1.1006 [0.9139, 1.3095] 3.9%
79
+ ridge(75 features) 1312 1.0515 +-0.0091 1.0963 [0.9079, 1.3087] 4.3%
80
+ ridge(75 features) 1500 1.0466 +-0.0057 1.0961 [0.9040, 1.3084] 4.7%
81
+ ```
82
+
83
+ All eight land inside their intervals, never more than 6.9% from the median.
84
+
85
+ The projected loss shows no consistent bias. Over eight pilots the projection
86
+ at 2x sat above what actually happened in 3 of 8 for the nearly flat model and
87
+ 5 of 8 for the steeply descending one. The mean error was +0.4% and +2.4%, and
88
+ all sixteen intervals held the truth. The scatter comes from scoring on a slice
89
+ of your own pilot.
90
+
91
+ The audit stops at twice the measured pool. The held-back check fits on the
92
+ smaller sizes and predicts the largest two, a stretch of about 1.9x, so that
93
+ is as far as the method carries evidence. Projecting ten times out would
94
+ return a number and support none of it.
95
+
96
+ The error bars on the diamonds are smaller than the markers. Ten independent
97
+ collections at one size vary by 0.0027 to 0.0091, while the band spans about
98
+ 0.3, so the band is 30 to 100 times wider. That is the safe direction to err
99
+ in. Most of the width is test-set noise, not uncertainty about the curve.
100
+
101
+ Subsets are drawn without replacement. Each draw resplits the pool, so even the
102
+ full-size fit varies across draws. A bootstrap would add little to that spread
103
+ and would bias the level up, because a resample repeats rows.
104
+
105
+ `analyse` always checks itself. It refits the curves on the smaller sample
106
+ sizes, predicts the largest ones you already measured, and reports the error.
107
+ Above 15% the projection MUST NOT be relied on: the shape fits your data but
108
+ does not predict it.
109
+
110
+ `analyse(...).results` is an `xarray.DataArray` over `(fraction, model, draw)`
111
+ if you want the raw measurements.
112
+
113
+ ## Previous work in this area/Inspiration
114
+
115
+ - [The Shape of Learning Curves: a Review](https://arxiv.org/abs/2103.10948). Viering & Loog, 2021.
116
+ - [Deep Learning Scaling is Predictable, Empirically](https://arxiv.org/abs/1712.00409). Hestness et al., 2017.
117
+ - [Scaling Laws for Neural Language Models](https://arxiv.org/abs/2001.08361). Kaplan et al., 2020.
118
+ - [Training Compute-Optimal Large Language Models](https://arxiv.org/abs/2203.15556). Hoffmann et al., 2022.
119
+ - [Revisiting Neural Scaling Laws in Language and Vision](https://arxiv.org/abs/2209.06640). Alabdulmohsin et al., 2022.
120
+ - [Broken Neural Scaling Laws](https://github.com/ethancaballero/broken_neural_scaling_laws). Caballero et al., 2022.
121
+ - [How Much More Data Do I Need?](https://research.nvidia.com/labs/toronto-ai/estimatingrequirements/). Mahmood et al., 2022.
122
+ - [Estimation of Predictive Performance in High-Dimensional Data Settings using Learning Curves](https://arxiv.org/abs/2206.03825). Goedhart et al., 2022.
measly-0.1.0/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # measly🍽️
2
+
3
+ More data helps. measly estimates how much.
4
+
5
+ measly estimates whether a model is data-limited, meaning whether measuring more samples would improve its performance. It is built for fields where each measurement is slow and expensive, such as the life sciences.
6
+
7
+ Note that measly's sweep trains `'n_draws' * 'n_models' * 'n_fractions'` models, which can be extremely computationally expensive. The premise is that this is (should be) still cheaper than collecting new data. If this is not the case, measly isn't appropriate for your use case.
8
+
9
+ ## Problem Definition
10
+
11
+ measly fits a model to many random subsets of the dataset at different fractions of its size. Each draw gives one learning curve, and each curve is fitted with a scaling law. The default is `pow4`:
12
+
13
+ $$L(n) = L_\infty + A\,(n + d)^{-\alpha}$$
14
+
15
+ `pow3`, the three-parameter form most of the literature quotes, is `pow4`
16
+ with $d$ fixed at zero:
17
+
18
+ $$L(n) = L_\infty + A\,n^{-\alpha}$$
19
+
20
+
21
+ ![a learning curve for two model capacities](docs/learning-curve.png)
22
+
23
+ At 75 examples the 75-feature model is more than three times worse. At 750 it
24
+ is 1% better. The curves cross near 400.
25
+
26
+ A pilot study hides that crossover. Measured only at 75 examples, you would
27
+ have picked the small model and been wrong about every later round. A model's
28
+ rank at one sample size says little about its rank at the next.
29
+
30
+ Both gains are small but positive, and the larger model gains about 40% more.
31
+ So collecting more data helps a little, and mostly the high-capacity model.
32
+
33
+ The gain interval is far tighter than the loss interval. Every size
34
+ in a draw is scored on the same test set, so that draw's whole curve shifts up
35
+ or down together. The shift dominates the loss band and cancels in the gain,
36
+ because each curve is compared against its own level, not an average over
37
+ draws.
38
+
39
+ ## Does it work?
40
+
41
+ The example data is synthetic, so the projection can be checked against the
42
+ truth. [`examples/capacity.py`](examples/capacity.py) draws extra rows from the
43
+ same process, refits at four sizes past the measured range, and scores on
44
+ 20,000 held-out rows. These are the open diamonds in the figure. The larger
45
+ sets extend the pilot, as collecting more data would. Only the new rows are
46
+ redrawn across the ten repeats.
47
+
48
+ ```
49
+ model examples actual projected interval error
50
+ ridge(20 features) 938 1.1592 +-0.0027 1.0795 [0.9534, 1.2388] 6.9%
51
+ ridge(20 features) 1125 1.1539 +-0.0047 1.0762 [0.9357, 1.2321] 6.7%
52
+ ridge(20 features) 1312 1.1519 +-0.0047 1.0737 [0.9322, 1.2308] 6.8%
53
+ ridge(20 features) 1500 1.1499 +-0.0042 1.0717 [0.9312, 1.2301] 6.8%
54
+ ridge(75 features) 938 1.0736 +-0.0091 1.1035 [0.9201, 1.3113] 2.8%
55
+ ridge(75 features) 1125 1.0594 +-0.0090 1.1006 [0.9139, 1.3095] 3.9%
56
+ ridge(75 features) 1312 1.0515 +-0.0091 1.0963 [0.9079, 1.3087] 4.3%
57
+ ridge(75 features) 1500 1.0466 +-0.0057 1.0961 [0.9040, 1.3084] 4.7%
58
+ ```
59
+
60
+ All eight land inside their intervals, never more than 6.9% from the median.
61
+
62
+ The projected loss shows no consistent bias. Over eight pilots the projection
63
+ at 2x sat above what actually happened in 3 of 8 for the nearly flat model and
64
+ 5 of 8 for the steeply descending one. The mean error was +0.4% and +2.4%, and
65
+ all sixteen intervals held the truth. The scatter comes from scoring on a slice
66
+ of your own pilot.
67
+
68
+ The audit stops at twice the measured pool. The held-back check fits on the
69
+ smaller sizes and predicts the largest two, a stretch of about 1.9x, so that
70
+ is as far as the method carries evidence. Projecting ten times out would
71
+ return a number and support none of it.
72
+
73
+ The error bars on the diamonds are smaller than the markers. Ten independent
74
+ collections at one size vary by 0.0027 to 0.0091, while the band spans about
75
+ 0.3, so the band is 30 to 100 times wider. That is the safe direction to err
76
+ in. Most of the width is test-set noise, not uncertainty about the curve.
77
+
78
+ Subsets are drawn without replacement. Each draw resplits the pool, so even the
79
+ full-size fit varies across draws. A bootstrap would add little to that spread
80
+ and would bias the level up, because a resample repeats rows.
81
+
82
+ `analyse` always checks itself. It refits the curves on the smaller sample
83
+ sizes, predicts the largest ones you already measured, and reports the error.
84
+ Above 15% the projection MUST NOT be relied on: the shape fits your data but
85
+ does not predict it.
86
+
87
+ `analyse(...).results` is an `xarray.DataArray` over `(fraction, model, draw)`
88
+ if you want the raw measurements.
89
+
90
+ ## Previous work in this area/Inspiration
91
+
92
+ - [The Shape of Learning Curves: a Review](https://arxiv.org/abs/2103.10948). Viering & Loog, 2021.
93
+ - [Deep Learning Scaling is Predictable, Empirically](https://arxiv.org/abs/1712.00409). Hestness et al., 2017.
94
+ - [Scaling Laws for Neural Language Models](https://arxiv.org/abs/2001.08361). Kaplan et al., 2020.
95
+ - [Training Compute-Optimal Large Language Models](https://arxiv.org/abs/2203.15556). Hoffmann et al., 2022.
96
+ - [Revisiting Neural Scaling Laws in Language and Vision](https://arxiv.org/abs/2209.06640). Alabdulmohsin et al., 2022.
97
+ - [Broken Neural Scaling Laws](https://github.com/ethancaballero/broken_neural_scaling_laws). Caballero et al., 2022.
98
+ - [How Much More Data Do I Need?](https://research.nvidia.com/labs/toronto-ai/estimatingrequirements/). Mahmood et al., 2022.
99
+ - [Estimation of Predictive Performance in High-Dimensional Data Settings using Learning Curves](https://arxiv.org/abs/2206.03825). Goedhart et al., 2022.
Binary file
@@ -0,0 +1,127 @@
1
+ """More capacity is worse on a pilot and better once the data arrives.
2
+
3
+ The small model is misspecified: it sees a subset of the features, so it has a
4
+ floor above the noise. The large model is unbiased but pays variance early.
5
+ The curves therefore cross, and which model is "better" depends entirely on
6
+ how much data you have.
7
+
8
+ Because the data is synthetic the projection can be audited rather than
9
+ trusted. The extra rows are drawn from the same process and the models
10
+ refitted on them, so the figure carries both what measly predicted and what
11
+ actually happened.
12
+
13
+ uv run --group demo python examples/capacity.py
14
+
15
+ Writes docs/learning-curve.png.
16
+ """
17
+
18
+ import numpy as np
19
+ from matplotlib.lines import Line2D
20
+ from sklearn.compose import ColumnTransformer
21
+ from sklearn.linear_model import Ridge
22
+ from sklearn.pipeline import Pipeline
23
+
24
+ from measly import analyse, mean_squared_error, plot
25
+ from measly.plot import GUIDE, PALETTE
26
+
27
+ TOTAL, CAPACITY = 75, 20
28
+ PILOT, NOISE = 3000, 1.0
29
+ TAIL = 0.05
30
+ """Weight on every feature the small model omits.
31
+
32
+ It alone sets where the curves cross, at `NOISE**2 / TAIL**2` examples. The
33
+ feature counts set how steep the large model's descent is and how wide the
34
+ final gap is, without moving the crossing.
35
+ """
36
+
37
+ FACTORS = (1.25, 1.5, 1.75, 2.0)
38
+ """Multiples of the measured pool to audit the projection at.
39
+
40
+ Capped at 2x on purpose. The held-back check fits on the smaller sizes and
41
+ predicts the largest two, a stretch of `1.0 / 0.5179`, so roughly 1.9x is as
42
+ far as the method carries evidence. Auditing past that measures nothing the
43
+ tool claims.
44
+ """
45
+
46
+ REPEATS = 10
47
+ """Independent collections at each size, so the audit carries its own spread."""
48
+
49
+
50
+ def ridge(capacity):
51
+ """Ridge that sees only the first `capacity` features."""
52
+ return Pipeline([
53
+ ("capacity",
54
+ ColumnTransformer([("keep", "passthrough", slice(0, capacity))])),
55
+ ("ridge", Ridge()),
56
+ ])
57
+
58
+
59
+ rng = np.random.default_rng(0)
60
+ weights = np.concatenate([rng.normal(size=4), np.full(TOTAL - 4, TAIL)])
61
+
62
+
63
+ def sample(n):
64
+ X = rng.normal(size=(n, TOTAL))
65
+ return X, X @ weights + rng.normal(0.0, NOISE, n)
66
+
67
+
68
+ # Named, because a Pipeline's repr embeds a memory address.
69
+ models = {f"ridge({capacity} features)": ridge(capacity)
70
+ for capacity in (CAPACITY, TOTAL)}
71
+
72
+ X_pilot, y_pilot = sample(PILOT)
73
+ result = analyse(models, X_pilot, y_pilot, rng=0)
74
+ print(result.summary())
75
+ print(f"\ncurves cross near {round(NOISE ** 2 / TAIL ** 2)} examples\n")
76
+
77
+ # Go and collect the data measly was asked about, then check it was right.
78
+ # A lab keeps its pilot and adds to it, so the larger sets contain the smaller
79
+ # ones. Only the new rows are redrawn across repeats, because the pilot is not
80
+ # something that gets collected again.
81
+ X_check, y_check = sample(20_000)
82
+ sizes = [round(result.n_train * factor) for factor in FACTORS]
83
+ X_base, y_base = X_pilot[:result.n_train], y_pilot[:result.n_train]
84
+
85
+ scores = {name: np.empty((REPEATS, len(sizes))) for name in models}
86
+ for repeat in range(REPEATS):
87
+ X_new, y_new = sample(max(sizes) - result.n_train)
88
+ X_more = np.vstack([X_base, X_new])
89
+ y_more = np.concatenate([y_base, y_new])
90
+ for name, model in models.items():
91
+ for column, n in enumerate(sizes):
92
+ model.fit(X_more[:n], y_more[:n])
93
+ scores[name][repeat, column] = mean_squared_error(
94
+ model.predict(X_check), y_check)
95
+
96
+ actual = {name: value.mean(axis=0) for name, value in scores.items()}
97
+ spread = {name: value.std(axis=0, ddof=1) for name, value in scores.items()}
98
+
99
+ print(f"{'model':>20} {'examples':>9} {'actual':>17} {'projected':>10}"
100
+ f" {'interval':>18} {'error':>7}")
101
+ for name in models:
102
+ for factor, n, measured, sd in zip(FACTORS, sizes, actual[name], spread[name]):
103
+ projected = result.project(factor)[name]
104
+ print(f"{name:>20} {n:>9} {f'{measured:.4f} +-{sd:.4f}':>17}"
105
+ f" {projected.loss:>10.4f}"
106
+ f" {f'[{projected.low:.4f}, {projected.high:.4f}]':>18}"
107
+ f" {abs(projected.loss - measured) / measured:>7.1%}"
108
+ f"{'' if projected.low <= measured <= projected.high else ' OUT'}")
109
+
110
+ ax = plot(result, factor=max(FACTORS))
111
+ for index, name in enumerate(result.models):
112
+ colour = PALETTE[index % len(PALETTE)]
113
+ ax.errorbar(sizes, actual[name], yerr=spread[name], fmt="D", ms=5.5,
114
+ mfc="white", mec=colour, mew=1.5, color=colour,
115
+ elinewidth=1.1, capsize=0, zorder=6)
116
+
117
+ legend = ax.get_legend_handles_labels()[0] + [
118
+ Line2D([], [], ls="none", marker="o", color=GUIDE, ms=5,
119
+ label="measured by measly"),
120
+ Line2D([], [], ls="none", marker="D", mfc="white", mec=GUIDE, mew=1.5,
121
+ ms=5.5, label="actual, after collecting more"),
122
+ ]
123
+ ax.legend(handles=legend, frameon=False, fontsize=9, loc="upper right",
124
+ handlelength=1.6, borderaxespad=0)
125
+ ax.figure.tight_layout()
126
+ ax.figure.savefig("docs/learning-curve.png", dpi=120)
127
+ print("\nwrote docs/learning-curve.png")
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "measly"
3
+ version = "0.1.0"
4
+ description = "Estimate whether a model is data-limited, and whether more capacity would pay off."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ requires-python = ">=3.12"
9
+ authors = [{ name = "Remi Tregan", email = "tregan.remi@gmail.com" }]
10
+ keywords = ["learning-curve", "scaling-law", "sample-size", "active-learning"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Intended Audience :: Science/Research",
14
+ "Programming Language :: Python :: 3.12",
15
+ "Programming Language :: Python :: 3.13",
16
+ "Topic :: Scientific/Engineering",
17
+ ]
18
+ dependencies = [
19
+ "matplotlib>=3.8",
20
+ "numpy>=1.26",
21
+ "scipy>=1.17.1",
22
+ "xarray>=2026.9.0",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/tremgan/measly"
27
+ Source = "https://github.com/tremgan/measly"
28
+ Issues = "https://github.com/tremgan/measly/issues"
29
+
30
+ [dependency-groups]
31
+ dev = ["pytest>=8"]
32
+ demo = ["scikit-learn>=1.4"]
33
+
34
+ [tool.pytest.ini_options]
35
+ pythonpath = ["tests"]
36
+
37
+ [build-system]
38
+ requires = ["hatchling"]
39
+ build-backend = "hatchling.build"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/measly"]
@@ -0,0 +1,43 @@
1
+ """Estimate whether a model is data-limited, and whether more capacity would pay off."""
2
+
3
+ from measly.analysis import (
4
+ DEFAULT_FRACTIONS,
5
+ VALIDATION_WARN,
6
+ Analysis,
7
+ Projection,
8
+ analyse,
9
+ mean_squared_error,
10
+ )
11
+ from measly.fit import (
12
+ POW3,
13
+ POW4,
14
+ CurveEnsemble,
15
+ ScalingLaw,
16
+ fit_scaling_law,
17
+ fit_scaling_laws,
18
+ pow3,
19
+ )
20
+ from measly.interfaces import Model, Score
21
+ from measly.plot import plot
22
+ from measly.sweep import sweep, train_test_split
23
+
24
+ __all__ = [
25
+ "analyse",
26
+ "Analysis",
27
+ "Projection",
28
+ "mean_squared_error",
29
+ "plot",
30
+ "DEFAULT_FRACTIONS",
31
+ "VALIDATION_WARN",
32
+ "Model",
33
+ "Score",
34
+ "train_test_split",
35
+ "sweep",
36
+ "pow3",
37
+ "ScalingLaw",
38
+ "POW3",
39
+ "POW4",
40
+ "CurveEnsemble",
41
+ "fit_scaling_law",
42
+ "fit_scaling_laws",
43
+ ]