ManmohanSharma commited on
Commit
986e37d
·
verified ·
1 Parent(s): 48532fb

Upload code/model.py

Browse files
Files changed (1) hide show
  1. code/model.py +117 -0
code/model.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+
5
+ import torch
6
+ from torch import nn
7
+
8
+
9
+ def fourier_loglam(loglam: torch.Tensor, n_freq: int = 32) -> torch.Tensor:
10
+ # Center roughly around optical wavelengths to improve conditioning.
11
+ x = loglam - math.log(6000.0)
12
+ freqs = torch.logspace(0.0, math.log10(128.0), n_freq, device=loglam.device, dtype=loglam.dtype)
13
+ angles = x.unsqueeze(-1) * freqs
14
+ return torch.cat([torch.sin(angles), torch.cos(angles)], dim=-1)
15
+
16
+
17
+ class NativeSpecZMAE(nn.Module):
18
+ def __init__(
19
+ self,
20
+ feature_dim: int = 6,
21
+ target_aux_dim: int = 4,
22
+ d_model: int = 256,
23
+ nhead: int = 8,
24
+ encoder_layers: int = 4,
25
+ decoder_layers: int = 3,
26
+ dim_feedforward: int | None = None,
27
+ dropout: float = 0.1,
28
+ fourier_freqs: int = 32,
29
+ z_bins: int = 64,
30
+ y_min: float = 0.0,
31
+ y_max: float = math.log1p(6.0),
32
+ ):
33
+ super().__init__()
34
+ self.fourier_freqs = fourier_freqs
35
+ self.y_min = y_min
36
+ self.y_max = y_max
37
+ self.z_bins = z_bins
38
+ pos_dim = fourier_freqs * 2
39
+ ff = dim_feedforward or d_model * 4
40
+
41
+ self.input_proj = nn.Sequential(
42
+ nn.Linear(feature_dim + pos_dim, d_model),
43
+ nn.LayerNorm(d_model),
44
+ nn.GELU(),
45
+ nn.Linear(d_model, d_model),
46
+ )
47
+ self.target_proj = nn.Sequential(
48
+ nn.Linear(target_aux_dim + pos_dim, d_model),
49
+ nn.LayerNorm(d_model),
50
+ nn.GELU(),
51
+ nn.Linear(d_model, d_model),
52
+ )
53
+ self.cls = nn.Parameter(torch.randn(1, 1, d_model) * 0.02)
54
+ self.z_query = nn.Parameter(torch.randn(1, 1, d_model) * 0.02)
55
+
56
+ enc_layer = nn.TransformerEncoderLayer(
57
+ d_model=d_model,
58
+ nhead=nhead,
59
+ dim_feedforward=ff,
60
+ dropout=dropout,
61
+ batch_first=True,
62
+ norm_first=True,
63
+ activation="gelu",
64
+ )
65
+ self.encoder = nn.TransformerEncoder(enc_layer, num_layers=encoder_layers)
66
+ dec_layer = nn.TransformerDecoderLayer(
67
+ d_model=d_model,
68
+ nhead=nhead,
69
+ dim_feedforward=ff,
70
+ dropout=dropout,
71
+ batch_first=True,
72
+ norm_first=True,
73
+ activation="gelu",
74
+ )
75
+ self.decoder = nn.TransformerDecoder(dec_layer, num_layers=decoder_layers)
76
+ self.rec_head = nn.Sequential(nn.LayerNorm(d_model), nn.Linear(d_model, d_model // 2), nn.GELU(), nn.Linear(d_model // 2, 1))
77
+ self.z_head = nn.Sequential(nn.LayerNorm(d_model * 2), nn.Linear(d_model * 2, d_model), nn.GELU(), nn.Linear(d_model, 2))
78
+ self.z_bin_head = nn.Sequential(nn.LayerNorm(d_model * 2), nn.Linear(d_model * 2, d_model), nn.GELU(), nn.Linear(d_model, z_bins))
79
+
80
+ def forward(
81
+ self,
82
+ enc_features: torch.Tensor,
83
+ enc_loglam: torch.Tensor,
84
+ enc_padding: torch.Tensor,
85
+ target_loglam: torch.Tensor,
86
+ target_aux: torch.Tensor,
87
+ ) -> dict[str, torch.Tensor]:
88
+ bsz = enc_features.shape[0]
89
+ enc_pos = fourier_loglam(enc_loglam, self.fourier_freqs)
90
+ tokens = self.input_proj(torch.cat([enc_features, enc_pos], dim=-1))
91
+ cls = self.cls.expand(bsz, -1, -1)
92
+ z_query = self.z_query.expand(bsz, -1, -1)
93
+ memory_in = torch.cat([cls, z_query, tokens], dim=1)
94
+ special_padding = torch.zeros((bsz, 2), dtype=torch.bool, device=enc_padding.device)
95
+ memory_padding = torch.cat([special_padding, enc_padding], dim=1)
96
+ memory = self.encoder(memory_in, src_key_padding_mask=memory_padding)
97
+
98
+ cls_out = memory[:, 0]
99
+ z_out = memory[:, 1]
100
+ z_feat = torch.cat([z_out, cls_out], dim=-1)
101
+ z_params = self.z_head(z_feat)
102
+ z_bins = self.z_bin_head(z_feat)
103
+
104
+ tgt_pos = fourier_loglam(target_loglam, self.fourier_freqs)
105
+ tgt = self.target_proj(torch.cat([target_aux, tgt_pos], dim=-1))
106
+ decoded = self.decoder(tgt=tgt, memory=memory, memory_key_padding_mask=memory_padding)
107
+ rec = self.rec_head(decoded).squeeze(-1)
108
+ return {
109
+ "rec": rec,
110
+ "y_mu": z_params[:, 0],
111
+ "y_logvar": torch.clamp(z_params[:, 1], -8.0, 4.0),
112
+ "z_bin_logits": z_bins,
113
+ }
114
+
115
+ def y_to_bin(self, y: torch.Tensor) -> torch.Tensor:
116
+ scaled = (y - self.y_min) / max(self.y_max - self.y_min, 1e-6)
117
+ return torch.clamp((scaled * self.z_bins).long(), 0, self.z_bins - 1)