bgnx 0.0.1__py3-none-any.whl
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.
Potentially problematic release.
This version of bgnx might be problematic. Click here for more details.
- bgnx/__init__.py +9 -0
- bgnx/device.py +54 -0
- bgnx/metrics.py +16 -0
- bgnx/stats.py +22 -0
- bgnx-0.0.1.dist-info/METADATA +50 -0
- bgnx-0.0.1.dist-info/RECORD +9 -0
- bgnx-0.0.1.dist-info/WHEEL +5 -0
- bgnx-0.0.1.dist-info/licenses/LICENSE +21 -0
- bgnx-0.0.1.dist-info/top_level.txt +1 -0
bgnx/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""BGNX: a framework for travel time prediction (early alpha: evaluation utilities only).
|
|
2
|
+
|
|
3
|
+
PT: BGNX: framework de previsão do tempo de viagem (alfa inicial: só utilitários de avaliação).
|
|
4
|
+
"""
|
|
5
|
+
from .metrics import metrics
|
|
6
|
+
from .stats import paired_comparison
|
|
7
|
+
|
|
8
|
+
__version__ = '0.0.1'
|
|
9
|
+
__all__ = ['metrics', 'paired_comparison', '__version__']
|
bgnx/device.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Training device helper (needs PyTorch: pip install "bgnx[torch]"): CPU or GPU, batch size and learning rate from a
|
|
2
|
+
JSON file, with environment overrides.
|
|
3
|
+
|
|
4
|
+
from bgnx.device import configure_device, move
|
|
5
|
+
dev, cfg = configure_device() # picks the device and prints the choice
|
|
6
|
+
tensors = move(tensors, dev, cfg) # whole training set on the GPU if it fits (data_on_gpu = auto)
|
|
7
|
+
|
|
8
|
+
Settings: defaults below, then the JSON in BGNX_DEVICE_CONFIG (if set), then BGNX_DEVICE=cpu|cuda|auto.
|
|
9
|
+
|
|
10
|
+
PT: Ajuda para o dispositivo de treino (precisa do PyTorch): CPU ou GPU, lote e taxa de aprendizado lidos de um JSON,
|
|
11
|
+
com variáveis de ambiente por cima (BGNX_DEVICE_CONFIG aponta o JSON; BGNX_DEVICE=cpu|cuda|auto).
|
|
12
|
+
"""
|
|
13
|
+
import json, os
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
DEFAULTS = {'device': 'auto', 'cpu_threads': 8, 'data_on_gpu': 'auto', 'batch': None, 'lr': None, 'predict_batch': 32768}
|
|
17
|
+
|
|
18
|
+
def _torch():
|
|
19
|
+
try:
|
|
20
|
+
import torch
|
|
21
|
+
except ImportError as e:
|
|
22
|
+
raise ImportError('bgnx.device needs PyTorch: pip install "bgnx[torch]"') from e
|
|
23
|
+
return torch
|
|
24
|
+
|
|
25
|
+
def read_device_config():
|
|
26
|
+
"""Defaults, then the JSON file, then the environment variable. PT: padrões, depois o JSON, depois a variável."""
|
|
27
|
+
cfg = dict(DEFAULTS)
|
|
28
|
+
path = os.environ.get('BGNX_DEVICE_CONFIG')
|
|
29
|
+
if path and Path(path).exists():
|
|
30
|
+
cfg.update({k: v for k, v in json.loads(Path(path).read_text(encoding='utf-8')).items() if k in DEFAULTS})
|
|
31
|
+
if os.environ.get('BGNX_DEVICE'): cfg['device'] = os.environ['BGNX_DEVICE']
|
|
32
|
+
return cfg
|
|
33
|
+
|
|
34
|
+
def configure_device():
|
|
35
|
+
"""Returns (torch.device, config dict). PT: devolve (dispositivo, configuração)."""
|
|
36
|
+
torch = _torch(); cfg = read_device_config()
|
|
37
|
+
torch.set_num_threads(int(cfg['cpu_threads']))
|
|
38
|
+
wanted = str(cfg['device']).lower()
|
|
39
|
+
if wanted not in ('auto', 'cuda', 'cpu'): raise ValueError(f'invalid device: {wanted}')
|
|
40
|
+
if wanted == 'cuda' and not torch.cuda.is_available(): print('warning: cuda requested but unavailable; using cpu', flush=True)
|
|
41
|
+
dev = torch.device('cuda' if wanted != 'cpu' and torch.cuda.is_available() else 'cpu')
|
|
42
|
+
name = torch.cuda.get_device_name(dev) if dev.type == 'cuda' else f'{torch.get_num_threads()} threads'
|
|
43
|
+
print(f'device: {dev} ({name})', flush=True)
|
|
44
|
+
return dev, cfg
|
|
45
|
+
|
|
46
|
+
def move(tensors, dev, cfg, headroom=1.5):
|
|
47
|
+
"""Copies a tuple of tensors to the GPU if `data_on_gpu` allows and it fits (with headroom); otherwise returns it as is.
|
|
48
|
+
|
|
49
|
+
PT: Copia os tensores para a GPU se `data_on_gpu` permitir e couber (com folga); senão devolve como está."""
|
|
50
|
+
torch = _torch()
|
|
51
|
+
if dev.type != 'cuda' or cfg['data_on_gpu'] in (False, 'false'): return tensors
|
|
52
|
+
size = sum(t.element_size()*t.nelement() for t in tensors)
|
|
53
|
+
if cfg['data_on_gpu'] == 'auto' and size*headroom > torch.cuda.mem_get_info(dev)[0]: return tensors
|
|
54
|
+
return tuple(t.to(dev) for t in tensors)
|
bgnx/metrics.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Error metrics for travel time prediction. Units follow the inputs (e.g. minutes); predictions are clipped at zero.
|
|
2
|
+
|
|
3
|
+
PT: Métricas de erro para previsão do tempo de viagem. As unidades seguem as entradas; previsões negativas viram zero.
|
|
4
|
+
"""
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
def metrics(y, p):
|
|
8
|
+
"""MAE, MedAE, MAPE (%), MARE (sum|e| / sum y), RMSLE, R2 and explained variance (EV).
|
|
9
|
+
|
|
10
|
+
PT: MAE, MedAE, MAPE (%), MARE (soma|e| / soma y), RMSLE, R2 e variância explicada (EV)."""
|
|
11
|
+
y = np.asarray(y, dtype=float); p = np.maximum(np.asarray(p, dtype=float), 0)
|
|
12
|
+
if y.shape != p.shape: raise ValueError(f'y and p differ in shape: {y.shape} vs {p.shape}')
|
|
13
|
+
e = y - p; a = np.abs(e); var = y.var()
|
|
14
|
+
return {'MAE': a.mean(), 'MedAE': float(np.median(a)), 'MAPE_%': 100*np.mean(a/y), 'MARE': a.sum()/y.sum(),
|
|
15
|
+
'RMSLE': float(np.sqrt(np.mean((np.log1p(p) - np.log1p(y))**2))),
|
|
16
|
+
'R2': 1 - np.mean(e**2)/var, 'EV': 1 - e.var()/var}
|
bgnx/stats.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Paired comparison of two models on the SAME observations: bootstrap interval of the MAE difference and the Wilcoxon
|
|
2
|
+
signed-rank test on the paired absolute errors.
|
|
3
|
+
|
|
4
|
+
PT: Comparação pareada de dois modelos nas MESMAS observações: intervalo bootstrap da diferença de MAE e o teste de
|
|
5
|
+
Wilcoxon nos erros absolutos pareados.
|
|
6
|
+
"""
|
|
7
|
+
import numpy as np
|
|
8
|
+
from scipy.stats import wilcoxon
|
|
9
|
+
|
|
10
|
+
def paired_comparison(y, pred_a, pred_b, replicas=2000, seed=42, level=0.95):
|
|
11
|
+
"""Difference = MAE(B) - MAE(A) (positive = A is better), its bootstrap interval and the Wilcoxon p-value.
|
|
12
|
+
|
|
13
|
+
PT: diferença = MAE(B) - MAE(A) (positiva = A é melhor), o intervalo bootstrap e o p-valor de Wilcoxon."""
|
|
14
|
+
y = np.asarray(y, dtype=float)
|
|
15
|
+
ea = np.abs(np.asarray(pred_a, dtype=float) - y); eb = np.abs(np.asarray(pred_b, dtype=float) - y)
|
|
16
|
+
if not (ea.shape == eb.shape == y.shape): raise ValueError('y, pred_a and pred_b must have the same shape')
|
|
17
|
+
d = eb - ea; n = len(d); rng = np.random.default_rng(seed)
|
|
18
|
+
boot = np.array([d[rng.integers(0, n, n)].mean() for _ in range(replicas)])
|
|
19
|
+
lo, hi = np.percentile(boot, [100*(1 - level)/2, 100*(1 + level)/2])
|
|
20
|
+
p = float(wilcoxon(ea, eb).pvalue) if np.any(d != 0) else 1.0
|
|
21
|
+
return {'mae_a': ea.mean(), 'mae_b': eb.mean(), 'difference': d.mean(), 'ci_low': lo, 'ci_high': hi,
|
|
22
|
+
'level': level, 'wilcoxon_p': p, 'n': n}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bgnx
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: BGNX: a framework for travel time prediction (early alpha: evaluation utilities).
|
|
5
|
+
Author: BGNX Project
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: travel time,ETA,transportation,evaluation,machine learning
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: numpy>=1.22
|
|
17
|
+
Requires-Dist: scipy>=1.8
|
|
18
|
+
Provides-Extra: torch
|
|
19
|
+
Requires-Dist: torch>=2.0; extra == "torch"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# BGNX
|
|
23
|
+
|
|
24
|
+
**BGNX** is a framework for travel time prediction, under development.
|
|
25
|
+
|
|
26
|
+
This early alpha (0.0.x) ships only general evaluation utilities. The models and the full documentation will be
|
|
27
|
+
released with the accompanying publications.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install bgnx # metrics and paired comparison
|
|
31
|
+
pip install "bgnx[torch]" # + CPU/GPU device helper
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import numpy as np
|
|
36
|
+
from bgnx import metrics, paired_comparison
|
|
37
|
+
|
|
38
|
+
y = np.array([10.0, 12.5, 30.0, 7.0]) # observed durations (minutes)
|
|
39
|
+
pa = np.array([11.0, 12.0, 27.0, 8.0]) # model A
|
|
40
|
+
pb = np.array([ 9.0, 15.0, 25.0, 9.5]) # model B
|
|
41
|
+
|
|
42
|
+
print(metrics(y, pa)) # MAE, MedAE, MAPE, MARE, RMSLE, R2, EV
|
|
43
|
+
print(paired_comparison(y, pa, pb)) # MAE difference (B - A), bootstrap 95% CI, Wilcoxon p-value
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`paired_comparison` compares two models on the **same** observations: the 95% interval of the MAE difference comes
|
|
47
|
+
from a paired bootstrap (resampling observations), and the paired absolute errors are compared with the Wilcoxon
|
|
48
|
+
signed-rank test.
|
|
49
|
+
|
|
50
|
+
License: MIT.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
bgnx/__init__.py,sha256=xrx7dDb0LMZL5uC6zWNOhoclXJUBoNi7Ti1ldH1xZ-s,343
|
|
2
|
+
bgnx/device.py,sha256=B50vIhmoBQpUBqoERUJ6UbYgBWEfq5fNKS5AbWMH-V4,2879
|
|
3
|
+
bgnx/metrics.py,sha256=rkXbfur2T72a6vV4HFsaSlLZbntryfwvDb1H6jVEZ00,949
|
|
4
|
+
bgnx/stats.py,sha256=pVUQ6XH5242wpeB1AlpwyQruVWN3eEu_Sjdz3S2VQSQ,1378
|
|
5
|
+
bgnx-0.0.1.dist-info/licenses/LICENSE,sha256=sWcrjQfZ83woHz_3zPw3Djxzj86cdOv2GCKRHoLpFNY,1069
|
|
6
|
+
bgnx-0.0.1.dist-info/METADATA,sha256=kkYAXsghHNIgMdlTfQtpvQOiV7RXxqZuPfinPy-7KwM,1828
|
|
7
|
+
bgnx-0.0.1.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
8
|
+
bgnx-0.0.1.dist-info/top_level.txt,sha256=YONYQUA389AY3UKVxSIRF-x_0BKqKg-lv81j8mvpX3A,5
|
|
9
|
+
bgnx-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BGNX Project
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bgnx
|