nsharper 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,151 @@
1
+ Metadata-Version: 2.4
2
+ Name: nsharper
3
+ Version: 0.1.0
4
+ Summary: A lightweight computer-vision framework for building, training and benchmarking compact object detectors
5
+ License-Expression: MIT
6
+ Project-URL: Documentation, https://github.com/nsharper/nsharper/blob/main/docs.md
7
+ Keywords: computer-vision,object-detection,deep-learning,benchmark
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
12
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: torch>=2.1
16
+ Requires-Dist: torchvision>=0.16
17
+ Requires-Dist: numpy>=1.24
18
+ Requires-Dist: pillow>=9.0
19
+ Requires-Dist: pyyaml>=6.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7.0; extra == "dev"
22
+
23
+ # nsharper
24
+
25
+ A lightweight Python framework for building and evaluating computer-vision
26
+ models with a deliberately simple API.
27
+
28
+ ```text
29
+ Dataset → Model → Summary → Train → Test → Benchmark → Save
30
+ ```
31
+
32
+ > Keep the model definition simple. Keep the workflow obvious.
33
+
34
+ Full documentation lives in [`docs.md`](docs.md).
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install nsharper
40
+ ```
41
+
42
+ ## A complete project
43
+
44
+ ```python
45
+ import nsharper as ns
46
+
47
+ train = ns.Dataset("dataset/train")
48
+ val = ns.Dataset("dataset/val")
49
+
50
+ model = ns.Model([
51
+ ns.Conv(224, 224, 3, 16, 3, 2),
52
+ ns.Conv(112, 112, 16, 32, 3, 2),
53
+ ns.Conv(56, 56, 32, 64, 3, 2),
54
+ ns.Detect(28, 28, 64, 10)
55
+ ])
56
+
57
+ model.summary()
58
+
59
+ model.fit(train, epochs=50, batch_size=32, lr=0.001, val=val)
60
+
61
+ results = model.test(val)
62
+ results.show()
63
+
64
+ model.save("supercharger.nsh")
65
+ ```
66
+
67
+ ## What each command answers
68
+
69
+ | Command | Question it answers |
70
+ | ------------- | ---------------------------------------------- |
71
+ | `summary()` | What is my model, and what does it cost? |
72
+ | `test()` | How well does it do on *my* dataset? |
73
+ | `benchmark()` | How well does it do on COCO? |
74
+
75
+ `summary()` reports parameters, FLOPs, model size, memory and measured
76
+ latency/FPS on every backend the machine offers, plus a Mermaid diagram of
77
+ the graph. It needs no trained weights, so architectures can be compared
78
+ before spending time on training.
79
+
80
+ ## Dataset layout
81
+
82
+ ```text
83
+ dataset/
84
+ ├── images/001.jpg
85
+ └── labels/001.yaml
86
+ ```
87
+
88
+ ```yaml
89
+ cat:
90
+ - [0.12, 0.20, 0.43, 0.61]
91
+ dog:
92
+ - [0.55, 0.31, 0.88, 0.72]
93
+ ```
94
+
95
+ Boxes are normalized `[x1, y1, x2, y2]`, all coordinates between `0.0` and `1.0`.
96
+
97
+ ## Devices
98
+
99
+ `"auto"` (default) walks CUDA → MPS → CPU and takes the first available
100
+ backend. `"cpu"`, `"cuda"`, `"mps"` and `"gpu"` select one explicitly.
101
+
102
+ ```python
103
+ model.fit(train, epochs=50, device="mps")
104
+ ns.device() # 'mps'
105
+ ```
106
+
107
+ ## Architecture errors surface immediately
108
+
109
+ ```python
110
+ ns.Model([
111
+ ns.Conv(224, 224, 3, 16, 3, 2),
112
+ ns.Conv(112, 112, 64, 32, 3, 2),
113
+ ])
114
+ ```
115
+
116
+ ```text
117
+ error: channel mismatch
118
+
119
+ layer: Conv
120
+ expected: 64
121
+ received: 16
122
+ ```
123
+
124
+ ## COCO benchmark
125
+
126
+ COCO is not bundled. Point `benchmark()` at a local copy — by argument, via
127
+ `NSHARPER_COCO`, or by placing it in `~/.nsharper/coco`:
128
+
129
+ ```python
130
+ ns.benchmark("supercharger.nsh")
131
+ ns.benchmark(model, data="~/datasets/coco")
132
+ ```
133
+
134
+ Both the nsharper layout (`images/` + `labels/`) and the official COCO
135
+ layout (`val2017/` + `annotations/instances_val2017.json`) are read.
136
+
137
+ ## Examples
138
+
139
+ ```bash
140
+ python examples/make_shapes.py dataset # generate a synthetic dataset
141
+ python examples/train.py # train, test and save a detector
142
+ python examples/predict.py dataset/val/images/0000.jpg
143
+ python examples/benchmark.py # benchmark saved models
144
+ ```
145
+
146
+ ## Development
147
+
148
+ ```bash
149
+ pip install -e ".[dev]"
150
+ pytest
151
+ ```
@@ -0,0 +1,129 @@
1
+ # nsharper
2
+
3
+ A lightweight Python framework for building and evaluating computer-vision
4
+ models with a deliberately simple API.
5
+
6
+ ```text
7
+ Dataset → Model → Summary → Train → Test → Benchmark → Save
8
+ ```
9
+
10
+ > Keep the model definition simple. Keep the workflow obvious.
11
+
12
+ Full documentation lives in [`docs.md`](docs.md).
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install nsharper
18
+ ```
19
+
20
+ ## A complete project
21
+
22
+ ```python
23
+ import nsharper as ns
24
+
25
+ train = ns.Dataset("dataset/train")
26
+ val = ns.Dataset("dataset/val")
27
+
28
+ model = ns.Model([
29
+ ns.Conv(224, 224, 3, 16, 3, 2),
30
+ ns.Conv(112, 112, 16, 32, 3, 2),
31
+ ns.Conv(56, 56, 32, 64, 3, 2),
32
+ ns.Detect(28, 28, 64, 10)
33
+ ])
34
+
35
+ model.summary()
36
+
37
+ model.fit(train, epochs=50, batch_size=32, lr=0.001, val=val)
38
+
39
+ results = model.test(val)
40
+ results.show()
41
+
42
+ model.save("supercharger.nsh")
43
+ ```
44
+
45
+ ## What each command answers
46
+
47
+ | Command | Question it answers |
48
+ | ------------- | ---------------------------------------------- |
49
+ | `summary()` | What is my model, and what does it cost? |
50
+ | `test()` | How well does it do on *my* dataset? |
51
+ | `benchmark()` | How well does it do on COCO? |
52
+
53
+ `summary()` reports parameters, FLOPs, model size, memory and measured
54
+ latency/FPS on every backend the machine offers, plus a Mermaid diagram of
55
+ the graph. It needs no trained weights, so architectures can be compared
56
+ before spending time on training.
57
+
58
+ ## Dataset layout
59
+
60
+ ```text
61
+ dataset/
62
+ ├── images/001.jpg
63
+ └── labels/001.yaml
64
+ ```
65
+
66
+ ```yaml
67
+ cat:
68
+ - [0.12, 0.20, 0.43, 0.61]
69
+ dog:
70
+ - [0.55, 0.31, 0.88, 0.72]
71
+ ```
72
+
73
+ Boxes are normalized `[x1, y1, x2, y2]`, all coordinates between `0.0` and `1.0`.
74
+
75
+ ## Devices
76
+
77
+ `"auto"` (default) walks CUDA → MPS → CPU and takes the first available
78
+ backend. `"cpu"`, `"cuda"`, `"mps"` and `"gpu"` select one explicitly.
79
+
80
+ ```python
81
+ model.fit(train, epochs=50, device="mps")
82
+ ns.device() # 'mps'
83
+ ```
84
+
85
+ ## Architecture errors surface immediately
86
+
87
+ ```python
88
+ ns.Model([
89
+ ns.Conv(224, 224, 3, 16, 3, 2),
90
+ ns.Conv(112, 112, 64, 32, 3, 2),
91
+ ])
92
+ ```
93
+
94
+ ```text
95
+ error: channel mismatch
96
+
97
+ layer: Conv
98
+ expected: 64
99
+ received: 16
100
+ ```
101
+
102
+ ## COCO benchmark
103
+
104
+ COCO is not bundled. Point `benchmark()` at a local copy — by argument, via
105
+ `NSHARPER_COCO`, or by placing it in `~/.nsharper/coco`:
106
+
107
+ ```python
108
+ ns.benchmark("supercharger.nsh")
109
+ ns.benchmark(model, data="~/datasets/coco")
110
+ ```
111
+
112
+ Both the nsharper layout (`images/` + `labels/`) and the official COCO
113
+ layout (`val2017/` + `annotations/instances_val2017.json`) are read.
114
+
115
+ ## Examples
116
+
117
+ ```bash
118
+ python examples/make_shapes.py dataset # generate a synthetic dataset
119
+ python examples/train.py # train, test and save a detector
120
+ python examples/predict.py dataset/val/images/0000.jpg
121
+ python examples/benchmark.py # benchmark saved models
122
+ ```
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ pip install -e ".[dev]"
128
+ pytest
129
+ ```
@@ -0,0 +1,67 @@
1
+ """nsharper — a lightweight computer-vision framework.
2
+
3
+ Dataset → Model → Summary → Train → Test → Benchmark → Save
4
+
5
+ Keep the model definition simple. Keep the workflow obvious.
6
+
7
+ >>> import nsharper as ns
8
+ >>>
9
+ >>> train = ns.Dataset("dataset/train")
10
+ >>> model = ns.Model([
11
+ ... ns.Conv(224, 224, 3, 16, 3, 2),
12
+ ... ns.Conv(112, 112, 16, 32, 3, 2),
13
+ ... ns.Conv(56, 56, 32, 64, 3, 2),
14
+ ... ns.Detect(28, 28, 64, 10),
15
+ ... ])
16
+ >>> model.summary()
17
+ >>> model.fit(train, epochs=50)
18
+ >>> model.save("supercharger.nsh")
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from .coco import benchmark
24
+ from .dataset import Box, Dataset, Sample
25
+ from .backends import device
26
+ from .errors import (
27
+ ArchitectureError,
28
+ BenchmarkError,
29
+ DatasetError,
30
+ DeviceError,
31
+ ModelError,
32
+ NsharperError,
33
+ )
34
+ from .layers import Conv, Detect, Layer
35
+ from .model import Model
36
+ from .results import Detection, Prediction, TestResults
37
+ from .serialization import load
38
+ from .summary import Summary
39
+
40
+ __version__ = "0.1.0"
41
+
42
+ __all__ = [
43
+ # core API
44
+ "Dataset",
45
+ "Model",
46
+ "Conv",
47
+ "Detect",
48
+ "load",
49
+ "benchmark",
50
+ "device",
51
+ # supporting types
52
+ "Box",
53
+ "Sample",
54
+ "Layer",
55
+ "Summary",
56
+ "TestResults",
57
+ "Prediction",
58
+ "Detection",
59
+ # errors
60
+ "NsharperError",
61
+ "ArchitectureError",
62
+ "DatasetError",
63
+ "DeviceError",
64
+ "ModelError",
65
+ "BenchmarkError",
66
+ "__version__",
67
+ ]
@@ -0,0 +1,113 @@
1
+ """Compute-backend selection.
2
+
3
+ The public entry point is ``ns.device()``; this module keeps a separate name
4
+ so importing it can never shadow that function.
5
+
6
+ nsharper accepts the identifiers documented in the "Devices" section:
7
+ ``auto``, ``cpu``, ``cuda``, ``mps`` and ``gpu``. ``auto`` walks the
8
+ priority chain CUDA -> MPS -> GPU -> CPU and picks the first backend the
9
+ installed runtime actually offers.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import torch
15
+
16
+ from .errors import DeviceError
17
+
18
+ __all__ = ["device", "resolve", "available", "is_available"]
19
+
20
+ #: Priority chain used by ``device="auto"``.
21
+ PRIORITY = ("cuda", "mps", "cpu")
22
+
23
+ ALIASES = {
24
+ None: "auto",
25
+ "auto": "auto",
26
+ "cpu": "cpu",
27
+ "cuda": "cuda",
28
+ "gpu": "gpu",
29
+ "mps": "mps",
30
+ }
31
+
32
+
33
+ def is_available(name: str) -> bool:
34
+ """Return whether a concrete backend can be used right now."""
35
+ if name == "cpu":
36
+ return True
37
+ if name == "cuda":
38
+ return torch.cuda.is_available()
39
+ if name == "mps":
40
+ return torch.backends.mps.is_available()
41
+ return False
42
+
43
+
44
+ def available() -> list[str]:
45
+ """Every usable backend, best first."""
46
+ return [name for name in PRIORITY if is_available(name)]
47
+
48
+
49
+ def resolve(spec: str | torch.device | None = "auto") -> torch.device:
50
+ """Turn a device identifier into a concrete :class:`torch.device`."""
51
+ if isinstance(spec, torch.device):
52
+ return spec
53
+
54
+ if isinstance(spec, str):
55
+ key = spec.strip().lower()
56
+ # Allow indexed devices such as "cuda:1" to pass through untouched.
57
+ if ":" in key:
58
+ base = key.split(":", 1)[0]
59
+ if base not in ALIASES or base in ("auto", "gpu"):
60
+ raise DeviceError(_unknown(spec))
61
+ if not is_available(base):
62
+ raise DeviceError(_unavailable(base))
63
+ return torch.device(key)
64
+ elif spec is None:
65
+ key = "auto"
66
+ else:
67
+ raise DeviceError(_unknown(spec))
68
+
69
+ if key not in ALIASES:
70
+ raise DeviceError(_unknown(spec))
71
+
72
+ if key == "auto":
73
+ return torch.device(available()[0])
74
+
75
+ if key == "gpu":
76
+ for name in ("cuda", "mps"):
77
+ if is_available(name):
78
+ return torch.device(name)
79
+ raise DeviceError(
80
+ "error: no gpu available\n\n"
81
+ "requested: gpu\n"
82
+ f"available: {', '.join(available())}"
83
+ )
84
+
85
+ if not is_available(key):
86
+ raise DeviceError(_unavailable(key))
87
+ return torch.device(key)
88
+
89
+
90
+ def _unknown(spec: object) -> str:
91
+ return (
92
+ "error: unknown device\n\n"
93
+ f"received: {spec!r}\n"
94
+ "expected: auto, cpu, cuda, mps or gpu"
95
+ )
96
+
97
+
98
+ def _unavailable(name: str) -> str:
99
+ return (
100
+ "error: device unavailable\n\n"
101
+ f"requested: {name}\n"
102
+ f"available: {', '.join(available())}"
103
+ )
104
+
105
+
106
+ def device(spec: str | None = "auto") -> str:
107
+ """Report the execution backend nsharper would use.
108
+
109
+ >>> import nsharper as ns
110
+ >>> ns.device()
111
+ 'mps'
112
+ """
113
+ return str(resolve(spec))