Feature Extraction
Transformers
Safetensors
PyTorch
reve
eeg
neuroscience
foundation-model
custom_code
Eval Results (legacy)
Instructions to use brain-bzh/reve-base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use brain-bzh/reve-base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="brain-bzh/reve-base", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("brain-bzh/reve-base", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Rollback the add_time_patch method
Browse files- modeling_reve.py +69 -7
modeling_reve.py
CHANGED
|
@@ -217,16 +217,36 @@ class Learnable4DPE(nn.Module):
|
|
| 217 |
|
| 218 |
|
| 219 |
class FourierEmb4D(nn.Module):
|
| 220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
super().__init__()
|
| 222 |
self.dimension = dimension
|
| 223 |
self.freqs = freqs
|
| 224 |
self.increment_time = increment_time
|
| 225 |
self.margin = margin
|
| 226 |
|
| 227 |
-
def forward(self, positions_):
|
| 228 |
positions = positions_.clone()
|
| 229 |
-
positions[
|
| 230 |
input_shape = positions.shape
|
| 231 |
batch_dims = list(input_shape[:-1])
|
| 232 |
|
|
@@ -241,26 +261,68 @@ class FourierEmb4D(nn.Module):
|
|
| 241 |
p_z = 2 * math.pi * freqs_z / width
|
| 242 |
p_w = 2 * math.pi * freqs_w / width
|
| 243 |
positions = positions[..., None, None, None, None, :]
|
| 244 |
-
loc =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
batch_dims.append(-1)
|
| 246 |
loc = loc.view(batch_dims)
|
| 247 |
|
| 248 |
half_dim = self.dimension // 2
|
| 249 |
current_dim = loc.shape[-1]
|
| 250 |
-
|
| 251 |
-
# FIX: Safe slicing logic
|
| 252 |
if current_dim != half_dim:
|
| 253 |
if current_dim > half_dim:
|
| 254 |
loc = loc[..., :half_dim]
|
| 255 |
else:
|
| 256 |
raise ValueError(
|
| 257 |
f"Input dimension ({current_dim}) is too small for target "
|
| 258 |
-
f"embedding dimension ({self.dimension}). Expected at least {half_dim}."
|
| 259 |
)
|
| 260 |
|
| 261 |
emb = torch.cat([torch.cos(loc), torch.sin(loc)], dim=-1)
|
| 262 |
return emb
|
| 263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
|
| 265 |
def patch_embedding(embed_dim, patch_size):
|
| 266 |
to_patch_embedding = nn.Sequential(nn.Linear(patch_size, embed_dim))
|
|
|
|
| 217 |
|
| 218 |
|
| 219 |
class FourierEmb4D(nn.Module):
|
| 220 |
+
"""
|
| 221 |
+
Fourier positional embedding for 4D positions (x, y, z, t).
|
| 222 |
+
This version allows for a reduced number of frequencies (n_freqs),
|
| 223 |
+
and ensures the output embedding has the specified dimension.
|
| 224 |
+
|
| 225 |
+
Parameters
|
| 226 |
+
----------
|
| 227 |
+
dimension : int
|
| 228 |
+
The dimension of the output embedding. Must be an even number.
|
| 229 |
+
freqs : int
|
| 230 |
+
The number of frequencies to use for the Fourier embedding.
|
| 231 |
+
increment_time : float, optional
|
| 232 |
+
The time increment to scale the time dimension. Default is 0.1.
|
| 233 |
+
margin : float, optional
|
| 234 |
+
The margin to add to the position coordinates to avoid boundary issues. Default is 0.4.
|
| 235 |
+
|
| 236 |
+
"""
|
| 237 |
+
|
| 238 |
+
def __init__(
|
| 239 |
+
self, dimension: int, freqs: int, increment_time=0.1, margin: float = 0.4
|
| 240 |
+
):
|
| 241 |
super().__init__()
|
| 242 |
self.dimension = dimension
|
| 243 |
self.freqs = freqs
|
| 244 |
self.increment_time = increment_time
|
| 245 |
self.margin = margin
|
| 246 |
|
| 247 |
+
def forward(self, positions_: torch.Tensor) -> torch.Tensor:
|
| 248 |
positions = positions_.clone()
|
| 249 |
+
positions[:, :, -1] *= self.increment_time
|
| 250 |
input_shape = positions.shape
|
| 251 |
batch_dims = list(input_shape[:-1])
|
| 252 |
|
|
|
|
| 261 |
p_z = 2 * math.pi * freqs_z / width
|
| 262 |
p_w = 2 * math.pi * freqs_w / width
|
| 263 |
positions = positions[..., None, None, None, None, :]
|
| 264 |
+
loc = (
|
| 265 |
+
positions[..., 0] * p_x
|
| 266 |
+
+ positions[..., 1] * p_y
|
| 267 |
+
+ positions[..., 2] * p_z
|
| 268 |
+
+ positions[..., 3] * p_w
|
| 269 |
+
)
|
| 270 |
batch_dims.append(-1)
|
| 271 |
loc = loc.view(batch_dims)
|
| 272 |
|
| 273 |
half_dim = self.dimension // 2
|
| 274 |
current_dim = loc.shape[-1]
|
|
|
|
|
|
|
| 275 |
if current_dim != half_dim:
|
| 276 |
if current_dim > half_dim:
|
| 277 |
loc = loc[..., :half_dim]
|
| 278 |
else:
|
| 279 |
raise ValueError(
|
| 280 |
f"Input dimension ({current_dim}) is too small for target "
|
| 281 |
+
f"embedding dimension ({self.dimension}). Expected at least {half_dim}."
|
| 282 |
)
|
| 283 |
|
| 284 |
emb = torch.cat([torch.cos(loc), torch.sin(loc)], dim=-1)
|
| 285 |
return emb
|
| 286 |
|
| 287 |
+
@classmethod
|
| 288 |
+
def add_time_patch(cls, pos: torch.Tensor, num_patches: int) -> torch.Tensor:
|
| 289 |
+
"""
|
| 290 |
+
Expand the position tensor by adding a time dimension, handling batched data.
|
| 291 |
+
|
| 292 |
+
Parameters
|
| 293 |
+
----------
|
| 294 |
+
pos : torch.Tensor
|
| 295 |
+
Input tensor of shape (B, C, 3), where B is the batch size,
|
| 296 |
+
C is the number of channels, and 3 represents x, y, z.
|
| 297 |
+
num_patches : int
|
| 298 |
+
The number of time patches.
|
| 299 |
+
|
| 300 |
+
Returns
|
| 301 |
+
-------
|
| 302 |
+
torch.Tensor
|
| 303 |
+
Output tensor of shape (B, C * num_patches, 4), where each position is repeated with each time value.
|
| 304 |
+
"""
|
| 305 |
+
batch, nchans, _ = pos.shape
|
| 306 |
+
# Repeat each position for each time step
|
| 307 |
+
pos_repeated = pos.unsqueeze(2).repeat(
|
| 308 |
+
1, 1, num_patches, 1
|
| 309 |
+
) # Shape: (batch, nchans, num_patches, 3)
|
| 310 |
+
# Generate time values with the specified increment
|
| 311 |
+
time_values = torch.arange(
|
| 312 |
+
0, num_patches, 1, device=pos.device
|
| 313 |
+
).float() # Shape: (num_patches,)
|
| 314 |
+
time_values = time_values.view(1, 1, num_patches, 1).expand(
|
| 315 |
+
batch, nchans, num_patches, 1
|
| 316 |
+
) # (batch, nchans, num_patches, 1)
|
| 317 |
+
# Concatenate the repeated positions with the time values along the last dimension
|
| 318 |
+
pos_with_time = torch.cat(
|
| 319 |
+
(pos_repeated, time_values), dim=-1
|
| 320 |
+
) # Shape: (batch, nchans, num_patches, 4)
|
| 321 |
+
# Reshape to (batch, nchans * num_patches, 4)
|
| 322 |
+
pos_with_time = pos_with_time.view(batch, nchans * num_patches, 4)
|
| 323 |
+
|
| 324 |
+
return pos_with_time
|
| 325 |
+
|
| 326 |
|
| 327 |
def patch_embedding(embed_dim, patch_size):
|
| 328 |
to_patch_embedding = nn.Sequential(nn.Linear(patch_size, embed_dim))
|