StableNN-Phys / model /stablenn_phys.py
zhangrenchao's picture
Upload folder using huggingface_hub
7f71cfd verified
Raw
History Blame Contribute Delete
2.16 kB
import torch
from torch import nn
class StableNNPhys(nn.Module):
def __init__(self, hidden_size=32, input_size=71, output_size=68):
super().__init__()
self.hidden_size = hidden_size
self.input_size = input_size
self.output_size = output_size
self.hidden = nn.Linear(input_size, hidden_size)
self.output = nn.Linear(hidden_size, output_size)
self.bypass = nn.Linear(input_size, output_size)
nn.init.zeros_(self.output.weight)
nn.init.zeros_(self.output.bias)
nn.init.zeros_(self.bypass.weight)
nn.init.zeros_(self.bypass.bias)
def forward(self, x):
return self.output(torch.relu(self.hidden(x))) + self.bypass(x)
def rollout(model, initial_state, surface, advection, state_mean, state_std,
tendency_mean, tendency_std, dt_seconds=10800.0):
"""Integrate advection trapezoidally, then neural physics with Euler."""
states = [initial_state]
physics = []
state = initial_state
for step in range(surface.shape[1]):
adv_now = advection[:, step]
adv_next = advection[:, min(step + 1, advection.shape[1] - 1)]
forced = state + 0.5 * dt_seconds * (adv_now + adv_next)
surface_scaled = surface[:, step] / surface.new_tensor([100.0, 100.0, 1000.0])
features = torch.cat(((forced - state_mean) / state_std, surface_scaled), dim=-1)
tendency = model(features) * tendency_std + tendency_mean
state = forced + dt_seconds * tendency
physics.append(tendency)
states.append(state)
return torch.stack(states, dim=1), torch.stack(physics, dim=1)
def rollout_loss(prediction, target, layer_mass, mode="paper"):
error = torch.abs(prediction[:, 1:] - target[:, 1:])
if mode == "paper":
weights = torch.cat((layer_mass, layer_mass), dim=-1)
weights = weights / weights.mean(dim=-1, keepdim=True)
return (error * weights[:, None]).mean()
if mode == "official_v0_3":
scale = target[:, 1:].std(dim=(0, 1), unbiased=False).clamp_min(1e-6)
return (error / scale).mean()
raise ValueError(f"Unknown loss mode: {mode}")