PeizhaoEdinburgh commited on
Commit
97fd768
·
verified ·
1 Parent(s): bc46f19

Upload standalone NLOS model, inference code, and verified package

Browse files
Files changed (11) hide show
  1. .gitattributes +0 -34
  2. .gitignore +4 -0
  3. README.md +157 -1
  4. SHA256SUMS +10 -0
  5. best.pt +3 -0
  6. config.json +19 -0
  7. inference.py +64 -0
  8. model.py +148 -0
  9. preprocess_stats.json +7 -0
  10. requirements.txt +4 -0
  11. verification.json +16 -0
.gitattributes CHANGED
@@ -1,35 +1 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
  *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  *.pt filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .cache/
README.md CHANGED
@@ -1,3 +1,159 @@
1
  ---
2
- license: mit
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: pytorch
3
+ tags:
4
+ - lidar
5
+ - nlos
6
+ - binary-classification
7
+ - histogram
8
+ - pytorch
9
+ datasets:
10
+ - PeizhaoEdinburgh/Occlusion_Based_NLOS
11
  ---
12
+
13
+ # Occlusion-Based NLOS Model
14
+
15
+ Standalone PyTorch implementation and checkpoint for binary classification of
16
+ 32 × 32 × 64 histograms. This package includes the complete inference architecture,
17
+ weights, and saved preprocessing statistics. It does not require the original
18
+ `lidarx` repository and is not a Transformers `AutoModel` package.
19
+
20
+ ## Model
21
+
22
+ - Architecture: `HistCoarseMultiScaleMLP`; 549,641 parameters.
23
+ - Multiscale coarse histogram projections (32×8×8, 16×8×8, 32×4×4), global
24
+ statistics, temporal statistics, and spatial projections.
25
+ - Batch normalization, a 128-dimensional projection, gated residual layers,
26
+ and a 128→64→1 classification head; SiLU activation and dropout 0.2.
27
+ - Output: one logit; sigmoid produces the positive-class score.
28
+ - Threshold: 0.5. Class 0 is negative; class 1 is positive.
29
+ - `best.pt` contains the original state dictionary, training configuration,
30
+ preprocessing statistics, selected epoch, and validation loss.
31
+
32
+ The precise physical definition of positive/negative and histogram timing/range
33
+ units require author documentation. This package preserves the original labels.
34
+
35
+ ## Files
36
+
37
+ | File | Purpose |
38
+ |---|---|
39
+ | `best.pt` | Original checkpoint, unchanged |
40
+ | `model.py` | Architecture and feature extraction |
41
+ | `inference.py` | Input validation, preprocessing, model loading, and prediction CLI |
42
+ | `config.json` | Inference configuration and class labels |
43
+ | `preprocess_stats.json` | Saved normalization statistics |
44
+ | `requirements.txt` | Runtime dependencies |
45
+ | `verification.json` | Original-versus-standalone parity results and tested versions |
46
+ | `SHA256SUMS` | Integrity hashes for package files |
47
+
48
+ ## Local inference
49
+
50
+ Use Python 3.10 or newer. Install a PyTorch build suitable for your hardware if
51
+ needed, then install the remaining requirements:
52
+
53
+ ```bash
54
+ python -m pip install -r requirements.txt
55
+ python inference.py /path/to/sample.h5
56
+ # Optional CUDA inference:
57
+ python inference.py /path/to/sample.h5 --device cuda
58
+ ```
59
+
60
+ The HDF5 key must be `stamped_histogram`, with raw shape `(32, 32, 64)` in
61
+ `(height, width, time_bin)` order. Values must be finite, nonnegative counts.
62
+ Do not pass already normalized data. No test-time augmentation is applied.
63
+ The output JSON contains the logit, positive probability, numeric label, and label name.
64
+
65
+ From Python, with this folder on the Python import path:
66
+
67
+ ```python
68
+ import h5py
69
+ from inference import load_model, predict
70
+
71
+ model, config, stats = load_model()
72
+ with h5py.File("sample.h5", "r") as f:
73
+ result = predict(f["stamped_histogram"][()], model, config, stats)
74
+ print(result)
75
+ ```
76
+
77
+ ## Downloading from Hugging Face
78
+
79
+ Download this model package from
80
+ [`PeizhaoEdinburgh/Occlusion_Based_NLOS_model`](https://huggingface.co/PeizhaoEdinburgh/Occlusion_Based_NLOS_model).
81
+
82
+ ```python
83
+ from huggingface_hub import snapshot_download
84
+
85
+ folder = snapshot_download(
86
+ repo_id="PeizhaoEdinburgh/Occlusion_Based_NLOS_model",
87
+ repo_type="model",
88
+ # revision="COMMIT_HASH", # Pin a published commit for reproducibility.
89
+ )
90
+ print(folder)
91
+ ```
92
+
93
+ Run `python /downloaded/folder/inference.py /path/to/sample.h5`. The downloaded
94
+ Python files execute locally, so review the source before running them.
95
+
96
+ ## Exact preprocessing
97
+
98
+ 1. Cast raw counts to NumPy float32.
99
+ 2. Compute the total using float64 accumulation. For a positive total, multiply
100
+ all bins by `10000 / total`; an all-zero histogram remains zero at this step.
101
+ 3. Apply `log1p`.
102
+ 4. Subtract `0.10141183639534776` and divide by `0.22149132767394814`.
103
+ 5. Transpose to `(64, 32, 32)` and add batch/channel axes: `(B, 1, 64, 32, 32)`.
104
+
105
+ The original checkpoint also records `pixel_photon_count` and `count_power`;
106
+ those settings are inactive for this preprocessing mode.
107
+
108
+ ## Training and recorded evaluation
109
+
110
+ Source run:
111
+ `20260726_212202_tmf8829_36noise_seed_lhs_plus30_36_global_log_count_coarse_multiscale_h128_d4_aug_standard_hist_coarse_multiscale_mlp`.
112
+
113
+ Training used the synthetic dataset with 26,600 training, 5,700 validation,
114
+ and 5,700 test samples, seed 42, batch size 64, learning rate 0.001,
115
+ weight decay 0.0001, and D4 spatial augmentation. The selected checkpoint is
116
+ from epoch 50, with the lowest run validation loss, **0.3138319095**.
117
+ No real experimental samples were used for training according to the run artifacts.
118
+
119
+ | Evaluation | Recorded result |
120
+ |---|---:|
121
+ | Synthetic test accuracy | 0.8626316 |
122
+ | Synthetic test precision | 0.8627589 |
123
+ | Synthetic test recall | 0.8624561 |
124
+ | Synthetic test F1 | 0.8626075 |
125
+ | Synthetic test ROC-AUC | 0.9465309 |
126
+ | Experimental groups 1–5 | 88/100 correct |
127
+ | Additional left/right/long/short groups | 68/80 correct |
128
+ | Combined experimental accuracy | 156/180 = 86.67% |
129
+
130
+ Metrics above are historical artifacts, not newly recomputed benchmark scores.
131
+ “Best” means lowest validation loss within this run, not best across all models.
132
+ Experimental data use during model selection has not been audited. The synthetic
133
+ split does not establish independence between related clean/noisy scenes.
134
+
135
+ ## Verification
136
+
137
+ `verification.json` records exact CPU agreement with the original implementation
138
+ for preprocessing and logits on all 180 experimental samples and six synthetic
139
+ samples spanning both labels and clean/noise_1/noise_36 conditions. Boundary
140
+ checks cover zero counts, constant counts, wrong shape, negative counts, and NaNs.
141
+
142
+ ```bash
143
+ sha256sum --check SHA256SUMS
144
+ ```
145
+
146
+ ## Intended use and limitations
147
+
148
+ Research on NLOS histogram classification. Generalization to different sensors,
149
+ scene geometry, or timing calibration is not established. Probability outputs
150
+ have not been shown to be calibrated. The original checkpoint contains provenance
151
+ paths that are not used by the standalone loader.
152
+
153
+ ## License and attribution
154
+
155
+ A license for these model weights and source code has not been selected. The
156
+ associated dataset's MIT metadata does not automatically license this model.
157
+ Author attribution and a paper citation have not been supplied.
158
+
159
+ The card follows the [Hugging Face model card format](https://huggingface.co/docs/hub/model-cards).
SHA256SUMS ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ 4009e8f5faf67ca3607a646c9b12350d8237e344e6853c59bf9dbad697db3952 .gitattributes
2
+ 3e7f345273a9999a6c5e379f8418d7bbc46b7bee5899436384b03bfde7a4e044 .gitignore
3
+ 46b438bea76f30462c2164095addfed08cbeb27cec8f856e9be3e0b9767f0fc5 README.md
4
+ 6e6b8bf4adbd61f7cdda117498c916c9c098d9a49ef0edecb224a4cac8690f5d best.pt
5
+ 543bfb9a13bfdfde410ed42116267cb8b291c1dfd69f664d214638eca6057526 config.json
6
+ a8a513e9231546bc0b64612673677a466e562a0e8eccafe6b040c042a589069f inference.py
7
+ 52b036003ee5f5a0d4b62f66f5281e60f7775cfa95f003f588c77195272ab240 model.py
8
+ db61d5a67ecfc6fea45be741ea0e185d2add1d7a30c77d197569371a18489ddf preprocess_stats.json
9
+ 0abfce5b440789fe8c39e170023071816ad44e9fa899f8f1e71b164da382d0c7 requirements.txt
10
+ 0a3fe2f23144ec52342a3c6096ad8e8646256e6260f2a0a4cb94fbf09801569b verification.json
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6e6b8bf4adbd61f7cdda117498c916c9c098d9a49ef0edecb224a4cac8690f5d
3
+ size 2236504
config.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architecture": "HistCoarseMultiScaleMLP",
3
+ "hidden_features": 128,
4
+ "dropout": 0.2,
5
+ "input_shape": [
6
+ 32,
7
+ 32,
8
+ 64
9
+ ],
10
+ "h5_key": "stamped_histogram",
11
+ "threshold": 0.5,
12
+ "id2label": {
13
+ "0": "negative",
14
+ "1": "positive"
15
+ },
16
+ "epoch": 50,
17
+ "validation_loss": 0.3138319095184928,
18
+ "parameters": 549641
19
+ }
inference.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Inference on raw (height, width, time-bin) HDF5 histograms."""
2
+ import argparse
3
+ import json
4
+ from pathlib import Path
5
+
6
+ import h5py
7
+ import numpy as np
8
+ import torch
9
+ from model import HistCoarseMultiScaleMLP
10
+
11
+
12
+ def preprocess(histogram, stats):
13
+ data = np.asarray(histogram, dtype=np.float32)
14
+ if data.shape != (32, 32, 64):
15
+ raise ValueError(f'Expected (32, 32, 64), got {data.shape}')
16
+ if not np.isfinite(data).all() or (data < 0).any():
17
+ raise ValueError('Histogram counts must be finite and nonnegative')
18
+ if stats['mode'] != 'photon_count_10000_log1p_standardize':
19
+ raise ValueError('Unsupported preprocessing mode')
20
+ total = float(data.sum(dtype=np.float64))
21
+ if total > 0:
22
+ data = data * (10000.0 / total)
23
+ data = np.log1p(data)
24
+ data = (data - stats['mean']) / max(stats['std'], 1e-6)
25
+ return torch.from_numpy(np.transpose(data, (2, 0, 1)).copy()).unsqueeze(0).unsqueeze(0)
26
+
27
+
28
+ def load_model(model_dir=None, device='cpu'):
29
+ root = Path(model_dir) if model_dir else Path(__file__).resolve().parent
30
+ config = json.loads((root / 'config.json').read_text())
31
+ stats = json.loads((root / 'preprocess_stats.json').read_text())
32
+ checkpoint = torch.load(root / 'best.pt', map_location='cpu', weights_only=True)
33
+ if stats != checkpoint['preprocess_stats']:
34
+ raise ValueError('Preprocessing statistics differ from checkpoint')
35
+ model = HistCoarseMultiScaleMLP(config['hidden_features'], config['dropout'])
36
+ model.load_state_dict(checkpoint['model_state'], strict=True)
37
+ model.to(device).eval()
38
+ return model, config, stats
39
+
40
+
41
+ def predict(histogram, model, config, stats):
42
+ device = next(model.parameters()).device
43
+ with torch.inference_mode():
44
+ logit = model(preprocess(histogram, stats).to(device)).item()
45
+ probability = torch.sigmoid(torch.tensor(logit)).item()
46
+ label = int(probability >= config['threshold'])
47
+ return {'logit': logit, 'probability_positive': probability,
48
+ 'label': label, 'label_name': config['id2label'][str(label)]}
49
+
50
+
51
+ def main():
52
+ parser = argparse.ArgumentParser(description=__doc__)
53
+ parser.add_argument('histogram', type=Path)
54
+ parser.add_argument('--model-dir', type=Path, default=Path(__file__).resolve().parent)
55
+ parser.add_argument('--device', default='cpu')
56
+ args = parser.parse_args()
57
+ model, config, stats = load_model(args.model_dir, args.device)
58
+ with h5py.File(args.histogram, 'r') as f:
59
+ histogram = f[config['h5_key']][()]
60
+ print(json.dumps(predict(histogram, model, config, stats), indent=2))
61
+
62
+
63
+ if __name__ == '__main__':
64
+ main()
model.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Standalone architecture extracted from the original lidarx implementation."""
2
+ import torch
3
+ from torch import nn
4
+
5
+
6
+ def coarse_projection_features(x: torch.Tensor) -> torch.Tensor:
7
+ """Return `projection_coarse_32x8x8` features for `[B, 1, D, H, W]` tensors."""
8
+ if x.ndim != 5:
9
+ msg = f"expected input with shape [batch, channel, depth, height, width], got {x.shape}"
10
+ raise ValueError(msg)
11
+ if x.shape[1] != 1:
12
+ msg = f"expected one histogram channel, got {x.shape[1]}"
13
+ raise ValueError(msg)
14
+
15
+ x = x.squeeze(1)
16
+ depth = x.shape[1]
17
+ height = x.shape[2]
18
+ width = x.shape[3]
19
+ if depth % 32 != 0 or height % 8 != 0 or width % 8 != 0:
20
+ msg = (
21
+ "hist coarse projection requires depth divisible by 32 and "
22
+ f"height/width divisible by 8, got {(depth, height, width)}"
23
+ )
24
+ raise ValueError(msg)
25
+
26
+ global_features = torch.cat(
27
+ [
28
+ x.mean(dim=(1, 2, 3), keepdim=False).unsqueeze(1),
29
+ x.std(dim=(1, 2, 3), unbiased=False, keepdim=False).unsqueeze(1),
30
+ x.amin(dim=(1, 2, 3), keepdim=False).unsqueeze(1),
31
+ x.amax(dim=(1, 2, 3), keepdim=False).unsqueeze(1),
32
+ ],
33
+ dim=1,
34
+ )
35
+ depth_features = torch.cat(
36
+ [
37
+ x.mean(dim=(2, 3)),
38
+ x.std(dim=(2, 3), unbiased=False),
39
+ ],
40
+ dim=1,
41
+ )
42
+ row_features = x.mean(dim=(1, 3))
43
+ col_features = x.mean(dim=(1, 2))
44
+ coarse = (
45
+ x.reshape(
46
+ x.shape[0],
47
+ 32,
48
+ depth // 32,
49
+ 8,
50
+ height // 8,
51
+ 8,
52
+ width // 8,
53
+ )
54
+ .mean(dim=(2, 4, 6))
55
+ .reshape(x.shape[0], -1)
56
+ )
57
+ return torch.cat(
58
+ [global_features, depth_features, row_features, col_features, coarse],
59
+ dim=1,
60
+ )
61
+
62
+
63
+ def _coarse_grid_features(
64
+ x: torch.Tensor,
65
+ *,
66
+ depth_bins: int,
67
+ row_bins: int,
68
+ col_bins: int,
69
+ ) -> torch.Tensor:
70
+ depth = x.shape[1]
71
+ height = x.shape[2]
72
+ width = x.shape[3]
73
+ if depth % depth_bins != 0 or height % row_bins != 0 or width % col_bins != 0:
74
+ msg = (
75
+ "hist coarse grid requires dimensions divisible by requested bins, "
76
+ f"got volume {(depth, height, width)} and bins {(depth_bins, row_bins, col_bins)}"
77
+ )
78
+ raise ValueError(msg)
79
+
80
+ return (
81
+ x.reshape(
82
+ x.shape[0],
83
+ depth_bins,
84
+ depth // depth_bins,
85
+ row_bins,
86
+ height // row_bins,
87
+ col_bins,
88
+ width // col_bins,
89
+ )
90
+ .mean(dim=(2, 4, 6))
91
+ .reshape(x.shape[0], -1)
92
+ )
93
+
94
+
95
+ def multiscale_coarse_projection_features(x: torch.Tensor) -> torch.Tensor:
96
+ """Return coarse histogram features with added low-resolution context views."""
97
+ base = coarse_projection_features(x)
98
+ volume = x.squeeze(1)
99
+ depth_context = _coarse_grid_features(volume, depth_bins=16, row_bins=8, col_bins=8)
100
+ spatial_context = _coarse_grid_features(volume, depth_bins=32, row_bins=4, col_bins=4)
101
+ return torch.cat([base, depth_context, spatial_context], dim=1)
102
+
103
+
104
+ class HistCoarseMultiScaleMLP(nn.Module):
105
+ """Small supervised MLP over multi-scale coarse histogram projections.
106
+
107
+ This keeps the strong non-backbone inductive bias of the coarse-only model,
108
+ but gives the classifier both the best 32x8x8 block view and two coarser
109
+ context views before a lightweight gated residual head.
110
+ """
111
+
112
+ def __init__(self, hidden_features: int = 128, dropout: float = 0.2) -> None:
113
+ super().__init__()
114
+ bottleneck_features = max(1, hidden_features // 2)
115
+ self.input_norm = nn.LazyBatchNorm1d()
116
+ self.input_projection = nn.Sequential(
117
+ nn.LazyLinear(hidden_features),
118
+ nn.SiLU(inplace=True),
119
+ nn.Dropout(dropout),
120
+ )
121
+ self.residual = nn.Sequential(
122
+ nn.Linear(hidden_features, hidden_features),
123
+ nn.SiLU(inplace=True),
124
+ nn.Dropout(dropout),
125
+ nn.Linear(hidden_features, hidden_features),
126
+ )
127
+ self.gate = nn.Sequential(
128
+ nn.Linear(hidden_features, hidden_features),
129
+ nn.Sigmoid(),
130
+ )
131
+ self.head = nn.Sequential(
132
+ nn.LayerNorm(hidden_features),
133
+ nn.SiLU(inplace=True),
134
+ nn.Dropout(dropout),
135
+ nn.Linear(hidden_features, bottleneck_features),
136
+ nn.SiLU(inplace=True),
137
+ nn.Dropout(dropout),
138
+ nn.Linear(bottleneck_features, 1),
139
+ )
140
+
141
+ def forward_features(self, x: torch.Tensor) -> torch.Tensor:
142
+ """Return the learned 128-D representation immediately before the classifier."""
143
+ features = self.input_norm(multiscale_coarse_projection_features(x))
144
+ embedding = self.input_projection(features)
145
+ return embedding + self.gate(embedding) * self.residual(embedding)
146
+
147
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
148
+ return self.head(self.forward_features(x))
preprocess_stats.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "mode": "photon_count_10000_log1p_standardize",
3
+ "mean": 0.10141183639534776,
4
+ "std": 0.22149132767394814,
5
+ "pixel_photon_count": 1000.0,
6
+ "count_power": 0.75
7
+ }
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch>=2.5.1
2
+ numpy>=1.24
3
+ h5py>=3.8
4
+ huggingface_hub>=0.24
verification.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "samples_compared": 186,
3
+ "experimental_samples": 180,
4
+ "synthetic_samples": 6,
5
+ "preprocessing_exact_match": true,
6
+ "logits_exact_match": true,
7
+ "maximum_absolute_logit_difference": 0,
8
+ "checkpoint_sha256": "6e6b8bf4adbd61f7cdda117498c916c9c098d9a49ef0edecb224a4cac8690f5d",
9
+ "parameters": 549641,
10
+ "validation_device": "cpu",
11
+ "tested_versions": {
12
+ "torch": "2.5.1+cu121",
13
+ "numpy": "2.4.6",
14
+ "h5py": "3.16.0"
15
+ }
16
+ }