Download model/vrba.py from OneScience-Group/vRBA: direct link, hf CLI and curl.
- Browser
- Download file 2.26 kB
-
https://huggingface.co/OneScience-Group/vRBA/resolve/main/model/vrba.py
- Command line
-
hf download hf://OneScience-Group/vRBA/model/vrba.py
-
curl -L -o vrba.py https://huggingface.co/OneScience-Group/vRBA/resolve/main/model/vrba.py
2.26 kB
| """Independent DeepONet and exponential vRBA implementation from the paper.""" | |
| import math | |
| import torch | |
| from torch import nn | |
| class VRBADeepONet(nn.Module): | |
| def __init__(self, sensors=200, width=100, hidden_layers=4, latent_dim=100): | |
| super().__init__() | |
| def network(inputs): | |
| layers = [] | |
| for _ in range(hidden_layers): | |
| layers.extend([nn.Linear(inputs, width), nn.GELU()]) | |
| inputs = width | |
| layers.append(nn.Linear(width, latent_dim)) | |
| return nn.Sequential(*layers) | |
| self.branch = network(sensors) | |
| self.trunk = network(1) | |
| def forward(self, pressure, time): | |
| """Normalized pressure [B,M], normalized time [N,1] -> radius [B,N].""" | |
| return self.branch(pressure) @ self.trunk(time).transpose(0, 1) | |
| class ExponentialVRBA: | |
| """Eqs. 19, 40--44: detached EMA weights and function marginal sampling. | |
| phi mixes the max-normalized exponential tilt with a uniform floor. | |
| The exponential divided by its maximum is evaluated as exp((r-rmax)/eps). | |
| """ | |
| def __init__(self, functions, points, device, eta=0.1, gamma=0.99, | |
| phi=0.9, c=1.0, initial_weight=1.0): | |
| self.weights = torch.full((functions, points), initial_weight, device=device) | |
| self.eta, self.gamma, self.phi, self.c = eta, gamma, phi, c | |
| def probabilities(self): | |
| scores = self.weights.sum(dim=1) | |
| return scores / scores.sum() | |
| def update(self, indices, residual, step): | |
| r = residual.detach().abs() | |
| maximum = r.amax(dim=1, keepdim=True) | |
| epsilon = self.c * maximum / math.log(step + 2.0) | |
| # Zero residual -> uniform tilt. Numerical floor does not add temperature. | |
| safe = epsilon.clamp_min(torch.finfo(r.dtype).tiny) | |
| tilt = torch.exp((r - maximum) / safe) | |
| # Eq. 14 with q=tilt/sum(tilt), p_u=1/N and eta*=eta/max(q). | |
| # Thus p_u/max(q)=mean(tilt); using a constant 1 here changes Eq. 14. | |
| tilt = self.phi * tilt + (1.0 - self.phi) * tilt.mean(dim=1, keepdim=True) | |
| updated = self.gamma * self.weights[indices] + self.eta * tilt | |
| self.weights[indices] = updated | |
| return updated | |